changeset 15316:9363fffa8b07

Merge.
author Roland Schatz <roland.schatz@oracle.com>
date Wed, 23 Apr 2014 15:48:38 +0200
parents 7f5c9079e24a (diff) 518a7f487c4f (current diff)
children 54d06efb0392 ab90641473a6
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java
diffstat 1093 files changed, 30785 insertions(+), 15059 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Apr 23 15:22:20 2014 +0200
+++ b/.hgignore	Wed Apr 23 15:48:38 2014 +0200
@@ -5,6 +5,7 @@
 ^mx/netbeans-config.zip
 ^mx/netbeans-config-libs.zip
 ^mx/eclipse-launches
+^mx/jmh
 ^mx/currentAnnotationProcessors
 ^mx/ecj.jar
 ^mx/includes
--- a/CHANGELOG.md	Wed Apr 23 15:22:20 2014 +0200
+++ b/CHANGELOG.md	Wed Apr 23 15:48:38 2014 +0200
@@ -5,9 +5,19 @@
 * Explicit support for oop compression/uncompression in high level graph.
 * LIRGenerator refactoring.
 * Explicit types for inputs (InputType enum).
+* Added graal.version system property to Graal enabled VM builds.
+* Transitioned to JDK 8 as minimum JDK level for Graal.
+* Added support for stack introspection.
 * ...
 
 ### Truffle
+* The method CallTarget#call takes now a variable number of Object arguments.
+* Support for collecting stack traces and for accessing the current frame in slow paths.
+* Renamed CallNode to DirectCallNode.
+* Renamed TruffleRuntime#createCallNode to TruffleRuntime#createDirectCallNode.
+* Added IndirectCallNode for calls with a changing CallTarget. 
+* Added TruffleRuntime#createIndirectCallNode to create an IndirectCallNode.
+* DirectCallNode#inline was renamed to DirectCallNode#forceInlining().
 * ...
 
 ## Version 0.2
@@ -21,7 +31,8 @@
 * New (tested) invariant that equality comparisons for `JavaType`/`JavaMethod`/`JavaField` values use `.equals()` instead of `==`.
 * Made graph caching compilation-local.
 * Added AllocSpy tool for analyzing allocation in Graal using the [Java Allocation Instrumenter](https://code.google.com/p/java-allocation-instrumenter/).
-* Initial support for memory arithmetic operations on x86
+* Initial support for memory arithmetic operations on x86.
+* Expanded Debug logging/dumping API to avoid allocation when this Debug facilities are not enabled.
 
 ### Truffle
 * New API `TruffleRuntime#createCallNode` to create call nodes and to give the runtime system control over its implementation.
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.nodes.cfg.*;
 
 /**
@@ -34,12 +35,12 @@
  * with the most likely path that was left out during this process. The process iteratively
  * continues until all blocks are scheduled. Additionally, it is guaranteed that all blocks of a
  * loop are scheduled before any block following the loop is scheduled.
- * 
+ *
  * The machine code generator order includes reordering of loop headers such that the backward jump
  * is a conditional jump if there is only one loop end block. Additionally, the target of loop
  * backward jumps are always marked as aligned. Aligning the target of conditional jumps does not
  * bring a measurable benefit and is therefore avoided to keep the code size small.
- * 
+ *
  * The linear scan register allocator order has an additional mechanism that prevents merge nodes
  * from being scheduled if there is at least one highly likely predecessor still unscheduled. This
  * increases the probability that the merge node and the corresponding predecessor are more closely
@@ -63,7 +64,7 @@
 
     /**
      * Computes the block order used for the linear scan register allocator.
-     * 
+     *
      * @return sorted list of blocks
      */
     public static <T extends AbstractBlock<T>> List<T> computeLinearScanOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) {
@@ -77,7 +78,7 @@
 
     /**
      * Computes the block order used for code emission.
-     * 
+     *
      * @return sorted list of blocks
      */
     public static <T extends AbstractBlock<T>> List<T> computeCodeEmittingOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) {
@@ -151,7 +152,6 @@
     /**
      * Add a linear path to the code emission order greedily following the most likely successor.
      */
-    @SuppressWarnings("unchecked")
     private static <T extends AbstractBlock<T>> void addPathToCodeEmittingOrder(T initialBlock, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) {
         T block = initialBlock;
         while (block != null) {
@@ -166,17 +166,17 @@
                 addBlock(block, order);
             }
 
-            Loop loop = block.getLoop();
+            Loop<T> loop = block.getLoop();
             if (block.isLoopEnd() && skipLoopHeader(loop.header)) {
 
                 // This is the only loop end of a skipped loop header.
                 // Add the header immediately afterwards.
-                addBlock((T) loop.header, order);
+                addBlock(loop.header, order);
 
                 // Make sure the loop successors of the loop header are aligned
                 // as they are the target
                 // of the backward jump.
-                for (Block successor : loop.header.getSuccessors()) {
+                for (T successor : loop.header.getSuccessors()) {
                     if (successor.getLoopDepth() == block.getLoopDepth()) {
                         successor.setAlign(true);
                     }
@@ -230,8 +230,8 @@
      * Skip the loop header block if the loop consists of more than one block and it has only a
      * single loop end block.
      */
-    private static boolean skipLoopHeader(AbstractBlock<?> block) {
-        return (block.isLoopHeader() && !block.isLoopEnd() && block.getLoop().loopBegin().loopEnds().count() == 1);
+    private static <T extends AbstractBlock<T>> boolean skipLoopHeader(AbstractBlock<T> block) {
+        return (block.isLoopHeader() && !block.isLoopEnd() && block.getLoop().numBackedges() == 1);
     }
 
     /**
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Wed Apr 23 15:48:38 2014 +0200
@@ -94,6 +94,43 @@
     public final boolean duringCall;
 
     /**
+     * This BCI should be used for frame states that are built for code with no meaningful BCI.
+     */
+    public static final int UNKNOWN_BCI = -5;
+
+    /**
+     * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
+     * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized,
+     * the monitor is still held.
+     */
+    public static final int UNWIND_BCI = -1;
+
+    /**
+     * The BCI for the state before starting to execute a method. Note that if the method is
+     * synchronized, the monitor is not yet held.
+     */
+    public static final int BEFORE_BCI = -2;
+
+    /**
+     * The BCI for the state after finishing the execution of a method and returning normally. Note
+     * that if the method was synchronized the monitor is already released.
+     */
+    public static final int AFTER_BCI = -3;
+
+    /**
+     * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
+     * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the
+     * monitor is already released.
+     */
+    public static final int AFTER_EXCEPTION_BCI = -4;
+
+    /**
+     * This BCI should be used for states that cannot be the target of a deoptimization, like
+     * snippet frame states.
+     */
+    public static final int INVALID_FRAMESTATE_BCI = -6;
+
+    /**
      * Creates a new frame object.
      *
      * @param caller the caller frame (which may be {@code null})
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -34,18 +34,18 @@
     /**
      * Adds the given compilation result as an implementation of the given method without making it
      * the default implementation.
-     * 
+     *
      * @param method a method to which the executable code is begin added
      * @param compResult the compilation result to be added
      * @param speculationLog the speculation log to be used
-     * @return a reference to the compiled and ready-to-run code or null if the code installation
-     *         failed
+     * @return a reference to the compiled and ready-to-run code or throws a
+     *         {@link BailoutException} if the code installation failed
      */
-    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog);
+    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode);
 
     /**
      * Sets the given compilation result as the default implementation of the given method.
-     * 
+     *
      * @param method a method to which the executable code is begin added
      * @param compResult the compilation result to be added
      * @return a reference to the compiled and ready-to-run code or null if the code installation
@@ -55,11 +55,11 @@
 
     /**
      * Returns a disassembly of some compiled code.
-     * 
+     *
      * @param compResult some compiled code
      * @param installedCode the result of installing the code in {@code compResult} or null if the
      *            code has not yet been installed
-     * 
+     *
      * @return a disassembly. This will be of length 0 if the runtime does not support
      *         disassembling.
      */
@@ -73,15 +73,14 @@
     /**
      * Minimum size of the stack area reserved for outgoing parameters. This area is reserved in all
      * cases, even when the compiled method has no regular call instructions.
-     * 
+     *
      * @return the minimum size of the outgoing parameter area in bytes
      */
     int getMinimumOutgoingSize();
 
     /**
-     * Determines if a {@link DataPatch} should be created for a given
-     * {@linkplain Constant#getPrimitiveAnnotation() annotated} primitive constant that part of a
-     * {@link CompilationResult}. A data patch is always created for an object constant.
+     * Determines if a {@link DataPatch} should be created for a given primitive constant that is
+     * part of a {@link CompilationResult}. A data patch is always created for an object constant.
      */
     boolean needsDataPatch(Constant constant);
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api.code;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -342,7 +341,7 @@
         int sigCount = sig.getParameterCount(false);
         JavaType[] argTypes;
         int argIndex = 0;
-        if (!Modifier.isStatic(method.getModifiers())) {
+        if (!method.isStatic()) {
             argTypes = new JavaType[sigCount + 1];
             argTypes[argIndex++] = method.getDeclaringClass();
         } else {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Apr 23 15:48:38 2014 +0200
@@ -368,7 +368,7 @@
      * starting address of the table. This type of table maybe generated when translating a
      * multi-way branch based on a key value from a dense value set (e.g. the {@code tableswitch}
      * JVM instruction).
-     * 
+     *
      * The table is indexed by the contiguous range of integers from {@link #low} to {@link #high}
      * inclusive.
      */
@@ -460,7 +460,7 @@
     private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();
     private final List<Mark> marks = new ArrayList<>();
 
-    private int frameSize = -1;
+    private int totalFrameSize = -1;
     private int customStackAreaOffset = -1;
     private int registerRestoreEpilogueOffset = -1;
 
@@ -525,18 +525,29 @@
     }
 
     /**
-     * Sets the frame size in bytes. Does not include the return address pushed onto the stack, if
-     * any.
-     * 
+     * The total frame size of the method in bytes. This includes the return address pushed onto the
+     * stack, if any.
+     *
+     * @return the frame size
+     */
+    public int getTotalFrameSize() {
+        assert totalFrameSize != -1 : "frame size not yet initialized!";
+        return totalFrameSize;
+    }
+
+    /**
+     * Sets the total frame size in bytes. This includes the return address pushed onto the stack,
+     * if any.
+     *
      * @param size the size of the frame in bytes
      */
-    public void setFrameSize(int size) {
-        frameSize = size;
+    public void setTotalFrameSize(int size) {
+        totalFrameSize = size;
     }
 
     /**
      * Sets the machine that has been generated by the compiler.
-     * 
+     *
      * @param code the machine code generated
      * @param size the size of the machine code
      */
@@ -548,7 +559,7 @@
     /**
      * Records a reference to the data section in the code section (e.g. to load an integer or
      * floating point constant).
-     * 
+     *
      * @param codePos the position in the code where the data reference occurs
      * @param data the data that is referenced
      */
@@ -559,7 +570,7 @@
 
     /**
      * Records a reference to an inlined constant in the code section (e.g. to load a constant oop).
-     * 
+     *
      * @param codePos the position in the code where the inlined constant occurs
      * @param data the data that is referenced
      */
@@ -570,7 +581,7 @@
 
     /**
      * Records a call in the code array.
-     * 
+     *
      * @param codePos the position of the call in the code array
      * @param size the size of the call instruction
      * @param target the being called
@@ -584,7 +595,7 @@
 
     /**
      * Records an exception handler for this method.
-     * 
+     *
      * @param codePos the position in the code that is covered by the handler
      * @param handlerPos the position of the handler
      */
@@ -594,7 +605,7 @@
 
     /**
      * Records an infopoint in the code array.
-     * 
+     *
      * @param codePos the position of the infopoint in the code array
      * @param debugInfo the debug info for the infopoint
      */
@@ -604,10 +615,10 @@
 
     /**
      * Records a custom infopoint in the code section.
-     * 
+     *
      * Compiler implementations can use this method to record non-standard infopoints, which are not
      * handled by the dedicated methods like {@link #recordCall}.
-     * 
+     *
      * @param infopoint the infopoint to record, usually a derived class from {@link Infopoint}
      */
     public void addInfopoint(Infopoint infopoint) {
@@ -621,7 +632,7 @@
 
     /**
      * Records an instruction mark within this method.
-     * 
+     *
      * @param codePos the position in the code that is covered by the handler
      * @param markId the identifier for this mark
      * @param references an array of other marks that this mark references
@@ -636,7 +647,7 @@
      * Allows a method to specify the offset of the epilogue that restores the callee saved
      * registers. Must be called iff the method is a callee saved method and stores callee registers
      * on the stack.
-     * 
+     *
      * @param registerRestoreEpilogueOffset the offset in the machine code where the epilogue begins
      */
     public void setRegisterRestoreEpilogueOffset(int registerRestoreEpilogueOffset) {
@@ -645,16 +656,6 @@
     }
 
     /**
-     * The frame size of the method in bytes.
-     * 
-     * @return the frame size
-     */
-    public int getFrameSize() {
-        assert frameSize != -1 : "frame size not yet initialized!";
-        return frameSize;
-    }
-
-    /**
      * @return the code offset of the start of the epilogue that restores all callee saved
      *         registers, or -1 if this is not a callee saved method
      */
@@ -664,7 +665,7 @@
 
     /**
      * Offset in bytes for the custom stack area (relative to sp).
-     * 
+     *
      * @return the offset in bytes
      */
     public int getCustomStackAreaOffset() {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,41 +22,66 @@
  */
 package com.oracle.graal.api.code;
 
-import com.oracle.graal.api.meta.*;
-
 /**
  * Represents a compiled instance of a method. It may have been invalidated or removed in the
  * meantime.
  */
-public interface InstalledCode {
+public class InstalledCode {
+
+    /**
+     * Raw address of this code blob.
+     */
+    private long address;
+
+    /**
+     * Counts how often the address field was reassigned.
+     */
+    private long version;
 
     /**
-     * Returns the method (if any) to which the installed code belongs.
+     * @return the address of this code blob
      */
-    ResolvedJavaMethod getMethod();
+    public final long getAddress() {
+        return address;
+    }
+
+    /**
+     * @return the address of this code blob
+     */
+    public final long getVersion() {
+        return version;
+    }
 
     /**
      * Returns the start address of this installed code if it is {@linkplain #isValid() valid}, 0
      * otherwise.
      */
-    long getStart();
+    public long getStart() {
+        return 0;
+    }
 
     /**
      * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise.
      */
-    byte[] getCode();
+    public byte[] getCode() {
+        return null;
+    }
 
     /**
      * @return true if the code represented by this object is still valid, false otherwise (may
      *         happen due to deopt, etc.)
      */
-    boolean isValid();
+    public boolean isValid() {
+        return address != 0;
+    }
 
     /**
      * Invalidates this installed code such that any subsequent invocation will throw an
      * {@link InvalidInstalledCodeException}.
      */
-    void invalidate();
+    public void invalidate() {
+        throw new UnsupportedOperationException();
+    }
 
     /**
      * Executes the installed code with a variable number of arguments.
@@ -64,5 +89,8 @@
      * @param args the array of object arguments
      * @return the value returned by the executed code
      */
-    Object executeVarargs(Object... args) throws InvalidInstalledCodeException;
+    @SuppressWarnings("unused")
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java	Wed Apr 23 15:48:38 2014 +0200
@@ -32,7 +32,7 @@
     /**
      * 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
@@ -48,7 +48,7 @@
 
     /**
      * Resolves the function pointer {@code NativeFunctionPointer} of a native function.
-     * 
+     *
      * @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
@@ -60,7 +60,7 @@
      * 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
@@ -68,26 +68,26 @@
      * @return the function handle of the native function
      * @throws UnsatisfiedLinkError if the function handle could not be resolved
      */
-    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes);
+    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class<?> returnType, Class<?>... argumentTypes);
 
     /**
      * 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 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
      */
-    NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes);
+    NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class<?> returnType, Class<?>... argumentTypes);
 
     /**
      * 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 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
@@ -95,13 +95,13 @@
      * @return the function handle of the native function
      * @throws UnsatisfiedLinkError if the function handle could not be created
      */
-    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes);
+    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class<?> returnType, Class<?>... argumentTypes);
 
     /**
      * 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 name the name of the function to be resolved
      * @param returnType the type of the return value
      * @param argumentTypes the types of the arguments
@@ -110,11 +110,11 @@
      *             {@linkplain #isDefaultLibrarySearchSupported() supported} or if the function
      *             could not be resolved
      */
-    NativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes);
+    NativeFunctionHandle getFunctionHandle(String name, Class<?> returnType, Class<?>... argumentTypes);
 
     /**
      * Creates a {@link NativeFunctionPointer} from a raw value.
-     * 
+     *
      * @param rawValue raw function pointer
      * @return {@code NativeFunctionPointer} for {@code rawValue}
      */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
  * Manages a list of unique deoptimization reasons.
  * 
  */
-public final class SpeculationLog {
+public abstract class SpeculationLog {
     private volatile Object lastFailed;
     private volatile Collection<Object> speculations;
     private Set<Object> failedSpeculations;
@@ -54,7 +54,7 @@
         return true;
     }
 
-    public Constant speculate(Object reason) {
+    protected void addSpeculation(Object reason) {
         assert maySpeculate(reason);
         if (speculations == null) {
             synchronized (this) {
@@ -64,6 +64,7 @@
             }
         }
         speculations.add(reason);
-        return Constant.forObject(reason);
     }
+
+    public abstract Constant speculate(Object reason);
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,6 @@
 package com.oracle.graal.api.code;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
-import static java.lang.reflect.Modifier.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -83,7 +81,7 @@
 
     /**
      * Derives hint information for use when generating the code for a type check instruction.
-     * 
+     *
      * @param targetType the target type of the type check
      * @param profile the profiling information available for the instruction (if any)
      * @param assumptions the object in which speculations are recorded. This is null if
@@ -151,10 +149,10 @@
     /**
      * Determines if a given type can have subtypes other than itself. This analysis is purely
      * static; no assumptions are made.
-     * 
+     *
      * @return true if {@code type} can have subtypes
      */
     public static boolean canHaveSubtype(ResolvedJavaType type) {
-        return !isFinal(getElementalType(type).getModifiers());
+        return !getElementalType(type).isFinal();
     }
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,7 @@
 /**
  * Package that defines the interface between a Java application that wants to install code and the runtime.
  * The runtime provides in implementation of the {@link com.oracle.graal.api.code.CodeCacheProvider} interface.
- * The method {@link com.oracle.graal.api.code.CodeCacheProvider#addMethod(com.oracle.graal.api.meta.ResolvedJavaMethod, CompilationResult, SpeculationLog)}
+ * The method {@link com.oracle.graal.api.code.CodeCacheProvider#addMethod(com.oracle.graal.api.meta.ResolvedJavaMethod, CompilationResult, SpeculationLog, InstalledCode)}
  * can be used to install code for a given method.
  */
 package com.oracle.graal.api.code;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/InspectedFrame.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.api.code.stack;
+
+import com.oracle.graal.api.meta.*;
+
+public interface InspectedFrame {
+
+    /**
+     * Returns the value of the local at the given index. Currently only works for object values.
+     * This value is a copy iff {@link #isVirtual(int)} is true.
+     */
+    Object getLocal(int index);
+
+    /**
+     * Returns whether the local at the given index is a virtual object, and therefore the object
+     * returned by {@link #getLocal(int)} is a copy.
+     */
+    boolean isVirtual(int index);
+
+    /**
+     * Returns true if the stack frame is a compiled stack frame and there are virtual objects
+     * anywhere in the current state of the compiled method. This can return true even if
+     * {@link #isVirtual(int)} return false for all locals.
+     */
+    boolean hasVirtualObjects();
+
+    /**
+     * This method will materialize all virtual objects, deoptimize the stack frame and make sure
+     * that subsequent execution of the deoptimized frame uses the materialized values.
+     */
+    void materializeVirtualObjects(boolean invalidateCode);
+
+    /**
+     * @return the current bytecode index
+     */
+    int getBytecodeIndex();
+
+    /**
+     * @return the current method
+     */
+    ResolvedJavaMethod getMethod();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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.api.code.stack;
+
+import com.oracle.graal.api.meta.*;
+
+public interface StackIntrospection {
+
+    /**
+     * Accesses the current stack, returning a collection of {@long InspectedFrame}s that can be
+     * used to inspect the stack frames' contents.
+     *
+     * @param initialMethods if this is non-{@code null}, then the stack trace will start at these
+     *            methods
+     * @param matchingMethods if this is non-{@code null}, then only matching stack frames are
+     *            returned
+     */
+    Iterable<InspectedFrame> getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip);
+}
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/FieldUniverse.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/FieldUniverse.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,7 +35,7 @@
     public final Map<Field, ResolvedJavaField> fields = new HashMap<>();
 
     public FieldUniverse() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             for (Field f : c.getDeclaredFields()) {
                 ResolvedJavaField field = metaAccess.lookupJavaField(f);
                 fields.put(f, field);
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/MethodUniverse.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/MethodUniverse.java	Wed Apr 23 15:48:38 2014 +0200
@@ -36,12 +36,12 @@
     public final Map<Constructor<?>, ResolvedJavaMethod> constructors = new HashMap<>();
 
     public MethodUniverse() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             for (Method m : c.getDeclaredMethods()) {
                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
                 methods.put(m, method);
             }
-            for (Constructor m : c.getDeclaredConstructors()) {
+            for (Constructor<?> m : c.getDeclaredConstructors()) {
                 constructors.put(m, metaAccess.lookupJavaConstructor(m));
             }
         }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java	Wed Apr 23 15:48:38 2014 +0200
@@ -34,8 +34,8 @@
     public static final MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess();
 
     final String name;
-    final Class returnType;
-    final Class[] parameterTypes;
+    final Class<?> returnType;
+    final Class<?>[] parameterTypes;
 
     public NameAndSignature(Method m) {
         this.name = m.getName();
@@ -61,7 +61,7 @@
     public String toString() {
         StringBuilder sb = new StringBuilder(name + "(");
         String sep = "";
-        for (Class p : parameterTypes) {
+        for (Class<?> p : parameterTypes) {
             sb.append(sep);
             sep = ", ";
             sb.append(p.getName());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestConstantReflectionProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.meta.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Tests for {@link ConstantReflectionProvider}. It assumes an implementation of the interface that
+ * actually returns non-null results for access operations that are possible, i.e., the tests will
+ * fail for an implementation that spuriously returns null (which is allowed by the specification).
+ */
+public class TestConstantReflectionProvider extends TypeUniverse {
+
+    @Test
+    public void constantEqualsTest() {
+        for (Constant c1 : constants) {
+            for (Constant c2 : constants) {
+                // test symmetry
+                assertEquals(constantReflection.constantEquals(c1, c2), constantReflection.constantEquals(c2, c1));
+                if (c1.getKind() != Kind.Object && c2.getKind() != Kind.Object) {
+                    assertEquals(c1.equals(c2), constantReflection.constantEquals(c2, c1));
+                }
+            }
+        }
+    }
+
+    @Test
+    public void readArrayLengthTest() {
+        for (Constant c : constants) {
+            Integer actual = constantReflection.readArrayLength(c);
+            if (c.getKind() != Kind.Object || c.isNull() || !snippetReflection.asObject(c).getClass().isArray()) {
+                assertNull(actual);
+            } else {
+                assertNotNull(actual);
+                int actualInt = actual;
+                assertEquals(Array.getLength(snippetReflection.asObject(c)), actualInt);
+            }
+        }
+    }
+
+    @Test
+    public void boxTest() {
+        for (Constant c : constants) {
+            Constant boxed = constantReflection.boxPrimitive(c);
+            if (c.getKind().isPrimitive()) {
+                assertTrue(boxed.getKind().isObject());
+                assertFalse(boxed.isNull());
+            }
+        }
+
+        assertEquals(Long.valueOf(42), snippetReflection.asObject(constantReflection.boxPrimitive(Constant.forLong(42))));
+        assertEquals(Integer.valueOf(666), snippetReflection.asObject(constantReflection.boxPrimitive(Constant.forInt(666))));
+        assertEquals(Byte.valueOf((byte) 123), snippetReflection.asObject(constantReflection.boxPrimitive(Constant.forByte((byte) 123))));
+        assertSame(Boolean.TRUE, snippetReflection.asObject(constantReflection.boxPrimitive(Constant.forBoolean(true))));
+
+        assertNull(constantReflection.boxPrimitive(Constant.NULL_OBJECT));
+        assertNull(constantReflection.boxPrimitive(snippetReflection.forObject("abc")));
+    }
+
+    @Test
+    public void unboxTest() {
+        for (Constant c : constants) {
+            Constant unboxed = constantReflection.unboxPrimitive(c);
+            if (unboxed != null) {
+                assertFalse(unboxed.getKind().isObject());
+            }
+        }
+
+        assertEquals(Constant.forLong(42), constantReflection.unboxPrimitive(snippetReflection.forObject(Long.valueOf(42))));
+        assertEquals(Constant.forInt(666), constantReflection.unboxPrimitive(snippetReflection.forObject(Integer.valueOf(666))));
+        assertEquals(Constant.forByte((byte) 123), constantReflection.unboxPrimitive(snippetReflection.forObject(Byte.valueOf((byte) 123))));
+        assertSame(Constant.forBoolean(true), constantReflection.unboxPrimitive(snippetReflection.forObject(Boolean.TRUE)));
+
+        assertNull(constantReflection.unboxPrimitive(Constant.NULL_OBJECT));
+        assertNull(constantReflection.unboxPrimitive(snippetReflection.forObject("abc")));
+    }
+
+    @Test
+    public void testAsJavaType() {
+        for (Constant c : constants) {
+            ResolvedJavaType type = constantReflection.asJavaType(c);
+
+            Object o = snippetReflection.asBoxedValue(c);
+            if (o instanceof Class) {
+                assertEquals(metaAccess.lookupJavaType((Class<?>) o), type);
+            } else {
+                assertNull(type);
+            }
+        }
+
+    }
+}
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaField.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaField.java	Wed Apr 23 15:48:38 2014 +0200
@@ -68,7 +68,7 @@
     @Test
     public void getDeclaringClassTest() {
         for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
-            Class expected = e.getKey().getDeclaringClass();
+            Class<?> expected = e.getKey().getDeclaringClass();
             ResolvedJavaType actual = e.getValue().getDeclaringClass();
             assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
         }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaMethod.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaMethod.java	Wed Apr 23 15:48:38 2014 +0200
@@ -48,7 +48,7 @@
     @Test
     public void getDeclaringClassTest() {
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
-            Class expected = e.getKey().getDeclaringClass();
+            Class<?> expected = e.getKey().getDeclaringClass();
             ResolvedJavaType actual = e.getValue().getDeclaringClass();
             assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
         }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Wed Apr 23 15:48:38 2014 +0200
@@ -38,7 +38,7 @@
 
     @Test
     public void getKindTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             JavaType type = metaAccess.lookupJavaType(c);
             Kind expected = Kind.fromJavaClass(c);
             Kind actual = type.getKind();
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -38,7 +38,7 @@
 
     @Test
     public void lookupJavaTypeTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             assertNotNull(type);
             assertEquals(c.getModifiers(), type.getModifiers());
@@ -51,7 +51,7 @@
 
     @Test
     public void lookupJavaMethodTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             for (Method reflect : c.getDeclaredMethods()) {
                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(reflect);
                 assertNotNull(method);
@@ -65,7 +65,7 @@
 
     @Test
     public void lookupJavaFieldTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             for (Field reflect : c.getDeclaredFields()) {
                 ResolvedJavaField field = metaAccess.lookupJavaField(reflect);
                 assertNotNull(field);
@@ -81,7 +81,7 @@
     public void lookupJavaTypeConstantTest() {
         for (Constant c : constants) {
             if (c.getKind() == Kind.Object && !c.isNull()) {
-                Object o = c.asObject();
+                Object o = snippetReflection.asObject(c);
                 ResolvedJavaType type = metaAccess.lookupJavaType(c);
                 assertNotNull(type);
                 assertTrue(type.equals(metaAccess.lookupJavaType(o.getClass())));
@@ -90,31 +90,4 @@
             }
         }
     }
-
-    @Test
-    public void constantEqualsTest() {
-        for (Constant c1 : constants) {
-            for (Constant c2 : constants) {
-                // test symmetry
-                assertEquals(constantReflection.constantEquals(c1, c2), constantReflection.constantEquals(c2, c1));
-                if (c1.getKind() != Kind.Object && c2.getKind() != Kind.Object) {
-                    assertEquals(c1.equals(c2), constantReflection.constantEquals(c2, c1));
-                }
-            }
-        }
-    }
-
-    @Test
-    public void lookupArrayLengthTest() {
-        for (Constant c : constants) {
-            Integer actual = constantReflection.lookupArrayLength(c);
-            if (c.getKind() != Kind.Object || c.isNull() || !c.asObject().getClass().isArray()) {
-                assertNull(actual);
-            } else {
-                assertNotNull(actual);
-                int actualInt = actual;
-                assertEquals(Array.getLength(c.asObject()), actualInt);
-            }
-        }
-    }
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaField.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaField.java	Wed Apr 23 15:48:38 2014 +0200
@@ -78,7 +78,7 @@
             if (isStatic(field.getModifiers())) {
                 try {
                     Object expected = field.get(null);
-                    Object actual = e.getValue().readConstantValue(null).asBoxedValue();
+                    Object actual = snippetReflection.asBoxedValue(e.getValue().readConstantValue(null));
                     assertEquals(expected, actual);
                 } catch (IllegalArgumentException | IllegalAccessException e1) {
                 }
@@ -86,7 +86,7 @@
                 try {
                     Object receiver = field.getDeclaringClass().newInstance();
                     Object expected = field.get(receiver);
-                    Object actual = e.getValue().readConstantValue(Constant.forObject(receiver)).asBoxedValue();
+                    Object actual = snippetReflection.asBoxedValue(e.getValue().readConstantValue(snippetReflection.forObject(receiver)));
                     assertEquals(expected, actual);
                 } catch (InstantiationException | IllegalArgumentException | IllegalAccessException e1) {
                 }
@@ -95,16 +95,16 @@
 
         ResolvedJavaField field = metaAccess.lookupJavaField(getClass().getDeclaredField("stringField"));
         for (Object receiver : new Object[]{this, null, new String()}) {
-            Constant value = field.readConstantValue(Constant.forObject(receiver));
+            Constant value = field.readConstantValue(snippetReflection.forObject(receiver));
             assertNull(value);
         }
 
         ResolvedJavaField constField = metaAccess.lookupJavaField(getClass().getDeclaredField("constantStringField"));
         for (Object receiver : new Object[]{this, null, new String()}) {
-            Constant value = constField.readConstantValue(Constant.forObject(receiver));
+            Constant value = constField.readConstantValue(snippetReflection.forObject(receiver));
             if (value != null) {
                 Object expected = "constantField";
-                assertTrue(value.asObject() == expected);
+                assertTrue(snippetReflection.asObject(value) == expected);
             }
         }
     }
@@ -117,7 +117,7 @@
             if (isStatic(field.getModifiers())) {
                 try {
                     Object expected = field.get(null);
-                    Object actual = e.getValue().readValue(null).asBoxedValue();
+                    Object actual = snippetReflection.asBoxedValue(e.getValue().readValue(null));
                     assertEquals(expected, actual);
                 } catch (IllegalArgumentException | IllegalAccessException e1) {
                 }
@@ -131,7 +131,7 @@
             ResolvedJavaField rf = metaAccess.lookupJavaField(f);
             Object receiver = isStatic(f.getModifiers()) ? null : testString;
             Object expected = f.get(receiver);
-            Object actual = rf.readValue(receiver == null ? null : Constant.forObject(receiver)).asBoxedValue();
+            Object actual = snippetReflection.asBoxedValue(rf.readValue(receiver == null ? null : snippetReflection.forObject(receiver)));
             assertEquals(expected, actual);
         }
     }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api.meta.test;
 
-import static java.lang.reflect.Modifier.*;
 import static org.junit.Assert.*;
 
 import java.lang.annotation.*;
@@ -52,9 +51,9 @@
             if (code == null) {
                 assertTrue(m.getCodeSize() == 0);
             } else {
-                if (isAbstract(m.getModifiers())) {
+                if (m.isAbstract()) {
                     assertTrue(code.length == 0);
-                } else if (!isNative(m.getModifiers())) {
+                } else if (!m.isNative()) {
                     assertTrue(code.length > 0);
                 }
             }
@@ -69,9 +68,9 @@
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
             ResolvedJavaMethod m = e.getValue();
             int codeSize = m.getCodeSize();
-            if (isAbstract(m.getModifiers())) {
+            if (m.isAbstract()) {
                 assertTrue(codeSize == 0);
-            } else if (!isNative(m.getModifiers())) {
+            } else if (!m.isNative()) {
                 assertTrue(codeSize > 0);
             }
         }
@@ -128,19 +127,33 @@
     }
 
     @Test
-    public void canBeStaticallyBoundTest() {
+    public void isSynchronizedTest() {
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
             ResolvedJavaMethod m = e.getValue();
-            assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers()));
+            assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
         }
         for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
             ResolvedJavaMethod m = e.getValue();
-            assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers()));
+            assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
         }
     }
 
-    private static boolean canBeStaticallyBound(int modifiers) {
-        return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) && !Modifier.isAbstract(modifiers);
+    @Test
+    public void canBeStaticallyBoundTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey()));
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey()));
+        }
+    }
+
+    private static boolean canBeStaticallyBound(Member method) {
+        int modifiers = method.getModifiers();
+        return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(method.getDeclaringClass().getModifiers())) &&
+                        !Modifier.isAbstract(modifiers);
     }
 
     private static String methodWithExceptionHandlers(String p1, Object o2) {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Wed Apr 23 15:48:38 2014 +0200
@@ -46,7 +46,7 @@
 
     @Test
     public void findInstanceFieldWithOffsetTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             Set<Field> reflectionFields = getInstanceFields(c, true);
             for (Field f : reflectionFields) {
@@ -62,7 +62,7 @@
 
     @Test
     public void isInterfaceTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             boolean expected = c.isInterface();
             boolean actual = type.isInterface();
@@ -72,7 +72,7 @@
 
     @Test
     public void isInstanceClassTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             boolean expected = !c.isArray() && !c.isPrimitive() && !c.isInterface();
             boolean actual = type.isInstanceClass();
@@ -82,7 +82,7 @@
 
     @Test
     public void isArrayTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             boolean expected = c.isArray();
             boolean actual = type.isArray();
@@ -92,7 +92,7 @@
 
     @Test
     public void getModifiersTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             int expected = c.getModifiers();
             int actual = type.getModifiers();
@@ -102,7 +102,7 @@
 
     @Test
     public void isAssignableFromTest() {
-        Class[] all = classes.toArray(new Class[classes.size()]);
+        Class<?>[] all = classes.toArray(new Class[classes.size()]);
         for (int i = 0; i < all.length; i++) {
             Class<?> c1 = all[i];
             for (int j = i; j < all.length; j++) {
@@ -123,7 +123,7 @@
     public void isInstanceTest() {
         for (Constant c : constants) {
             if (c.getKind() == Kind.Object && !c.isNull()) {
-                Object o = c.asObject();
+                Object o = snippetReflection.asObject(c);
                 Class<? extends Object> cls = o.getClass();
                 while (cls != null) {
                     ResolvedJavaType type = metaAccess.lookupJavaType(cls);
@@ -136,7 +136,7 @@
         }
     }
 
-    private static Class asExactClass(Class c) {
+    private static Class<?> asExactClass(Class<?> c) {
         if (c.isArray()) {
             if (asExactClass(c.getComponentType()) != null) {
                 return c;
@@ -151,10 +151,10 @@
 
     @Test
     public void asExactTypeTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             ResolvedJavaType exactType = type.asExactType();
-            Class expected = asExactClass(c);
+            Class<?> expected = asExactClass(c);
             if (expected == null) {
                 assertTrue("exact(" + c.getName() + ") != null", exactType == null);
             } else {
@@ -166,9 +166,9 @@
 
     @Test
     public void getSuperclassTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
-            Class expected = c.getSuperclass();
+            Class<?> expected = c.getSuperclass();
             ResolvedJavaType actual = type.getSuperclass();
             if (expected == null) {
                 assertTrue(actual == null);
@@ -181,9 +181,9 @@
 
     @Test
     public void getInterfacesTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
-            Class[] expected = c.getInterfaces();
+            Class<?>[] expected = c.getInterfaces();
             ResolvedJavaType[] actual = type.getInterfaces();
             assertEquals(expected.length, actual.length);
             for (int i = 0; i < expected.length; i++) {
@@ -192,10 +192,10 @@
         }
     }
 
-    public Class getSupertype(Class c) {
+    public Class<?> getSupertype(Class<?> c) {
         assert !c.isPrimitive();
         if (c.isArray()) {
-            Class componentType = c.getComponentType();
+            Class<?> componentType = c.getComponentType();
             if (componentType.isPrimitive() || componentType == Object.class) {
                 return Object.class;
             }
@@ -207,7 +207,7 @@
         return c.getSuperclass();
     }
 
-    public Class findLeastCommonAncestor(Class<?> c1Initial, Class<?> c2Initial) {
+    public Class<?> findLeastCommonAncestor(Class<?> c1Initial, Class<?> c2Initial) {
         if (c1Initial.isPrimitive() || c2Initial.isPrimitive()) {
             return null;
         } else {
@@ -228,14 +228,14 @@
 
     @Test
     public void findLeastCommonAncestorTest() {
-        Class[] all = classes.toArray(new Class[classes.size()]);
+        Class<?>[] all = classes.toArray(new Class[classes.size()]);
         for (int i = 0; i < all.length; i++) {
             Class<?> c1 = all[i];
             for (int j = i; j < all.length; j++) {
                 Class<?> c2 = all[j];
                 ResolvedJavaType t1 = metaAccess.lookupJavaType(c1);
                 ResolvedJavaType t2 = metaAccess.lookupJavaType(c2);
-                Class expected = findLeastCommonAncestor(c1, c2);
+                Class<?> expected = findLeastCommonAncestor(c1, c2);
                 ResolvedJavaType actual = t1.findLeastCommonAncestor(t2);
                 if (expected == null) {
                     assertTrue(actual == null);
@@ -268,7 +268,7 @@
     abstract static class Abstract4 extends Concrete3 {
     }
 
-    void checkConcreteSubtype(ResolvedJavaType type, Class expected) {
+    void checkConcreteSubtype(ResolvedJavaType type, Class<?> expected) {
         ResolvedJavaType subtype = type.findUniqueConcreteSubtype();
         if (subtype == null) {
             // findUniqueConcreteSubtype() is conservative
@@ -323,9 +323,9 @@
 
     @Test
     public void getComponentTypeTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
-            Class expected = c.getComponentType();
+            Class<?> expected = c.getComponentType();
             ResolvedJavaType actual = type.getComponentType();
             if (expected == null) {
                 assertNull(actual);
@@ -337,10 +337,10 @@
 
     @Test
     public void getArrayClassTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             if (c != void.class) {
                 ResolvedJavaType type = metaAccess.lookupJavaType(c);
-                Class expected = getArrayClass(c);
+                Class<?> expected = getArrayClass(c);
                 ResolvedJavaType actual = type.getArrayClass();
                 assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
             }
@@ -381,14 +381,14 @@
         return false;
     }
 
-    static final Map<Class, VTable> vtables = new HashMap<>();
+    static final Map<Class<?>, VTable> vtables = new HashMap<>();
 
     static class VTable {
 
         final Map<NameAndSignature, Method> methods = new HashMap<>();
     }
 
-    static synchronized VTable getVTable(Class c) {
+    static synchronized VTable getVTable(Class<?> c) {
         VTable vtable = vtables.get(c);
         if (vtable == null) {
             vtable = new VTable();
@@ -411,7 +411,7 @@
         return vtable;
     }
 
-    static Set<Method> findDeclarations(Method impl, Class c) {
+    static Set<Method> findDeclarations(Method impl, Class<?> c) {
         Set<Method> declarations = new HashSet<>();
         NameAndSignature implSig = new NameAndSignature(impl);
         if (c != null) {
@@ -424,7 +424,7 @@
             if (!c.isInterface()) {
                 declarations.addAll(findDeclarations(impl, c.getSuperclass()));
             }
-            for (Class i : c.getInterfaces()) {
+            for (Class<?> i : c.getInterfaces()) {
                 declarations.addAll(findDeclarations(impl, i));
             }
         }
@@ -438,7 +438,7 @@
 
     @Test
     public void resolveMethodTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             if (c.isInterface() || c.isPrimitive()) {
                 ResolvedJavaType type = metaAccess.lookupJavaType(c);
                 for (Method m : c.getDeclaredMethods()) {
@@ -478,7 +478,7 @@
         assertEquals(thisMethod, ucm);
     }
 
-    public static Set<Field> getInstanceFields(Class c, boolean includeSuperclasses) {
+    public static Set<Field> getInstanceFields(Class<?> c, boolean includeSuperclasses) {
         if (c.isArray() || c.isPrimitive() || c.isInterface()) {
             return Collections.emptySet();
         }
@@ -529,7 +529,7 @@
 
     @Test
     public void getInstanceFieldsTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             for (boolean includeSuperclasses : new boolean[]{true, false}) {
                 Set<Field> expected = getInstanceFields(c, includeSuperclasses);
@@ -552,7 +552,7 @@
 
     @Test
     public void getDeclaredMethodsTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             Method[] raw = c.getDeclaredMethods();
             Set<ResolvedJavaMethod> expected = new HashSet<>();
@@ -595,7 +595,7 @@
 
     @Test
     public void getAnnotationTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             for (Annotation a : c.getAnnotations()) {
                 assertEquals(a, type.getAnnotation(a.annotationType()));
@@ -605,11 +605,11 @@
 
     @Test
     public void memberClassesTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             assertEquals(c.isLocalClass(), type.isLocal());
             assertEquals(c.isMemberClass(), type.isMember());
-            Class enclc = c.getEnclosingClass();
+            Class<?> enclc = c.getEnclosingClass();
             ResolvedJavaType enclt = type.getEnclosingType();
             assertFalse(enclc == null ^ enclt == null);
             if (enclc != null) {
@@ -620,7 +620,7 @@
 
     @Test
     public void classFilePathTest() {
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
             URL path = type.getClassFilePath();
             if (type.isPrimitive() || type.isArray()) {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java	Wed Apr 23 15:48:38 2014 +0200
@@ -32,6 +32,7 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.runtime.*;
@@ -46,6 +47,7 @@
 
     public final MetaAccessProvider metaAccess;
     public final ConstantReflectionProvider constantReflection;
+    public final SnippetReflectionProvider snippetReflection;
     public final Collection<Class<?>> classes = new HashSet<>();
     public final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
     public final List<Constant> constants = new ArrayList<>();
@@ -54,6 +56,7 @@
         Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders();
         metaAccess = providers.getMetaAccess();
         constantReflection = providers.getConstantReflection();
+        snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class);
         Unsafe theUnsafe = null;
         try {
             theUnsafe = Unsafe.getUnsafe();
@@ -68,10 +71,10 @@
         }
         unsafe = theUnsafe;
 
-        Class[] initialClasses = {void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, ClassLoader.class,
+        Class<?>[] initialClasses = {void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, ClassLoader.class,
                         String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class, HashMap.class,
                         LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class};
-        for (Class c : initialClasses) {
+        for (Class<?> c : initialClasses) {
             addClass(c);
         }
         for (Field f : Constant.class.getDeclaredFields()) {
@@ -86,22 +89,24 @@
                 }
             }
         }
-        for (Class c : classes) {
+        for (Class<?> c : classes) {
             if (c != void.class && !c.isArray()) {
-                constants.add(Constant.forObject(Array.newInstance(c, 42)));
+                constants.add(snippetReflection.forObject(Array.newInstance(c, 42)));
             }
         }
-        constants.add(Constant.forObject(new ArrayList<>()));
-        constants.add(Constant.forObject(new IdentityHashMap<>()));
-        constants.add(Constant.forObject(new LinkedHashMap<>()));
-        constants.add(Constant.forObject(new TreeMap<>()));
-        constants.add(Constant.forObject(new ArrayDeque<>()));
-        constants.add(Constant.forObject(new LinkedList<>()));
-        constants.add(Constant.forObject("a string"));
-        constants.add(Constant.forObject(42));
+        constants.add(snippetReflection.forObject(new ArrayList<>()));
+        constants.add(snippetReflection.forObject(new IdentityHashMap<>()));
+        constants.add(snippetReflection.forObject(new LinkedHashMap<>()));
+        constants.add(snippetReflection.forObject(new TreeMap<>()));
+        constants.add(snippetReflection.forObject(new ArrayDeque<>()));
+        constants.add(snippetReflection.forObject(new LinkedList<>()));
+        constants.add(snippetReflection.forObject("a string"));
+        constants.add(snippetReflection.forObject(42));
+        constants.add(snippetReflection.forObject(String.class));
+        constants.add(snippetReflection.forObject(String[].class));
     }
 
-    public synchronized Class<?> getArrayClass(Class componentType) {
+    public synchronized Class<?> getArrayClass(Class<?> componentType) {
         Class<?> arrayClass = arrayClasses.get(componentType);
         if (arrayClass == null) {
             arrayClass = Array.newInstance(componentType, 0).getClass();
@@ -110,27 +115,27 @@
         return arrayClass;
     }
 
-    public static int dimensions(Class c) {
+    public static int dimensions(Class<?> c) {
         if (c.getComponentType() != null) {
             return 1 + dimensions(c.getComponentType());
         }
         return 0;
     }
 
-    private void addClass(Class c) {
+    private void addClass(Class<?> c) {
         if (classes.add(c)) {
             if (c.getSuperclass() != null) {
                 addClass(c.getSuperclass());
             }
-            for (Class sc : c.getInterfaces()) {
+            for (Class<?> sc : c.getInterfaces()) {
                 addClass(sc);
             }
-            for (Class dc : c.getDeclaredClasses()) {
+            for (Class<?> dc : c.getDeclaredClasses()) {
                 addClass(dc);
             }
             for (Method m : c.getDeclaredMethods()) {
                 addClass(m.getReturnType());
-                for (Class p : m.getParameterTypes()) {
+                for (Class<?> p : m.getParameterTypes()) {
                     addClass(p);
                 }
             }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java	Wed Apr 23 15:48:38 2014 +0200
@@ -131,7 +131,7 @@
         if (!(obj instanceof AbstractJavaProfile)) {
             return false;
         }
-        AbstractJavaProfile that = (AbstractJavaProfile) obj;
+        AbstractJavaProfile<?, ?> that = (AbstractJavaProfile<?, ?>) obj;
         if (that.notRecordedProbability != notRecordedProbability) {
             return false;
         }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractProfiledItem.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractProfiledItem.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,7 +28,7 @@
  * A profiled type that has a probability. Profiled types are naturally sorted in descending order
  * of their probabilities.
  */
-public abstract class AbstractProfiledItem<T> implements Comparable<AbstractProfiledItem>, Serializable {
+public abstract class AbstractProfiledItem<T> implements Comparable<AbstractProfiledItem<?>>, Serializable {
 
     private static final long serialVersionUID = 7838575753661305744L;
 
@@ -56,7 +56,7 @@
     }
 
     @Override
-    public int compareTo(AbstractProfiledItem o) {
+    public int compareTo(AbstractProfiledItem<?> o) {
         if (getProbability() > o.getProbability()) {
             return -1;
         } else if (getProbability() < o.getProbability()) {
@@ -87,7 +87,7 @@
         if (getClass() != obj.getClass()) {
             return false;
         }
-        AbstractProfiledItem other = (AbstractProfiledItem) obj;
+        AbstractProfiledItem<?> other = (AbstractProfiledItem<?>) obj;
         if (Double.doubleToLongBits(probability) != Double.doubleToLongBits(other.probability)) {
             return false;
         }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,42 +22,40 @@
  */
 package com.oracle.graal.api.meta;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 /**
  * Represents a constant (boxed) value, such as an integer, floating point number, or object
  * reference, within the compiler and across the compiler/runtime interface. Exports a set of
  * {@code Constant} instances that represent frequently used constant values, such as
  * {@link #NULL_OBJECT}.
  */
-public final class Constant extends Value {
+public abstract class Constant extends Value {
 
     private static final long serialVersionUID = -6355452536852663986L;
 
     private static final Constant[] INT_CONSTANT_CACHE = new Constant[100];
     static {
         for (int i = 0; i < INT_CONSTANT_CACHE.length; ++i) {
-            INT_CONSTANT_CACHE[i] = new Constant(Kind.Int, null, i);
+            INT_CONSTANT_CACHE[i] = new PrimitiveConstant(Kind.Int, i);
         }
     }
 
-    public static final Constant NULL_OBJECT = new Constant(Kind.Object, null, 0);
-    public static final Constant INT_MINUS_1 = new Constant(Kind.Int, null, -1);
+    public static final Constant NULL_OBJECT = new NullConstant();
+    public static final Constant INT_MINUS_1 = new PrimitiveConstant(Kind.Int, -1);
     public static final Constant INT_0 = forInt(0);
     public static final Constant INT_1 = forInt(1);
     public static final Constant INT_2 = forInt(2);
     public static final Constant INT_3 = forInt(3);
     public static final Constant INT_4 = forInt(4);
     public static final Constant INT_5 = forInt(5);
-    public static final Constant LONG_0 = new Constant(Kind.Long, null, 0L);
-    public static final Constant LONG_1 = new Constant(Kind.Long, null, 1L);
-    public static final Constant FLOAT_0 = new Constant(Kind.Float, null, Float.floatToRawIntBits(0.0F));
-    public static final Constant FLOAT_1 = new Constant(Kind.Float, null, Float.floatToRawIntBits(1.0F));
-    public static final Constant FLOAT_2 = new Constant(Kind.Float, null, Float.floatToRawIntBits(2.0F));
-    public static final Constant DOUBLE_0 = new Constant(Kind.Double, null, Double.doubleToRawLongBits(0.0D));
-    public static final Constant DOUBLE_1 = new Constant(Kind.Double, null, Double.doubleToRawLongBits(1.0D));
-    public static final Constant TRUE = new Constant(Kind.Boolean, null, 1L);
-    public static final Constant FALSE = new Constant(Kind.Boolean, null, 0L);
+    public static final Constant LONG_0 = new PrimitiveConstant(Kind.Long, 0L);
+    public static final Constant LONG_1 = new PrimitiveConstant(Kind.Long, 1L);
+    public static final Constant FLOAT_0 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(0.0F));
+    public static final Constant FLOAT_1 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(1.0F));
+    public static final Constant FLOAT_2 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(2.0F));
+    public static final Constant DOUBLE_0 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(0.0D));
+    public static final Constant DOUBLE_1 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(1.0D));
+    public static final Constant TRUE = new PrimitiveConstant(Kind.Boolean, 1L);
+    public static final Constant FALSE = new PrimitiveConstant(Kind.Boolean, 0L);
 
     static {
         assert FLOAT_0 != forFloat(-0.0F) : "Constant for 0.0f must be different from -0.0f";
@@ -65,56 +63,86 @@
         assert NULL_OBJECT.isNull();
     }
 
-    /**
-     * The boxed object value if {@code !kind.isObject()} otherwise the (possibly null)
-     * {@link #getPrimitiveAnnotation() annotation} for a primitive value.
-     */
-    private final Object object;
-
-    /**
-     * The boxed primitive value as a {@code long}. This is ignored iff {@code kind.isObject()}. For
-     * {@code float} and {@code double} values, this value is the result of
-     * {@link Float#floatToRawIntBits(float)} and {@link Double#doubleToRawLongBits(double)}
-     * respectively.
-     */
-    private final long primitive;
-
-    private Constant(Kind kind, Object object, long primitive) {
+    protected Constant(Kind kind) {
         super(kind);
-        this.object = object;
-        this.primitive = primitive;
-    }
-
-    /**
-     * Checks whether this constant is non-null.
-     * 
-     * @return {@code true} if this constant is a primitive, or an object constant that is not null
-     */
-    public boolean isNonNull() {
-        return getKind() != Kind.Object || object != null;
     }
 
     /**
      * Checks whether this constant is null.
-     * 
+     *
      * @return {@code true} if this constant is the null constant
      */
-    public boolean isNull() {
-        return getKind() == Kind.Object && object == null;
+    public abstract boolean isNull();
+
+    /**
+     * Checks whether this constant is non-null.
+     *
+     * @return {@code true} if this constant is a primitive, or an object constant that is not null
+     */
+    public final boolean isNonNull() {
+        return !isNull();
     }
 
     /**
      * Checks whether this constant is the default value for its kind (null, 0, 0.0, false).
-     * 
+     *
      * @return {@code true} if this constant is the default value for its kind
      */
-    public boolean isDefaultForKind() {
-        return object == null && primitive == 0;
-    }
+    public abstract boolean isDefaultForKind();
+
+    /**
+     * Returns the value of this constant as a boxed Java value.
+     *
+     * @return the value of this constant
+     */
+    public abstract Object asBoxedPrimitive();
+
+    /**
+     * Returns the primitive int value this constant represents. The constant must have a
+     * {@link Kind#getStackKind()} of {@link Kind#Int}.
+     *
+     * @return the constant value
+     */
+    public abstract int asInt();
+
+    /**
+     * Returns the primitive boolean value this constant represents. The constant must have kind
+     * {@link Kind#Boolean}.
+     *
+     * @return the constant value
+     */
+    public abstract boolean asBoolean();
 
-    public long getPrimitive() {
-        assert getKind().isPrimitive();
-        return primitive;
+    /**
+     * Returns the primitive long value this constant represents. The constant must have kind
+     * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}.
+     *
+     * @return the constant value
+     */
+    public abstract long asLong();
+
+    /**
+     * Returns the primitive float value this constant represents. The constant must have kind
+     * {@link Kind#Float}.
+     *
+     * @return the constant value
+     */
+    public abstract float asFloat();
+
+    /**
+     * Returns the primitive double value this constant represents. The constant must have kind
+     * {@link Kind#Double}.
+     *
+     * @return the constant value
+     */
+    public abstract double asDouble();
+
+    public String toValueString() {
+        if (getKind() == Kind.Illegal) {
+            return "illegal";
+        } else {
+            return getKind().format(asBoxedPrimitive());
+        }
     }
 
     @Override
@@ -122,165 +150,13 @@
         if (getKind() == Kind.Illegal) {
             return "illegal";
         } else {
-            String annotationSuffix = "";
-            Object primitiveAnnotation = getPrimitiveAnnotation();
-            if (getKind() != Kind.Object && primitiveAnnotation != null) {
-                try {
-                    annotationSuffix = "{" + primitiveAnnotation + "}";
-                } catch (Throwable t) {
-                    annotationSuffix = "{" + getSimpleName(primitiveAnnotation.getClass(), true) + "@" + System.identityHashCode(primitiveAnnotation) + "}";
-                }
-            }
-            return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]" + annotationSuffix;
+            return getKind().getJavaName() + "[" + toValueString() + "]";
         }
     }
 
     /**
-     * Returns the value of this constant as a boxed Java value.
-     * 
-     * @return the value of this constant
-     */
-    public Object asBoxedValue() {
-        switch (getKind()) {
-            case Byte:
-                return (byte) asInt();
-            case Boolean:
-                return asInt() == 0 ? Boolean.FALSE : Boolean.TRUE;
-            case Short:
-                return (short) primitive;
-            case Char:
-                return (char) primitive;
-            case Int:
-                return (int) primitive;
-            case Long:
-                return primitive;
-            case Float:
-                return asFloat();
-            case Double:
-                return asDouble();
-            case Object:
-                return object;
-            case Illegal:
-                return this;
-        }
-        throw new IllegalArgumentException();
-    }
-
-    private boolean valueEqual(Constant other, boolean ignoreKind) {
-        // must have equivalent kinds to be equal
-        if (!ignoreKind && getKind() != other.getKind()) {
-            return false;
-        }
-        if (getKind() == Kind.Object) {
-            return object == other.object;
-        }
-        return primitive == other.primitive && getPrimitiveAnnotation() == other.getPrimitiveAnnotation();
-    }
-
-    /**
-     * Returns the primitive int value this constant represents. The constant must have a
-     * {@link Kind#getStackKind()} of {@link Kind#Int}.
-     * 
-     * @return the constant value
-     */
-    public int asInt() {
-        assert getKind().getStackKind() == Kind.Int;
-        return (int) primitive;
-    }
-
-    /**
-     * Returns the primitive boolean value this constant represents. The constant must have kind
-     * {@link Kind#Boolean}.
-     * 
-     * @return the constant value
-     */
-    public boolean asBoolean() {
-        assert getKind() == Kind.Boolean;
-        return primitive != 0L;
-    }
-
-    /**
-     * Returns the primitive long value this constant represents. The constant must have kind
-     * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}.
-     * 
-     * @return the constant value
-     */
-    public long asLong() {
-        assert getKind().isNumericInteger();
-        return primitive;
-    }
-
-    /**
-     * Returns the primitive float value this constant represents. The constant must have kind
-     * {@link Kind#Float}.
-     * 
-     * @return the constant value
-     */
-    public float asFloat() {
-        assert getKind() == Kind.Float;
-        return Float.intBitsToFloat((int) primitive);
-    }
-
-    /**
-     * Returns the primitive double value this constant represents. The constant must have kind
-     * {@link Kind#Double}.
-     * 
-     * @return the constant value
-     */
-    public double asDouble() {
-        assert getKind() == Kind.Double;
-        return Double.longBitsToDouble(primitive);
-    }
-
-    /**
-     * Returns the object reference this constant represents. The constant must have kind
-     * {@link Kind#Object}.
-     * 
-     * @return the constant value
-     */
-    public Object asObject() {
-        assert getKind() == Kind.Object;
-        return object;
-    }
-
-    /**
-     * Gets the annotation (if any) associated with this constant.
-     * 
-     * @return null if this constant is not primitive or has no annotation
-     */
-    public Object getPrimitiveAnnotation() {
-        return getKind() == Kind.Object ? null : object;
-    }
-
-    /**
-     * Computes the hashcode of this constant.
-     * 
-     * @return a suitable hashcode for this constant
-     */
-    @Override
-    public int hashCode() {
-        if (getKind() == Kind.Object) {
-            return System.identityHashCode(object);
-        }
-        return (int) primitive * getKind().ordinal();
-    }
-
-    /**
-     * Checks whether this constant equals another object. This is only true if the other object is
-     * a constant that has the same {@linkplain #getKind() kind}, value and
-     * {@link #getPrimitiveAnnotation() annotation}.
-     * 
-     * @param o the object to compare equality
-     * @return {@code true} if this constant is equivalent to the specified object
-     */
-    @Override
-    public boolean equals(Object o) {
-        return o == this || o instanceof Constant && valueEqual((Constant) o, false);
-    }
-
-    /**
      * Creates a boxed double constant.
-     * 
+     *
      * @param d the double value to box
      * @return a boxed copy of {@code value}
      */
@@ -291,12 +167,12 @@
         if (Double.compare(d, 1.0D) == 0) {
             return DOUBLE_1;
         }
-        return new Constant(Kind.Double, null, Double.doubleToRawLongBits(d));
+        return new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(d));
     }
 
     /**
      * Creates a boxed float constant.
-     * 
+     *
      * @param f the float value to box
      * @return a boxed copy of {@code value}
      */
@@ -310,22 +186,22 @@
         if (Float.compare(f, 2.0F) == 0) {
             return FLOAT_2;
         }
-        return new Constant(Kind.Float, null, Float.floatToRawIntBits(f));
+        return new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(f));
     }
 
     /**
      * Creates a boxed long constant.
-     * 
+     *
      * @param i the long value to box
      * @return a boxed copy of {@code value}
      */
     public static Constant forLong(long i) {
-        return i == 0 ? LONG_0 : i == 1 ? LONG_1 : new Constant(Kind.Long, null, i);
+        return i == 0 ? LONG_0 : i == 1 ? LONG_1 : new PrimitiveConstant(Kind.Long, i);
     }
 
     /**
      * Creates a boxed integer constant.
-     * 
+     *
      * @param i the integer value to box
      * @return a boxed copy of {@code value}
      */
@@ -336,22 +212,22 @@
         if (i >= 0 && i < INT_CONSTANT_CACHE.length) {
             return INT_CONSTANT_CACHE[i];
         }
-        return new Constant(Kind.Int, null, i);
+        return new PrimitiveConstant(Kind.Int, i);
     }
 
     /**
      * Creates a boxed byte constant.
-     * 
+     *
      * @param i the byte value to box
      * @return a boxed copy of {@code value}
      */
     public static Constant forByte(byte i) {
-        return new Constant(Kind.Byte, null, i);
+        return new PrimitiveConstant(Kind.Byte, i);
     }
 
     /**
      * Creates a boxed boolean constant.
-     * 
+     *
      * @param i the boolean value to box
      * @return a boxed copy of {@code value}
      */
@@ -361,52 +237,33 @@
 
     /**
      * Creates a boxed char constant.
-     * 
+     *
      * @param i the char value to box
      * @return a boxed copy of {@code value}
      */
     public static Constant forChar(char i) {
-        return new Constant(Kind.Char, null, i);
+        return new PrimitiveConstant(Kind.Char, i);
     }
 
     /**
      * Creates a boxed short constant.
-     * 
+     *
      * @param i the short value to box
      * @return a boxed copy of {@code value}
      */
     public static Constant forShort(short i) {
-        return new Constant(Kind.Short, null, i);
+        return new PrimitiveConstant(Kind.Short, i);
     }
 
     /**
-     * Creates a boxed object constant.
-     * 
-     * @param o the object value to box
-     * @return a boxed copy of {@code value}
+     * Creates a {@link Constant} from a primitive integer of a certain kind.
      */
-    public static Constant forObject(Object o) {
-        if (o == null) {
-            return NULL_OBJECT;
-        }
-        return new Constant(Kind.Object, o, 0L);
-    }
-
-    /**
-     * Creates an annotated int or long constant. An annotation enables a client to associate some
-     * extra semantic or debugging information with a primitive. An annotated primitive constant is
-     * never {@linkplain #equals(Object) equal} to a non-annotated constant.
-     * 
-     * @param kind the type of this constant
-     * @param i the value of this constant
-     * @param annotation an arbitrary non-null object
-     */
-    public static Constant forIntegerKind(Kind kind, long i, Object annotation) {
+    public static Constant forIntegerKind(Kind kind, long i) {
         switch (kind) {
             case Int:
-                return new Constant(kind, annotation, (int) i);
+                return new PrimitiveConstant(kind, (int) i);
             case Long:
-                return new Constant(kind, annotation, i);
+                return new PrimitiveConstant(kind, i);
             default:
                 throw new IllegalArgumentException("not an integer kind: " + kind);
         }
@@ -418,47 +275,42 @@
     public static Constant forPrimitiveInt(int bits, long i) {
         assert bits <= 64;
         if (bits > 32) {
-            return new Constant(Kind.Long, null, i);
+            return new PrimitiveConstant(Kind.Long, i);
         } else {
-            return new Constant(Kind.Int, null, (int) i);
+            return new PrimitiveConstant(Kind.Int, (int) i);
         }
     }
 
     /**
-     * Creates a boxed constant for the given kind from an Object. The object needs to be of the
-     * Java boxed type corresponding to the kind.
-     * 
-     * @param kind the kind of the constant to create
-     * @param value the Java boxed value: a {@link Byte} instance for {@link Kind#Byte}, etc.
-     * @return the boxed copy of {@code value}
+     * Creates a boxed constant for the given boxed primitive value.
+     *
+     * @param value the Java boxed value
+     * @return the primitive constant holding the {@code value}
      */
-    public static Constant forBoxed(Kind kind, Object value) {
-        switch (kind) {
-            case Boolean:
-                return forBoolean((Boolean) value);
-            case Byte:
-                return forByte((Byte) value);
-            case Char:
-                return forChar((Character) value);
-            case Short:
-                return forShort((Short) value);
-            case Int:
-                return forInt((Integer) value);
-            case Long:
-                return forLong((Long) value);
-            case Float:
-                return forFloat((Float) value);
-            case Double:
-                return forDouble((Double) value);
-            case Object:
-                return forObject(value);
-            default:
-                throw new RuntimeException("cannot create Constant for boxed " + kind + " value");
+    public static Constant forBoxedPrimitive(Object value) {
+        if (value instanceof Boolean) {
+            return forBoolean((Boolean) value);
+        } else if (value instanceof Byte) {
+            return forByte((Byte) value);
+        } else if (value instanceof Character) {
+            return forChar((Character) value);
+        } else if (value instanceof Short) {
+            return forShort((Short) value);
+        } else if (value instanceof Integer) {
+            return forInt((Integer) value);
+        } else if (value instanceof Long) {
+            return forLong((Long) value);
+        } else if (value instanceof Float) {
+            return forFloat((Float) value);
+        } else if (value instanceof Double) {
+            return forDouble((Double) value);
+        } else {
+            return null;
         }
     }
 
     public static Constant forIllegal() {
-        return new Constant(Kind.Illegal, null, 0);
+        return new PrimitiveConstant(Kind.Illegal, 0);
     }
 
     /**
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Wed Apr 23 15:48:38 2014 +0200
@@ -117,5 +117,5 @@
      *            {@code -1}
      * @return the appendix if it exists and is resolved or {@code null}
      */
-    Object lookupAppendix(int cpi, int opcode);
+    Constant lookupAppendix(int cpi, int opcode);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantReflectionProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantReflectionProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -23,34 +23,78 @@
 package com.oracle.graal.api.meta;
 
 /**
- * Reflection operations on values represented as {@linkplain Constant constants}.
+ * Reflection operations on values represented as {@linkplain Constant constants}. All methods in
+ * this interface require the VM to access the actual object encapsulated in {@link Kind#Object
+ * object} constants. This access is not always possible, depending on kind of VM and the state that
+ * the VM is in. Therefore, all methods can return {@code null} at any time, to indicate that the
+ * result is not available at this point. The caller is responsible to check for {@code null}
+ * results and handle them properly, e.g., not perform an optimization.
  */
 public interface ConstantReflectionProvider {
 
     /**
-     * Compares two constants for equality. The equality relationship is symmetric. If the constants
-     * cannot be compared at this point, the return value is {@code null};
-     * 
-     * @return {@code true} if the two parameters represent the same runtime object, {@code false}
-     *         if they are different, or {@code null} if the parameters cannot be compared.
+     * Compares two constants for equality. The equality relationship is symmetric. Returns
+     * {@link Boolean#TRUE true} if the two constants represent the same run time value,
+     * {@link Boolean#FALSE false} if they are different. Returns {@code null} if the constants
+     * cannot be compared at this point.
      */
     Boolean constantEquals(Constant x, Constant y);
 
     /**
-     * Returns the length of an array that is wrapped in a {@link Constant} object. If {@code array}
-     * is not an array, or the array length is not available at this point, the return value is
-     * {@code null}.
+     * Returns the length of the array constant. Returns {@code null} if the constant is not an
+     * array, or if the array length is not available at this point.
      */
-    Integer lookupArrayLength(Constant array);
+    Integer readArrayLength(Constant array);
 
     /**
-     * Reads a value of this kind using a base address and a displacement.
-     * 
-     * @param base the base address from which the value is read
+     * Reads a value from the given array at the given index. Returns {@code null} if the constant
+     * is not an array, if the index is out of bounds, or if the value is not available at this
+     * point.
+     */
+    Constant readArrayElement(Constant array, int index);
+
+    /**
+     * Reads a value of this kind using a base address and a displacement. No bounds checking or
+     * type checking is performed. Returns {@code null} if the value is not available at this point.
+     *
+     * @param base the base address from which the value is read.
      * @param displacement the displacement within the object in bytes
-     * @param compressible whether this is a read of a compressed or an uncompressed pointer
      * @return the read value encapsulated in a {@link Constant} object, or {@code null} if the
      *         value cannot be read.
      */
-    Constant readUnsafeConstant(Kind kind, Object base, long displacement, boolean compressible);
+    Constant readUnsafeConstant(Kind kind, Constant base, long displacement);
+
+    /**
+     * Reads a primitive value using a base address and a displacement.
+     *
+     * @param kind the {@link Kind} of the returned {@link Constant} object
+     * @param base the base address from which the value is read
+     * @param displacement the displacement within the object in bytes
+     * @param bits the number of bits to read from memory
+     * @return the read value encapsulated in a {@link Constant} object of {@link Kind} kind
+     */
+    Constant readRawConstant(Kind kind, Constant base, long displacement, int bits);
+
+    /**
+     * Converts the given {@link Kind#isPrimitive() primitive} constant to a boxed
+     * {@link Kind#Object object} constant, according to the Java boxing rules. Returns {@code null}
+     * if the source is is not a primitive constant, or the boxed value is not available at this
+     * point.
+     */
+    Constant boxPrimitive(Constant source);
+
+    /**
+     * Converts the given {@link Kind#Object object} constant to a {@link Kind#isPrimitive()
+     * primitive} constant, according to the Java unboxing rules. Returns {@code null} if the source
+     * is is not an object constant that can be unboxed, or the unboxed value is not available at
+     * this point.
+     */
+    Constant unboxPrimitive(Constant source);
+
+    /**
+     * Returns the {@link ResolvedJavaType} for a {@link Class} object (or any other object regarded
+     * as a class by the VM) encapsulated in the given constant. Returns {@code null} if the
+     * constant does not encapsulate a class, or if the type is not available at this point.
+     */
+    ResolvedJavaType asJavaType(Constant constant);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java	Wed Apr 23 15:48:38 2014 +0200
@@ -41,10 +41,10 @@
 public class ForeignCallDescriptor {
 
     private final String name;
-    private final Class resultType;
-    private final Class[] argumentTypes;
+    private final Class<?> resultType;
+    private final Class<?>[] argumentTypes;
 
-    public ForeignCallDescriptor(String name, Class resultType, Class... argumentTypes) {
+    public ForeignCallDescriptor(String name, Class<?> resultType, Class<?>... argumentTypes) {
         this.name = name;
         this.resultType = resultType;
         this.argumentTypes = argumentTypes;
@@ -89,7 +89,7 @@
     public String toString() {
         StringBuilder sb = new StringBuilder(name).append('(');
         String sep = "";
-        for (Class arg : argumentTypes) {
+        for (Class<?> arg : argumentTypes) {
             sb.append(sep).append(arg.getSimpleName());
             sep = ",";
         }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.api.meta;
 
-import static java.lang.reflect.Modifier.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
@@ -146,7 +144,7 @@
 
         public ProfiledType(ResolvedJavaType type, double probability) {
             super(type, probability);
-            assert type.isArray() || !isAbstract(type.getModifiers()) : type;
+            assert type.isArray() || !type.isAbstract() : type;
         }
 
         /**
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Wed Apr 23 15:48:38 2014 +0200
@@ -66,10 +66,10 @@
     private final char typeChar;
     private final String javaName;
     private final boolean isStackInt;
-    private final Class primitiveJavaClass;
-    private final Class boxedJavaClass;
+    private final Class<?> primitiveJavaClass;
+    private final Class<?> boxedJavaClass;
 
-    private Kind(char typeChar, String javaName, boolean isStackInt, Class primitiveJavaClass, Class boxedJavaClass) {
+    private Kind(char typeChar, String javaName, boolean isStackInt, Class<?> primitiveJavaClass, Class<?> boxedJavaClass) {
         this.typeChar = typeChar;
         this.javaName = javaName;
         this.isStackInt = isStackInt;
@@ -95,7 +95,7 @@
 
     /**
      * Checks whether this type is a Java primitive type.
-     * 
+     *
      * @return {@code true} if this is {@link #Boolean}, {@link #Byte}, {@link #Char},
      *         {@link #Short}, {@link #Int}, {@link #Long}, {@link #Float}, {@link #Double}, or
      *         {@link #Void}.
@@ -106,7 +106,7 @@
 
     /**
      * Returns the kind that represents this kind when on the Java operand stack.
-     * 
+     *
      * @return the kind used on the operand stack
      */
     public Kind getStackKind() {
@@ -118,7 +118,7 @@
 
     /**
      * Checks whether this type is a Java primitive type representing an integer number.
-     * 
+     *
      * @return {@code true} if the stack kind is {@link #Int} or {@link #Long}.
      */
     public boolean isNumericInteger() {
@@ -127,7 +127,7 @@
 
     /**
      * Checks whether this type is a Java primitive type representing an unsigned number.
-     * 
+     *
      * @return {@code true} if the kind is {@link #Boolean} or {@link #Char}.
      */
     public boolean isUnsigned() {
@@ -136,7 +136,7 @@
 
     /**
      * Checks whether this type is a Java primitive type representing a floating point number.
-     * 
+     *
      * @return {@code true} if this is {@link #Float} or {@link #Double}.
      */
     public boolean isNumericFloat() {
@@ -145,7 +145,7 @@
 
     /**
      * Checks whether this represent an Object of some sort.
-     * 
+     *
      * @return {@code true} if this is {@link #Object}.
      */
     public boolean isObject() {
@@ -154,7 +154,7 @@
 
     /**
      * Returns the kind corresponding to the Java type string.
-     * 
+     *
      * @param typeString the Java type string
      * @return the kind
      */
@@ -169,7 +169,7 @@
 
     /**
      * Returns the kind of a word given the size of a word in bytes.
-     * 
+     *
      * @param wordSizeInBytes the size of a word in bytes
      * @return the kind representing a word value
      */
@@ -184,7 +184,7 @@
 
     /**
      * Returns the kind from the character describing a primitive or void.
-     * 
+     *
      * @param ch the character
      * @return the kind
      */
@@ -214,7 +214,7 @@
 
     /**
      * Returns the Kind representing the given Java class.
-     * 
+     *
      * @param klass the class
      * @return the kind
      */
@@ -244,7 +244,7 @@
 
     /**
      * Returns the Java class representing this kind.
-     * 
+     *
      * @return the Java class
      */
     public Class<?> toJavaClass() {
@@ -253,7 +253,7 @@
 
     /**
      * Returns the Java class for instances of boxed values of this kind.
-     * 
+     *
      * @return the Java class
      */
     public Class<?> toBoxedJavaClass() {
@@ -279,13 +279,13 @@
     /**
      * Classes for which invoking {@link Object#toString()} does not run user code.
      */
-    private static boolean isToStringSafe(Class c) {
+    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
      */
@@ -307,7 +307,7 @@
                 } else if (value instanceof JavaType) {
                     return "JavaType:" + MetaUtil.toJavaName((JavaType) value);
                 } else if (value instanceof Enum) {
-                    return MetaUtil.getSimpleName(value.getClass(), true) + ":" + ((Enum) value).name();
+                    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<?>) {
@@ -351,7 +351,7 @@
 
     /**
      * The minimum value that can be represented as a value of this kind.
-     * 
+     *
      * @return the minimum value
      */
     public long getMinValue() {
@@ -375,7 +375,7 @@
 
     /**
      * The maximum value that can be represented as a value of this kind.
-     * 
+     *
      * @return the maximum value
      */
     public long getMaxValue() {
@@ -399,7 +399,7 @@
 
     /**
      * Number of bytes that are necessary to represent a value of this kind.
-     * 
+     *
      * @return the number of bytes
      */
     public int getByteCount() {
@@ -412,7 +412,7 @@
 
     /**
      * Number of bits that are necessary to represent a value of this kind.
-     * 
+     *
      * @return the number of bits
      */
     public int getBitCount() {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -45,7 +45,7 @@
     /**
      * Provides the {@link ResolvedJavaMethod} for a {@link Constructor} obtained via reflection.
      */
-    ResolvedJavaMethod lookupJavaConstructor(Constructor reflectionConstructor);
+    ResolvedJavaMethod lookupJavaConstructor(Constructor<?> reflectionConstructor);
 
     /**
      * Provides the {@link ResolvedJavaField} for a {@link Field} obtained via reflection.
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.api.meta;
 
-import static java.lang.reflect.Modifier.*;
-
 import java.io.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -50,18 +48,18 @@
     /**
      * Returns the number of bytes occupied by this constant value or constant object and
      * recursively all values reachable from this value.
-     * 
+     *
      * @param constant the constant whose bytes should be measured
      * @param printTopN print total size and instance count of the top n classes is desired
      * @return the number of bytes occupied by this constant
      */
-    public static long getMemorySizeRecursive(MetaAccessProvider access, Constant constant, PrintStream out, int printTopN) {
-        IdentityHashMap<Object, Boolean> marked = new IdentityHashMap<>();
+    public static long getMemorySizeRecursive(MetaAccessProvider access, ConstantReflectionProvider constantReflection, Constant constant, PrintStream out, int printTopN) {
+        Set<Constant> marked = new HashSet<>();
         Stack<Constant> stack = new Stack<>();
         if (constant.getKind() == Kind.Object && constant.isNonNull()) {
-            marked.put(constant.asObject(), Boolean.TRUE);
+            marked.add(constant);
         }
-        final HashMap<Class, ClassInfo> histogram = new HashMap<>();
+        final HashMap<ResolvedJavaType, ClassInfo> histogram = new HashMap<>();
         stack.push(constant);
         long sum = 0;
         while (!stack.isEmpty()) {
@@ -69,7 +67,7 @@
             long memorySize = access.getMemorySize(constant);
             sum += memorySize;
             if (c.getKind() == Kind.Object && c.isNonNull()) {
-                Class<?> clazz = c.asObject().getClass();
+                ResolvedJavaType clazz = access.lookupJavaType(c);
                 if (!histogram.containsKey(clazz)) {
                     histogram.put(clazz, new ClassInfo());
                 }
@@ -79,10 +77,10 @@
                 ResolvedJavaType type = access.lookupJavaType(c);
                 if (type.isArray()) {
                     if (!type.getComponentType().isPrimitive()) {
-                        Object[] array = (Object[]) c.asObject();
-                        for (Object value : array) {
-                            Constant forObject = Constant.forObject(value);
-                            pushConstant(marked, stack, forObject);
+                        int length = constantReflection.readArrayLength(c);
+                        for (int i = 0; i < length; i++) {
+                            Constant value = constantReflection.readArrayElement(c, i);
+                            pushConstant(marked, stack, value);
                         }
                     }
                 } else {
@@ -96,12 +94,12 @@
                 }
             }
         }
-        ArrayList<Class> clazzes = new ArrayList<>();
+        ArrayList<ResolvedJavaType> clazzes = new ArrayList<>();
         clazzes.addAll(histogram.keySet());
-        Collections.sort(clazzes, new Comparator<Class>() {
+        Collections.sort(clazzes, new Comparator<ResolvedJavaType>() {
 
             @Override
-            public int compare(Class o1, Class o2) {
+            public int compare(ResolvedJavaType o1, ResolvedJavaType o2) {
                 long l1 = histogram.get(o1).totalSize;
                 long l2 = histogram.get(o2).totalSize;
                 if (l1 > l2) {
@@ -115,7 +113,7 @@
         });
 
         int z = 0;
-        for (Class c : clazzes) {
+        for (ResolvedJavaType c : clazzes) {
             if (z > printTopN) {
                 break;
             }
@@ -126,10 +124,10 @@
         return sum;
     }
 
-    private static void pushConstant(IdentityHashMap<Object, Boolean> marked, Stack<Constant> stack, Constant value) {
+    private static void pushConstant(Set<Constant> marked, Stack<Constant> stack, Constant value) {
         if (value.isNonNull()) {
-            if (!marked.containsKey(value.asObject())) {
-                marked.put(value.asObject(), Boolean.TRUE);
+            if (!marked.contains(value)) {
+                marked.add(value);
                 stack.push(value);
             }
         }
@@ -158,7 +156,7 @@
     /**
      * Calls {@link MetaAccessProvider#lookupJavaType(Class)} on an array of classes.
      */
-    public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class[] classes) {
+    public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class<?>[] classes) {
         ResolvedJavaType[] result = new ResolvedJavaType[classes.length];
         for (int i = 0; i < result.length; i++) {
             result[i] = metaAccess.lookupJavaType(classes[i]);
@@ -182,7 +180,7 @@
     /**
      * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for
      * anonymous and local classes.
-     * 
+     *
      * @param clazz the class for which the simple name is being requested
      * @param withEnclosingClass specifies if the returned name should be qualified with the name(s)
      *            of the enclosing class/classes of {@code clazz} (if any). This option is ignored
@@ -218,7 +216,7 @@
     /**
      * Converts a given type to its Java programming language name. The following are examples of
      * strings returned by this method:
-     * 
+     *
      * <pre>
      *     qualified == true:
      *         java.lang.Object
@@ -229,7 +227,7 @@
      *         int
      *         boolean[][]
      * </pre>
-     * 
+     *
      * @param type the type to be converted to a Java name
      * @param qualified specifies if the package prefix of the type should be included in the
      *            returned name
@@ -246,13 +244,13 @@
     /**
      * Converts a given type to its Java programming language name. The following are examples of
      * strings returned by this method:
-     * 
+     *
      * <pre>
      *      java.lang.Object
      *      int
      *      boolean[][]
      * </pre>
-     * 
+     *
      * @param type the type to be converted to a Java name
      * @return the Java name corresponding to {@code type}
      */
@@ -308,7 +306,7 @@
      * and specifiers that denote an attribute of the method that is to be copied to the result. A
      * specifier is a single character preceded by a '%' character. The accepted specifiers and the
      * method attributes they denote are described below:
-     * 
+     *
      * <pre>
      *     Specifier | Description                                          | Example(s)
      *     ----------+------------------------------------------------------------------------------------------
@@ -322,7 +320,7 @@
      *     'f'       | Indicator if method is unresolved, static or virtual | "unresolved" "static" "virtual"
      *     '%'       | A '%' character                                      | "%"
      * </pre>
-     * 
+     *
      * @param format a format specification
      * @param method the method to be formatted
      * @return the result of formatting this method according to {@code format}
@@ -378,7 +376,7 @@
                         break;
                     }
                     case 'f': {
-                        sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : isStatic(((ResolvedJavaMethod) method).getModifiers()) ? "static" : "virtual");
+                        sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : ((ResolvedJavaMethod) method).isStatic() ? "static" : "virtual");
                         break;
                     }
                     case '%': {
@@ -402,7 +400,7 @@
      * specifiers that denote an attribute of the field that is to be copied to the result. A
      * specifier is a single character preceded by a '%' character. The accepted specifiers and the
      * field attributes they denote are described below:
-     * 
+     *
      * <pre>
      *     Specifier | Description                                          | Example(s)
      *     ----------+------------------------------------------------------------------------------------------
@@ -414,7 +412,7 @@
      *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
      *     '%'       | A '%' character                                      | "%"
      * </pre>
-     * 
+     *
      * @param format a format specification
      * @param field the field to be formatted
      * @return the result of formatting this field according to {@code format}
@@ -452,7 +450,7 @@
                         break;
                     }
                     case 'f': {
-                        sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : isStatic(((ResolvedJavaField) field).getModifiers()) ? "static" : "instance");
+                        sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) field).isStatic() ? "static" : "instance");
                         break;
                     }
                     case '%': {
@@ -472,7 +470,7 @@
 
     /**
      * Gets the annotations of a particular type for the formal parameters of a given method.
-     * 
+     *
      * @param annotationClass the Class object corresponding to the annotation type
      * @param method the method for which a parameter annotations are being requested
      * @return the annotation of type {@code annotationClass} (if any) for each formal parameter
@@ -494,7 +492,7 @@
 
     /**
      * Gets the annotation of a particular type for a formal parameter of a given method.
-     * 
+     *
      * @param annotationClass the Class object corresponding to the annotation type
      * @param parameterIndex the index of a formal parameter of {@code method}
      * @param method the method for which a parameter annotation is being requested
@@ -530,18 +528,18 @@
      * line number is {@linkplain ResolvedJavaMethod#asStackTraceElement(int) available} for the
      * given method, then the string returned is the {@link StackTraceElement#toString()} value of
      * the stack trace element, suffixed by the bci location. For example:
-     * 
+     *
      * <pre>
      *     java.lang.String.valueOf(String.java:2930) [bci: 12]
      * </pre>
-     * 
+     *
      * Otherwise, the string returned is the value of applying {@link #format(String, JavaMethod)}
      * with the format string {@code "%H.%n(%p)"}, suffixed by the bci location. For example:
-     * 
+     *
      * <pre>
      *     java.lang.String.valueOf(int) [bci: 12]
      * </pre>
-     * 
+     *
      * @param sb
      * @param method
      * @param bci
@@ -561,7 +559,7 @@
     }
 
     public static JavaType[] signatureToTypes(ResolvedJavaMethod method) {
-        JavaType receiver = isStatic(method.getModifiers()) ? null : method.getDeclaringClass();
+        JavaType receiver = method.isStatic() ? null : method.getDeclaringClass();
         return signatureToTypes(method.getSignature(), receiver);
     }
 
@@ -586,13 +584,13 @@
      * Gets the <a
      * href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
      * descriptor</a> corresponding to this signature. For example:
-     * 
+     *
      * <pre>
      * (ILjava/lang/String;D)V
      * </pre>
-     * 
+     *
      * .
-     * 
+     *
      * @param sig the {@link Signature} to be converted.
      * @return the signature as a string
      */
@@ -607,7 +605,7 @@
 
     /**
      * Formats some profiling information associated as a string.
-     * 
+     *
      * @param info the profiling info to format
      * @param method an optional method that augments the profile string returned
      * @param sep the separator to use for each separate profile record
@@ -669,13 +667,13 @@
         return s.substring(0, s.length() - sep.length());
     }
 
-    private static void appendProfile(StringBuilder buf, AbstractJavaProfile profile, int bci, String type, String sep) {
+    private static void appendProfile(StringBuilder buf, AbstractJavaProfile<?, ?> profile, int bci, String type, String sep) {
         if (profile != null) {
-            AbstractProfiledItem[] pitems = profile.getItems();
+            AbstractProfiledItem<?>[] pitems = profile.getItems();
             if (pitems != null) {
                 buf.append(String.format("%s@%d:", type, bci));
                 for (int j = 0; j < pitems.length; j++) {
-                    AbstractProfiledItem pitem = pitems[j];
+                    AbstractProfiledItem<?> pitem = pitems[j];
                     buf.append(String.format(" %.6f (%s)%s", pitem.getProbability(), pitem.getItem(), sep));
                 }
                 if (profile.getNotRecordedProbability() != 0) {
@@ -689,7 +687,7 @@
 
     /**
      * Converts a Java source-language class name into the internal form.
-     * 
+     *
      * @param className the class name
      * @return the internal name form of the class name
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ModifiersProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,131 @@
+/*
+ * 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.api.meta;
+
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+
+/**
+ * A Java element (i.e., a class, interface, field or method) that is described by a set of Java
+ * language {@linkplain #getModifiers() modifiers}.
+ */
+public interface ModifiersProvider {
+
+    /**
+     * Returns the Java language modifiers for this element.
+     */
+    int getModifiers();
+
+    /**
+     * see {@link Modifier#isInterface(int)}
+     */
+    default boolean isInterface() {
+        return Modifier.isInterface(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isSynchronized(int)}
+     */
+    default boolean isSynchronized() {
+        return Modifier.isSynchronized(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isStatic(int)}
+     */
+    default boolean isStatic() {
+        return Modifier.isStatic(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isFinal(int)}
+     */
+    default boolean isFinal() {
+        return Modifier.isFinal(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isPublic(int)}
+     */
+    default boolean isPublic() {
+        return Modifier.isPublic(getModifiers());
+    }
+
+    /**
+     * Determines if this element is neither {@linkplain #isPublic() public},
+     * {@linkplain #isProtected() protected} nor {@linkplain #isPrivate() private}.
+     */
+    default boolean isPackagePrivate() {
+        return ((PUBLIC | PROTECTED | PRIVATE) & getModifiers()) == 0;
+    }
+
+    /**
+     * see {@link Modifier#isPrivate(int)}
+     */
+    default boolean isPrivate() {
+        return Modifier.isPrivate(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isProtected(int)}
+     */
+    default boolean isProtected() {
+        return Modifier.isProtected(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isTransient(int)}
+     */
+    default boolean isTransient() {
+        return Modifier.isTransient(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isStrict(int)}
+     */
+    default boolean isStrict() {
+        return Modifier.isStrict(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isVolatile(int)}
+     */
+    default boolean isVolatile() {
+        return Modifier.isVolatile(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isNative(int)}
+     */
+    default boolean isNative() {
+        return Modifier.isNative(getModifiers());
+    }
+
+    /**
+     * see {@link Modifier#isAbstract(int)}
+     */
+    default boolean isAbstract() {
+        return Modifier.isAbstract(getModifiers());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/NullConstant.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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.api.meta;
+
+/**
+ * The implementation type of the {@link Constant#NULL_OBJECT null constant}.
+ */
+final class NullConstant extends Constant {
+
+    private static final long serialVersionUID = 8906209595800783961L;
+
+    protected NullConstant() {
+        super(Kind.Object);
+    }
+
+    @Override
+    public boolean isNull() {
+        return true;
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return true;
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public int asInt() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public boolean asBoolean() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public long asLong() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public float asFloat() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public double asDouble() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public String toValueString() {
+        return "null";
+    }
+
+    @Override
+    public int hashCode() {
+        return System.identityHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        assert o == this || !(o instanceof NullConstant) : "null constant is a singleton";
+        return o == this;
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ObjectLocationIdentity.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2013, 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.api.meta;
-
-import java.util.*;
-
-/**
- * A {@link LocationIdentity} wrapping an object.
- */
-public final class ObjectLocationIdentity implements LocationIdentity {
-
-    private static IdentityHashMap<Object, LocationIdentity> map = new IdentityHashMap<>();
-
-    private Object object;
-
-    public static LocationIdentity create(Object object) {
-        synchronized (map) {
-            if (map.containsKey(object)) {
-                return map.get(object);
-            } else {
-                ObjectLocationIdentity locationIdentity = new ObjectLocationIdentity(object);
-                map.put(object, locationIdentity);
-                return locationIdentity;
-            }
-        }
-    }
-
-    private ObjectLocationIdentity(Object object) {
-        this.object = object;
-    }
-
-    @Override
-    public String toString() {
-        return "Identity(" + object + ")";
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,129 @@
+/*
+ * 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.api.meta;
+
+/**
+ * Represents a primitive constant value, such as an integer or floating point number, within the
+ * compiler and across the compiler/runtime interface.
+ */
+public class PrimitiveConstant extends Constant {
+
+    private static final long serialVersionUID = 8787949721295655376L;
+
+    /**
+     * The boxed primitive value as a {@code long}. For {@code float} and {@code double} values,
+     * this value is the result of {@link Float#floatToRawIntBits(float)} and
+     * {@link Double#doubleToRawLongBits(double)} respectively.
+     */
+    private final long primitive;
+
+    protected PrimitiveConstant(Kind kind, long primitive) {
+        super(kind);
+        this.primitive = primitive;
+
+        assert kind.isPrimitive() || kind == Kind.Illegal;
+    }
+
+    @Override
+    public boolean isNull() {
+        return false;
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return primitive == 0;
+    }
+
+    @Override
+    public boolean asBoolean() {
+        assert getKind() == Kind.Boolean;
+        return primitive != 0L;
+    }
+
+    @Override
+    public int asInt() {
+        assert getKind().getStackKind() == Kind.Int;
+        return (int) primitive;
+    }
+
+    @Override
+    public long asLong() {
+        assert getKind().isNumericInteger();
+        return primitive;
+    }
+
+    @Override
+    public float asFloat() {
+        assert getKind() == Kind.Float;
+        return Float.intBitsToFloat((int) primitive);
+    }
+
+    @Override
+    public double asDouble() {
+        assert getKind() == Kind.Double;
+        return Double.longBitsToDouble(primitive);
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        switch (getKind()) {
+            case Byte:
+                return Byte.valueOf((byte) primitive);
+            case Boolean:
+                return Boolean.valueOf(asBoolean());
+            case Short:
+                return Short.valueOf((short) primitive);
+            case Char:
+                return Character.valueOf((char) primitive);
+            case Int:
+                return Integer.valueOf(asInt());
+            case Long:
+                return Long.valueOf(asLong());
+            case Float:
+                return Float.valueOf(asFloat());
+            case Double:
+                return Double.valueOf(asDouble());
+            default:
+                throw new IllegalArgumentException("unexpected kind " + getKind());
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return (int) (primitive ^ (primitive >>> 32)) * (getKind().ordinal() + 31);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o == this || (o instanceof PrimitiveConstant && super.equals(o) && primitive == ((PrimitiveConstant) o).primitive);
+    }
+
+    @Override
+    public String toString() {
+        if (getKind() == Kind.Illegal) {
+            return "illegal";
+        } else {
+            return getKind().getJavaName() + "[" + getKind().format(asBoxedPrimitive()) + "|0x" + Long.toHexString(primitive) + "]";
+        }
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,12 +29,13 @@
  * Represents a reference to a resolved Java field. Fields, like methods and types, are resolved
  * through {@link ConstantPool constant pools}.
  */
-public interface ResolvedJavaField extends JavaField, LocationIdentity {
+public interface ResolvedJavaField extends JavaField, LocationIdentity, ModifiersProvider {
 
     /**
-     * Returns the Java language modifiers for this field, as an integer. The {@link Modifier} class
-     * should be used to decode the modifiers. Only the {@linkplain Modifier#fieldModifiers() field
-     * flags} specified in the JVM specification will be included in the returned mask.
+     * {@inheritDoc}
+     * <p>
+     * Only the {@linkplain Modifier#fieldModifiers() field flags} specified in the JVM
+     * specification will be included in the returned mask.
      */
     int getModifiers();
 
@@ -53,7 +54,7 @@
      * Gets the constant value of this field. Note that a {@code static final} field may not be
      * considered constant if its declaring class is not yet initialized or if it is a well known
      * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}).
-     * 
+     *
      * @param receiver object from which this field's value is to be read. This value is ignored if
      *            this field is static.
      * @return the constant value of this field or {@code null} if this field is not considered
@@ -65,7 +66,7 @@
      * Gets the current value of this field for a given object, if available. There is no guarantee
      * that the same value will be returned by this method for a field unless the field is
      * considered to be {@linkplain #readConstantValue(Constant) constant} by the runtime.
-     * 
+     *
      * @param receiver object from which this field's value is to be read. This value is ignored if
      *            this field is static.
      * @return the value of this field or {@code null} if the value is not available (e.g., because
@@ -82,7 +83,7 @@
     /**
      * Returns the annotation for the specified type of this field, if such an annotation is
      * present.
-     * 
+     *
      * @param annotationClass the Class object corresponding to the annotation type
      * @return this element's annotation for the specified annotation type if present on this field,
      *         else {@code null}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,16 +29,16 @@
  * Represents a resolved Java method. Methods, like fields and types, are resolved through
  * {@link ConstantPool constant pools}.
  */
-public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget {
+public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersProvider {
 
     /**
      * Returns the bytecode of this method, if the method has code. The returned byte array does not
      * contain breakpoints or non-Java bytecodes. This may return null if the
      * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}.
-     * 
+     *
      * The contained constant pool indices may not be the ones found in the original class file but
      * they can be used with the Graal API (e.g. methods in {@link ConstantPool}).
-     * 
+     *
      * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the
      *         code is not ready.
      */
@@ -47,7 +47,7 @@
     /**
      * Returns the size of the bytecode of this method, if the method has code. This is equivalent
      * to {@link #getCode()}. {@code length} if the method has code.
-     * 
+     *
      * @return the size of the bytecode in bytes, or 0 if no bytecode is available
      */
     int getCodeSize();
@@ -69,10 +69,10 @@
     int getMaxStackSize();
 
     /**
-     * Returns the Java language modifiers for this method, as an integer. The {@link Modifier}
-     * class should be used to decode the modifiers. Only the
-     * {@linkplain Modifier#methodModifiers() method flags} specified in the JVM specification will
-     * be included in the returned mask.
+     * {@inheritDoc}
+     * <p>
+     * Only the {@linkplain Modifier#methodModifiers() method flags} specified in the JVM
+     * specification will be included in the returned mask.
      */
     int getModifiers();
 
@@ -84,10 +84,10 @@
 
     /**
      * Returns {@code true} if this method is a default method; returns {@code false} otherwise.
-     * 
+     *
      * A default method is a public non-abstract instance method, that is, a non-static method with
      * a body, declared in an interface type.
-     * 
+     *
      * @return true if and only if this method is a default method as defined by the Java Language
      *         Specification.
      */
@@ -95,22 +95,22 @@
 
     /**
      * Checks whether this method is a class initializer.
-     * 
+     *
      * @return {@code true} if the method is a class initializer
      */
     boolean isClassInitializer();
 
     /**
      * Checks whether this method is a constructor.
-     * 
+     *
      * @return {@code true} if the method is a constructor
      */
     boolean isConstructor();
 
     /**
      * Checks whether this method can be statically bound (usually, that means it is final or
-     * private or static, but not abstract).
-     * 
+     * private or static, but not abstract, or the declaring class is final)
+     *
      * @return {@code true} if this method can be statically bound
      */
     boolean canBeStaticallyBound();
@@ -143,7 +143,7 @@
     /**
      * Returns the annotation for the specified type of this method, if such an annotation is
      * present.
-     * 
+     *
      * @param annotationClass the Class object corresponding to the annotation type
      * @return this element's annotation for the specified annotation type if present on this
      *         method, else {@code null}
@@ -153,7 +153,7 @@
     /**
      * Returns an array of arrays that represent the annotations on the formal parameters, in
      * declaration order, of this method.
-     * 
+     *
      * @see Method#getParameterAnnotations()
      */
     Annotation[][] getParameterAnnotations();
@@ -161,7 +161,7 @@
     /**
      * Returns an array of {@link Type} objects that represent the formal parameter types, in
      * declaration order, of this method.
-     * 
+     *
      * @see Method#getGenericParameterTypes()
      */
     Type[] getGenericParameterTypes();
@@ -192,7 +192,7 @@
      * Invokes the underlying method represented by this object, on the specified object with the
      * specified parameters. This method is similar to a reflective method invocation by
      * {@link Method#invoke}.
-     * 
+     *
      * @param receiver The receiver for the invocation, or {@code null} if it is a static method.
      * @param arguments The arguments for the invocation.
      * @return The value returned by the method invocation, or {@code null} if the return type is
@@ -204,7 +204,7 @@
      * Uses the constructor represented by this object to create and initialize a new instance of
      * the constructor's declaring class, with the specified initialization parameters. This method
      * is similar to a reflective instantiation by {@link Constructor#newInstance}.
-     * 
+     *
      * @param arguments The arguments for the constructor.
      * @return The newly created and initialized object.
      */
@@ -212,14 +212,14 @@
 
     /**
      * Gets the encoding of (that is, a constant representing the value of) this method.
-     * 
+     *
      * @return a constant representing a reference to this method
      */
     Constant getEncoding();
 
     /**
      * Checks if this method is present in the virtual table.
-     * 
+     *
      * @return true is this method is present in the virtual table
      */
     boolean isInVirtualMethodTable();
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
  * thereof. Types, like fields and methods, are resolved through {@link ConstantPool constant pools}
  * .
  */
-public interface ResolvedJavaType extends JavaType {
+public interface ResolvedJavaType extends JavaType, ModifiersProvider {
 
     /**
      * Represents each of the several different parts of the runtime representation of a type which
@@ -54,7 +54,7 @@
     /**
      * Gets the encoding of (that is, a constant representing the value of) the specified part of
      * this type.
-     * 
+     *
      * @param r the part of this type
      * @return a constant representing a reference to the specified part of this type
      */
@@ -62,7 +62,7 @@
 
     /**
      * Checks whether this type has a finalizer method.
-     * 
+     *
      * @return {@code true} if this class has a finalizer
      */
     boolean hasFinalizer();
@@ -70,51 +70,52 @@
     /**
      * Checks whether this type has any finalizable subclasses so far. Any decisions based on this
      * information require the registration of a dependency, since this information may change.
-     * 
+     *
      * @return {@code true} if this class has any subclasses with finalizers
      */
     boolean hasFinalizableSubclass();
 
     /**
      * Checks whether this type is an interface.
-     * 
+     *
      * @return {@code true} if this type is an interface
      */
     boolean isInterface();
 
     /**
      * Checks whether this type is an instance class.
-     * 
+     *
      * @return {@code true} if this type is an instance class
      */
     boolean isInstanceClass();
 
     /**
      * Checks whether this type is an array class.
-     * 
+     *
      * @return {@code true} if this type is an array class
      */
     boolean isArray();
 
     /**
      * Checks whether this type is primitive.
-     * 
+     *
      * @return {@code true} if this type is primitive
      */
     boolean isPrimitive();
 
     /**
-     * Returns the Java language modifiers for this type, as an integer. The {@link Modifier} class
-     * should be used to decode the modifiers. Only the flags specified in the JVM specification
-     * will be included in the returned mask. This method is identical to
-     * {@link Class#getModifiers()} in terms of the value return for this type.
+     * {@inheritDoc}
+     * <p>
+     * Only the flags specified in the JVM specification will be included in the returned mask. This
+     * method is identical to {@link Class#getModifiers()} in terms of the value return for this
+     * type.
      */
     int getModifiers();
 
     /**
      * Checks whether this type is initialized. If a type is initialized it implies that it was
      * {@link #isLinked() linked} and that the static initializer has run.
-     * 
+     *
      * @return {@code true} if this type is initialized
      */
     boolean isInitialized();
@@ -127,7 +128,7 @@
     /**
      * Checks whether this type is linked and verified. When a type is linked the static initializer
      * has not necessarily run. An {@link #isInitialized() initialized} type is always linked.
-     * 
+     *
      * @return {@code true} if this type is linked
      */
     boolean isLinked();
@@ -141,7 +142,7 @@
 
     /**
      * Checks whether the specified object is an instance of this type.
-     * 
+     *
      * @param obj the object to test
      * @return {@code true} if the object is an instance of this type
      */
@@ -150,7 +151,7 @@
     /**
      * Returns this type if it is an exact type otherwise returns null. This type is exact if it is
      * void, primitive, final, or an array of a final or primitive type.
-     * 
+     *
      * @return this type if it is exact; {@code null} otherwise
      */
     ResolvedJavaType asExactType();
@@ -172,7 +173,7 @@
     /**
      * Walks the class hierarchy upwards and returns the least common class that is a superclass of
      * both the current and the given type.
-     * 
+     *
      * @return the least common type that is a super type of both the current and the given type, or
      *         {@code null} if primitive types are involved.
      */
@@ -194,7 +195,7 @@
      * <p>
      * If the compiler uses the result of this method for its compilation, it must register an
      * assumption because dynamic class loading can invalidate the result of this method.
-     * 
+     *
      * @return the unique concrete subclass for this type as described above
      */
     ResolvedJavaType findUniqueConcreteSubtype();
@@ -208,7 +209,7 @@
      * This resolution process only searches "up" the class hierarchy of this type. A broader search
      * that also walks "down" the hierarchy is implemented by
      * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}.
-     * 
+     *
      * @param method the method to select the implementation of
      * @return the concrete method that would be selected at runtime, or {@code null} if there is no
      *         concrete implementation of {@code method} in this type or any of its superclasses
@@ -223,7 +224,7 @@
      * <p>
      * If the compiler uses the result of this method for its compilation, it must register an
      * assumption because dynamic class loading can invalidate the result of this method.
-     * 
+     *
      * @param method the method A for which a unique concrete target is searched
      * @return the unique concrete target or {@code null} if no such target exists or assumptions
      *         are not supported by this runtime
@@ -237,7 +238,7 @@
      * is, for a single JVM execution the same order is returned each time this method is called. It
      * is also the "natural" order, which means that the JVM would expect the fields in this order
      * if no specific order is given.
-     * 
+     *
      * @param includeSuperclasses if true, then instance fields for the complete hierarchy of this
      *            type are included in the result
      * @return an array of instance fields
@@ -247,7 +248,7 @@
     /**
      * Returns the annotation for the specified type of this class, if such an annotation is
      * present.
-     * 
+     *
      * @param annotationClass the Class object corresponding to the annotation type
      * @return this element's annotation for the specified annotation type if present on this class,
      *         else {@code null}
@@ -257,7 +258,7 @@
     /**
      * Returns the instance field of this class (or one of its super classes) at the given offset,
      * or {@code null} if there is no such field.
-     * 
+     *
      * @param offset the offset of the field to look for
      * @return the field with the given offset, or {@code null} if there is no such field.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,70 @@
+/*
+ * 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.api.replacements;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Reflection operations on values represented as {@linkplain Constant constants} for the processing
+ * of snippets. Snippets need a direct access to the value of object constants, which is not allowed
+ * in other parts of Graal to enforce compiler-VM separation.
+ * <p>
+ * This interface must not be used in Graal code that is not related to snippet processing.
+ */
+public interface SnippetReflectionProvider {
+
+    /**
+     * Creates a boxed {@link Kind#Object object} constant.
+     *
+     * @param object the object value to box
+     * @return a constant containing {@code object}
+     */
+    Constant forObject(Object object);
+
+    /**
+     * Returns the object reference the given constant represents. The constant must have kind
+     * {@link Kind#Object}.
+     *
+     * @param constant the to access
+     * @return the object value of the constant
+     */
+    Object asObject(Constant constant);
+
+    /**
+     * Creates a boxed constant for the given kind from an Object. The object needs to be of the
+     * Java boxed type corresponding to the kind.
+     *
+     * @param kind the kind of the constant to create
+     * @param value the Java boxed value: a {@link Byte} instance for {@link Kind#Byte}, etc.
+     * @return the boxed copy of {@code value}
+     */
+    Constant forBoxed(Kind kind, Object value);
+
+    /**
+     * Returns the value of this constant as a boxed Java value.
+     *
+     * @param constant the constant to box
+     * @return the value of the constant
+     */
+    Object asBoxedValue(Constant constant);
+}
--- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Graal.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Graal.java	Wed Apr 23 15:48:38 2014 +0200
@@ -38,7 +38,7 @@
     public static GraalRuntime getRuntime() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
-            Class cc = Reflection.getCallerClass();
+            Class<?> cc = Reflection.getCallerClass();
             if (cc.getClassLoader() != null) {
                 sm.checkPermission(ACCESS_PERMISSION);
             }
@@ -60,7 +60,7 @@
     public static <T> T getRequiredCapability(Class<T> clazz) {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
-            Class cc = Reflection.getCallerClass();
+            Class<?> cc = Reflection.getCallerClass();
             if (cc.getClassLoader() != null) {
                 sm.checkPermission(ACCESS_PERMISSION);
             }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1647,9 +1647,14 @@
     public final void shrl(Register dst, int imm8) {
         assert isShiftCount(imm8) : "illegal shift count";
         int encode = prefixAndEncode(dst.encoding);
-        emitByte(0xC1);
-        emitByte(0xE8 | encode);
-        emitByte(imm8);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xE8 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xE8 | encode);
+            emitByte(imm8);
+        }
     }
 
     public final void shrl(Register dst) {
@@ -1658,6 +1663,82 @@
         emitByte(0xE8 | encode);
     }
 
+    public final void roll(Register dst, int imm8) {
+        assert isShiftCount(imm8) : "illegal shift count";
+        int encode = prefixAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xC0 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xC0 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void roll(Register dst) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void rorl(Register dst, int imm8) {
+        assert isShiftCount(imm8) : "illegal shift count";
+        int encode = prefixAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xC8 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xC8 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void rorl(Register dst) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xC8 | encode);
+    }
+
+    public final void rolq(Register dst, int imm8) {
+        assert isShiftCount(imm8) : "illegal shift count";
+        int encode = prefixqAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xC0 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xC0 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void rolq(Register dst) {
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void rorq(Register dst, int imm8) {
+        assert isShiftCount(imm8) : "illegal shift count";
+        int encode = prefixqAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xC8 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xC8 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void rorq(Register dst) {
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xC8 | encode);
+    }
+
     public final void sqrtsd(Register dst, AMD64Address src) {
         assert dst.getRegisterCategory() == AMD64.XMM;
         emitByte(0xF2);
@@ -2442,9 +2523,14 @@
     public final void shrq(Register dst, int imm8) {
         assert isShiftCount(imm8 >> 1) : "illegal shift count";
         int encode = prefixqAndEncode(dst.encoding);
-        emitByte(0xC1);
-        emitByte(0xE8 | encode);
-        emitByte(imm8);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xE8 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xE8 | encode);
+            emitByte(imm8);
+        }
     }
 
     public final void shrq(Register dst) {
@@ -2512,6 +2598,32 @@
         emitInt(imm32);
     }
 
+    public final void xaddl(AMD64Address dst, Register src) {
+        prefix(dst, src);
+        emitByte(0x0F);
+        emitByte(0xC1);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void xaddq(AMD64Address dst, Register src) {
+        prefixq(dst, src);
+        emitByte(0x0F);
+        emitByte(0xC1);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void xchgl(Register dst, AMD64Address src) {
+        prefix(src, dst);
+        emitByte(0x87);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void xchgq(Register dst, AMD64Address src) {
+        prefixq(src, dst);
+        emitByte(0x87);
+        emitOperandHelper(dst, src);
+    }
+
     public final void xorq(Register dst, int imm32) {
         emitArithImm32q(6, dst, imm32);
     }
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,18 +25,15 @@
 import static com.oracle.graal.api.code.MemoryBarriers.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 
-import java.lang.reflect.*;
-
-import com.amd.okra.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hsail.*;
 
 /**
  * This class contains routines to emit HSAIL assembly code.
  */
-public class HSAILAssembler extends AbstractHSAILAssembler {
+public abstract class HSAILAssembler extends AbstractHSAILAssembler {
 
     /**
      * Stack size in bytes (used to keep track of spilling).
@@ -87,35 +84,13 @@
      * references get updated by the GC whenever the GC moves an Object.
      *
      * @param a the destination register
-     * @param obj the Object being moved
+     * @param src the Object Constant being moved
      */
-    public final void mov(Register a, Object obj) {
-        String regName = "$d" + a.encoding();
-        // For a null object simply move 0x0 into the destination register.
-        if (obj == null) {
-            emitString("mov_b64 " + regName + ", 0x0;  // null object");
-        } else {
-            // Get a JNI reference handle to the object.
-            long refHandle = OkraUtil.getRefHandle(obj);
-            // Get the clasname of the object for emitting a comment.
-            Class<?> clazz = obj.getClass();
-            String className = clazz.getName();
-            String comment = "// handle for object of type " + className;
-            // If the object is an array note the array length in the comment.
-            if (className.startsWith("[")) {
-                comment += ", length " + Array.getLength(obj);
-            }
-            // First move the reference handle into a register.
-            emitString("mov_b64 " + regName + ", 0x" + Long.toHexString(refHandle) + ";    " + comment);
-            // Next load the Object addressed by this reference handle into the destination reg.
-            emitString("ld_global_u64 " + regName + ", [" + regName + "];");
-        }
-
-    }
+    public abstract void mov(Register a, Constant src);
 
     public final void emitMov(Kind kind, Value dst, Value src) {
         if (isRegister(dst) && isConstant(src) && kind.getStackKind() == Kind.Object) {
-            mov(asRegister(dst), (asConstant(src)).asObject());
+            mov(asRegister(dst), asConstant(src));
         } else {
             String argtype = getArgTypeFromKind(kind).substring(1);
             emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";");
@@ -127,7 +102,7 @@
         if (reg instanceof RegisterValue) {
             storeValue = HSAIL.mapRegister(reg);
         } else if (reg instanceof Constant) {
-            storeValue = ((Constant) reg).asBoxedValue().toString();
+            storeValue = ((Constant) reg).toValueString();
         }
         emitString(instr + " " + storeValue + ", " + mapAddress(addr) + ";");
     }
@@ -313,14 +288,14 @@
      *            float compares.
      * @param isUnsignedCompare - flag specifying if this is a compare of unsigned values.
      */
-    public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) {
+    public void emitCompare(Kind compareKind, Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) {
         // Formulate the prefix of the instruction.
         // if unordered is true, it should be ignored unless the src type is f32 or f64
-        String argType = getArgTypeFromKind(src1.getKind().getStackKind());
+        String argType = getArgTypeFromKind(compareKind);
         String unorderedPrefix = (argType.startsWith("f") && unordered ? "u" : "");
         String prefix = "cmp_" + condition + unorderedPrefix + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : argType);
         // Generate a comment for debugging purposes
-        String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) && (asConstant(src1).asObject() == null) ? " // null test " : "");
+        String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) && (asConstant(src1).isNull()) ? " // null test " : "");
         // Emit the instruction.
         emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";" + comment);
     }
@@ -367,8 +342,7 @@
                 case Long:
                     return "0x" + Long.toHexString(consrc.asLong());
                 case Object:
-                    Object obj = consrc.asObject();
-                    if (obj == null) {
+                    if (consrc.isNull()) {
                         return "0";
                     } else {
                         throw GraalInternalError.shouldNotReachHere("unknown type: " + src);
@@ -533,7 +507,7 @@
      */
     private void emitWithOptionalTestForNull(boolean testForNull, String mnemonic, Value result, Value... sources) {
         if (testForNull) {
-            emitCompare(result, Constant.forLong(0), "eq", false, true);
+            emitCompare(Kind.Long, result, Constant.forLong(0), "eq", false, true);
         }
         emitForceUnsigned(mnemonic, result, sources);
         if (testForNull) {
@@ -550,8 +524,8 @@
      * @param newValue the new value that will be written to the memory location if the cmpValue
      *            comparison matches
      */
-    public void emitAtomicCas(AllocatableValue result, HSAILAddress address, Value cmpValue, Value newValue) {
-        emitString(String.format("atomic_cas_global_b%d   %s, %s, %s, %s;", getArgSize(cmpValue), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(cmpValue),
+    public void emitAtomicCas(Kind accessKind, AllocatableValue result, HSAILAddress address, Value cmpValue, Value newValue) {
+        emitString(String.format("atomic_cas_global_b%d   %s, %s, %s, %s;", getArgSizeFromKind(accessKind), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(cmpValue),
                         mapRegOrConstToString(newValue)));
     }
 
@@ -560,10 +534,17 @@
      *
      * @param result result operand that gets the original contents of the memory location
      * @param address the memory location
-     * @param deltaValue the amount to add
+     * @param delta the amount to add
      */
-    public void emitAtomicAdd(AllocatableValue result, HSAILAddress address, Value deltaValue) {
-        emitString(String.format("atomic_add_global_u%d   %s, %s, %s;", getArgSize(result), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(deltaValue)));
+    public void emitAtomicAdd(AllocatableValue result, HSAILAddress address, Value delta) {
+        // ensure result and delta agree (this should probably be at some higher level)
+        Value mydelta = delta;
+        if (!isConstant(delta) && (getArgSize(result) != getArgSize(delta))) {
+            emitConvert(result, delta, result.getKind(), delta.getKind());
+            mydelta = result;
+        }
+        String prefix = getArgTypeForceUnsigned(result);
+        emitString(String.format("atomic_add_global_%s   %s, %s, %s;", prefix, HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(mydelta)));
     }
 
     /**
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,9 +27,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class PTXAssembler extends AbstractPTXAssembler {
 
@@ -370,7 +370,7 @@
             assert var instanceof Variable;
             assert val instanceof Constant;
             Constant constant = (Constant) val;
-            return ("[" + ((space == PTXStateSpace.Parameter) ? emitParameter((Variable) var) : emitRegister((Variable) var, false)) + " + " + constant.asBoxedValue() + "]");
+            return ("[" + ((space == PTXStateSpace.Parameter) ? emitParameter((Variable) var) : emitRegister((Variable) var, false)) + " + " + constant.toValueString() + "]");
         }
 
         @Override
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXMacroAssembler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXMacroAssembler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 
 public class PTXMacroAssembler extends PTXAssembler {
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,7 +25,7 @@
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.sparc.*;
 
 public class SPARCAddress extends AbstractAddress {
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -61,7 +61,7 @@
         byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
         compResult.setTargetCode(targetCode, targetCode.length);
 
-        InstalledCode code = codeCache.addMethod(method, compResult, null);
+        InstalledCode code = codeCache.addMethod(method, compResult, null, null);
 
         DisassemblerProvider dis = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getDisassembler();
         if (dis != null) {
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,7 @@
  */
 package com.oracle.graal.baseline;
 
-import static com.oracle.graal.phases.GraalOptions.*;
-import static java.lang.reflect.Modifier.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
@@ -33,27 +32,49 @@
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.alloc.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 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.java.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
+import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.*;
 
-public class BaselineBytecodeParser extends AbstractBytecodeParser<Value, LIRFrameStateBuilder> implements BytecodeParserTool {
+public class BaselineBytecodeParser extends AbstractBytecodeParser<Value, BaselineFrameStateBuilder> implements BytecodeParserTool {
     private Backend backend;
     protected LIRGenerator gen;
     private LIRGenerationResult lirGenRes;
     private BytecodeLIRBuilder lirBuilder;
+    @SuppressWarnings("unused") private BciBlock[] loopHeaders;
+    private LocalLiveness liveness;
+    private BciBlockBitMap blockVisited;
+
+    private static class BciBlockBitMap {
+        BitSet bitSet;
+
+        public BciBlockBitMap(BciBlockMapping blockMap) {
+            bitSet = new BitSet(blockMap.blocks.size());
+        }
+
+        public boolean get(BciBlock block) {
+            return bitSet.get(block.getId());
+        }
+
+        public void set(BciBlock block) {
+            bitSet.set(block.getId());
+        }
+    }
 
     public BaselineBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts,
-                    LIRFrameStateBuilder frameState, BytecodeStream stream, ProfilingInfo profilingInfo, ConstantPool constantPool, int entryBCI, Backend backend) {
+                    BaselineFrameStateBuilder frameState, BytecodeStream stream, ProfilingInfo profilingInfo, ConstantPool constantPool, int entryBCI, Backend backend) {
 
         super(metaAccess, method, graphBuilderConfig, optimisticOpts, frameState, stream, profilingInfo, constantPool, entryBCI);
         this.backend = backend;
@@ -74,6 +95,9 @@
 
             // compute the block map, setup exception handlers and get the entrypoint(s)
             BciBlockMapping blockMap = BciBlockMapping.create(method);
+            loopHeaders = blockMap.loopHeaders;
+            liveness = blockMap.liveness;
+            blockVisited = new BciBlockBitMap(blockMap);
             // add predecessors
             for (BciBlock block : blockMap.blocks) {
                 for (BciBlock successor : block.getSuccessors()) {
@@ -81,13 +105,15 @@
                 }
             }
 
-            if (isSynchronized(method.getModifiers())) {
+            if (method.isSynchronized()) {
                 throw GraalInternalError.unimplemented("Handle synchronized methods");
             }
 
-            // TODO: clear non live locals
+            frameState = new BaselineFrameStateBuilder(method);
+            frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true);
 
             currentBlock = blockMap.startBlock;
+            blockMap.startBlock.entryState = frameState;
             if (blockMap.startBlock.isLoopHeader) {
                 throw GraalInternalError.unimplemented("Handle start block as loop header");
             }
@@ -95,7 +121,7 @@
             // add loops ? how do we add looks when we haven't parsed the bytecode?
 
             // create the control flow graph
-            LIRControlFlowGraph cfg = new LIRControlFlowGraph(blockMap.blocks.toArray(new BciBlock[0]), new Loop[0]);
+            BaselineControlFlowGraph cfg = new BaselineControlFlowGraph(blockMap);
 
             BlocksToDoubles blockProbabilities = new BlocksToDoubles(blockMap.blocks.size());
             for (BciBlock b : blockMap.blocks) {
@@ -235,8 +261,7 @@
 
     @Override
     protected Value genIntegerMul(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
+        return gen.emitMul(x, y);
     }
 
     @Override
@@ -354,12 +379,6 @@
     }
 
     @Override
-    protected void genGoto() {
-        assert currentBlock.numNormalSuccessors() == 1;
-        gen.emitJump(LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, 0));
-    }
-
-    @Override
     protected Value genObjectEquals(Value x, Value y) {
         // TODO Auto-generated method stub
         throw GraalInternalError.unimplemented("Auto-generated method stub");
@@ -377,7 +396,7 @@
         BciBlock trueBlock = currentBlock.getSuccessors().get(0);
         BciBlock falseBlock = currentBlock.getSuccessors().get(1);
         if (trueBlock == falseBlock) {
-            gen.emitJump(LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, 0));
+            genGoto();
             return;
         }
 
@@ -396,8 +415,8 @@
             }
         }
 
-        LabelRef trueDestination = LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, 0);
-        LabelRef falseDestination = LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, 1);
+        LabelRef trueDestination = getSuccessor(0);
+        LabelRef falseDestination = getSuccessor(1);
 
         gen.emitCompareBranch(x.getKind(), x, y, cond, false, trueDestination, falseDestination, probability);
     }
@@ -546,13 +565,7 @@
     }
 
     @Override
-    protected void setBlockSuccessor(Value switchNode, int i, Value createBlockTarget) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genIntegerSwitch(Value value, int size, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    protected void genIntegerSwitch(Value value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
         // TODO Auto-generated method stub
         throw GraalInternalError.unimplemented("Auto-generated method stub");
     }
@@ -570,28 +583,127 @@
         return v;
     }
 
-    @Override
-    protected Value genDeoptimization() {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    private void createTarget(BciBlock block) {
+        assert block != null && frameState != null;
+        assert !block.isExceptionEntry || frameState.stackSize() == 1;
+
+        if (!blockVisited.get(block)) {
+            /*
+             * This is the first time we see this block as a branch target. Create and return a
+             * placeholder that later can be replaced with a MergeNode when we see this block again.
+             */
+            blockVisited.set(block);
+            if (block.getPredecessorCount() > 1) {
+                /*
+                 * If there are more than one predecessors we have to ensure that we are not passing
+                 * constants to the new framestate otherwise we will get interfacing problems.
+                 */
+                moveConstantsToVariables();
+            }
+            block.entryState = frameState.copy();
+            block.entryState.clearNonLiveLocals(block, liveness, true);
+
+            Debug.log("createTarget %s: first visit", block);
+            return;
+        }
+
+        // We already saw this block before, so we have to merge states.
+        if (!((BaselineFrameStateBuilder) block.entryState).isCompatibleWith(frameState)) {
+            throw new BailoutException("stacks do not match; bytecodes would not verify");
+        }
+
+        if (block.isLoopHeader) {
+            assert currentBlock == null || currentBlock.getId() >= block.getId() : "must be backward branch";
+            if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) {
+                // this is the only successor of the current block so we can adjust
+                adaptFramestate((BaselineFrameStateBuilder) block.entryState);
+                return;
+            }
+            GraalInternalError.unimplemented("Loops not yet supported");
+        }
+        assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
+
+        /*
+         * This is the second time we see this block. Create the actual MergeNode and the End Node
+         * for the already existing edge. For simplicity, we leave the placeholder in the graph and
+         * just append the new nodes after the placeholder.
+         */
+        if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) {
+            // this is the only successor of the current block so we can adjust
+            adaptFramestate((BaselineFrameStateBuilder) block.entryState);
+            return;
+        }
+        GraalInternalError.unimplemented("second block visit not yet implemented");
+
+        // merge frame states e.g. block.entryState.merge(mergeNode, target.state);
+
+        Debug.log("createTarget %s: merging state", block);
     }
 
-    @Override
-    protected Value createBlockTarget(double probability, BciBlock bciBlock, AbstractFrameStateBuilder<Value> stateAfter) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    private void moveConstantsToVariables() {
+        Debug.log("moveConstantsToVariables: framestate before: %s", frameState);
+        for (int i = 0; i < frameState.stackSize(); i++) {
+            Value src = frameState.stackAt(i);
+            if (src instanceof Constant) {
+                AllocatableValue dst = gen.newVariable(src.getPlatformKind());
+                gen.emitMove(dst, src);
+                frameState.storeStack(i, dst);
+                Debug.log("introduce new variabe %s for stackslot %d (end of block %s", dst, i, currentBlock);
+            }
+        }
+        for (int i = 0; i < frameState.localsSize(); i++) {
+            Value src = frameState.localAt(i);
+            if (src instanceof Constant) {
+                AllocatableValue dst = gen.newVariable(src.getPlatformKind());
+                gen.emitMove(dst, src);
+                frameState.storeLocal(i, dst);
+                Debug.log("introduce new variabe %s for local %d (end of block %s", dst, i, currentBlock);
+            }
+        }
+        Debug.log("moveConstantsToVariables: framestate after: %s", frameState);
+    }
+
+    private static void adaptValues(Value dst, Value src, PhiResolver resolver) {
+        if (dst == null) {
+            return;
+        }
+        assert src != null : "Source is null but Destination is not!";
+
+        if (!dst.equals(src)) {
+            resolver.move(dst, src);
+        }
+    }
+
+    private void adaptFramestate(BaselineFrameStateBuilder other) {
+        assert frameState.isCompatibleWith(other) : "framestates not compatible!";
+        PhiResolver resolver = new PhiResolver(gen);
+        for (int i = 0; i < frameState.stackSize(); i++) {
+            Value src = frameState.stackAt(i);
+            Value dst = other.stackAt(i);
+            adaptValues(dst, src, resolver);
+        }
+        for (int i = 0; i < frameState.localsSize(); i++) {
+            Value src = frameState.localAt(i);
+            Value dst = other.localAt(i);
+            adaptValues(dst, src, resolver);
+        }
+        resolver.dispose();
     }
 
     @Override
     protected void processBlock(BciBlock block) {
+        frameState = (BaselineFrameStateBuilder) block.entryState;
+        setCurrentFrameState(frameState);
         currentBlock = block;
         iterateBytecodesForBlock(block);
     }
 
-    @Override
-    protected void appendGoto(Value target) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    private boolean isBlockEnd() {
+        List<LIRInstruction> l = gen.getResult().getLIR().getLIRforBlock(currentBlock);
+        if (l.isEmpty()) {
+            return false;
+        }
+        return l.get(l.size() - 1) instanceof BlockEndOp;
     }
 
     @Override
@@ -605,6 +717,14 @@
             assert block.getPredecessorCount() > 0;
         }
 
+        if (block.isLoopHeader) {
+            /*
+             * We need to preserve the frame state builder of the loop header so that we can merge
+             * values for phi functions, so make a copy of it.
+             */
+            block.entryState = frameState.copy();
+
+        }
         int endBCI = stream.endBCI();
 
         stream.setBCI(block.startBci);
@@ -620,19 +740,20 @@
 
             processBytecode(bci, opcode);
 
-            if (gen.hasBlockEnd(currentBlock)) {
-                break;
-            }
-
             stream.next();
             bci = stream.currentBCI();
 
+            if (isBlockEnd()) {
+                break;
+            }
+
             if (bci < endBCI) {
                 if (bci > block.endBci) {
-                    assert block.numNormalSuccessors() == 1;
-                    assert !block.getSuccessor(0).isExceptionEntry;
-                    // we fell through to the next block, add a goto and break
-                    genGoto();
+                    if (block.numNormalSuccessors() == 1) {
+                        assert !block.getSuccessor(0).isExceptionEntry;
+                        // we fell through to the next block, add a goto and break
+                        genGoto();
+                    }
                     break;
                 }
             }
@@ -646,4 +767,14 @@
         frameState.storeLocal(i, x);
     }
 
+    LabelRef getSuccessor(int index) {
+        createTarget(currentBlock.getSuccessor(index));
+        return LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, index);
+    }
+
+    @Override
+    protected void genGoto() {
+        gen.emitJump(getSuccessor(0));
+    }
+
 }
\ No newline at end of file
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.baseline;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -57,7 +57,7 @@
         ConstantPool constantPool = method.getConstantPool();
         TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
 
-        LIRFrameStateBuilder frameState = new LIRFrameStateBuilder(method);
+        BaselineFrameStateBuilder frameState = new BaselineFrameStateBuilder(method);
 
         BaselineBytecodeParser parser = new BaselineBytecodeParser(metaAccess, method, graphBuilderConfig, optimisticOpts, frameState, stream, profilingInfo, constantPool, entryBCI, backend);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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.baseline;
+
+import java.util.*;
+
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.java.BciBlockMapping.BciBlock;
+
+public class BaselineControlFlowGraph implements AbstractControlFlowGraph<BciBlock> {
+
+    private BciBlock[] blocks;
+    private Collection<Loop<BciBlock>> loops;
+    private BitSet visited;
+
+    public BaselineControlFlowGraph(BciBlockMapping blockMap) {
+        blocks = blockMap.blocks.toArray(new BciBlock[0]);
+        loops = new ArrayList<>();
+        computeLoopInformation();
+    }
+
+    public BciBlock[] getBlocks() {
+        return blocks;
+    }
+
+    public Collection<Loop<BciBlock>> getLoops() {
+        return loops;
+    }
+
+    public BciBlock getStartBlock() {
+        if (blocks.length > 0) {
+            return blocks[0];
+        }
+        return null;
+    }
+
+    private void computeLoopInformation() {
+        visited = new BitSet(blocks.length);
+        Deque<BaselineLoop> stack = new ArrayDeque<>();
+        for (int i = blocks.length - 1; i >= 0; i--) {
+            BciBlock block = blocks[i];
+            calcLoop(block, stack);
+        }
+    }
+
+    private void calcLoop(BciBlock block, Deque<BaselineLoop> stack) {
+        if (visited.get(block.getId())) {
+            return;
+        }
+        visited.set(block.getId());
+        if (block.isLoopEnd()) {
+            BciBlock loopHeader = getLoopHeader(block);
+            BaselineLoop l = new BaselineLoop(stack.peek(), loops.size(), loopHeader);
+            loops.add(l);
+            stack.push(l);
+        }
+        block.loop = stack.peek();
+        if (block.isLoopHeader()) {
+            assert block.loop.header.equals(block);
+            stack.pop();
+        }
+        for (BciBlock pred : block.getPredecessors()) {
+            calcLoop(pred, stack);
+        }
+    }
+
+    private static BciBlock getLoopHeader(BciBlock block) {
+        assert block.isLoopEnd();
+        for (BciBlock sux : block.getSuccessors()) {
+            if (sux.isLoopHeader() && sux.getId() <= block.getId() && block.loops == sux.loops) {
+                return sux;
+            }
+        }
+        throw GraalInternalError.shouldNotReachHere("No loop header found for " + block);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineFrameStateBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,103 @@
+/*
+ * 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.baseline;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.java.*;
+
+public class BaselineFrameStateBuilder extends AbstractFrameStateBuilder<Value, BaselineFrameStateBuilder> {
+
+    private static final Value[] EMPTY_ARRAY = new Value[0];
+
+    public BaselineFrameStateBuilder(ResolvedJavaMethod method) {
+        // we always need at least one stack slot (for exceptions)
+        super(method, new Value[method.getMaxLocals()], new Value[Math.max(1, method.getMaxStackSize())], EMPTY_ARRAY);
+    }
+
+    protected BaselineFrameStateBuilder(BaselineFrameStateBuilder other) {
+        super(other);
+    }
+
+    @Override
+    protected Value[] getEmtpyArray() {
+        return EMPTY_ARRAY;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[locals: [");
+        for (int i = 0; i < locals.length; i++) {
+            sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString());
+        }
+        sb.append("] stack: [");
+        for (int i = 0; i < stackSize; i++) {
+            sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString());
+        }
+        sb.append("] locks: [");
+        for (int i = 0; i < lockedObjects.length; i++) {
+            sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString());
+        }
+        sb.append("]");
+        if (rethrowException) {
+            sb.append(" rethrowException");
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+
+    @Override
+    public BaselineFrameStateBuilder copy() {
+        return new BaselineFrameStateBuilder(this);
+    }
+
+    private static boolean isCompatible(Value x, Value y) {
+        if (x == null && y == null) {
+            return true;
+        }
+        if ((x == null || y == null) || (x.getKind() != y.getKind())) {
+            return false;
+        }
+        return true;
+
+    }
+
+    @Override
+    public boolean isCompatibleWith(BaselineFrameStateBuilder other) {
+        assert method.equals(other.method) && localsSize() == other.localsSize() : "Can only compare frame states of the same method";
+
+        if (stackSize() != other.stackSize()) {
+            return false;
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            if (!isCompatible(stackAt(i), other.stackAt(i))) {
+                return false;
+            }
+        }
+        if (lockedObjects.length != other.lockedObjects.length) {
+            return false;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineLoop.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * 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.baseline;
+
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.java.BciBlockMapping.BciBlock;
+
+public class BaselineLoop extends Loop<BciBlock> {
+
+    protected BaselineLoop(Loop<BciBlock> parent, int index, BciBlock header) {
+        super(parent, index, header);
+    }
+
+    @Override
+    public long numBackedges() {
+        // currently only loops with one backedge are supported
+        return 1;
+    }
+
+}
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +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.baseline;
-
-import java.util.*;
-
-import com.oracle.graal.nodes.cfg.*;
-
-public class LIRBlock extends AbstractBlockBase<LIRBlock> {
-
-    public LIRBlock(int id) {
-        this.id = id;
-        predecessors = Collections.emptyList();
-        successors = Collections.emptyList();
-    }
-
-    public Loop getLoop() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public int getLoopDepth() {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    public boolean isLoopEnd() {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    public boolean isLoopHeader() {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    public boolean isExceptionEntry() {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-}
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * 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.baseline;
-
-import com.oracle.graal.java.BciBlockMapping.BciBlock;
-import com.oracle.graal.nodes.cfg.*;
-
-public class LIRControlFlowGraph implements AbstractControlFlowGraph<BciBlock> {
-
-    private BciBlock[] blocks;
-    private Loop[] loops;
-
-    public LIRControlFlowGraph(BciBlock[] blocks, Loop[] loops) {
-        this.blocks = blocks;
-        this.loops = loops;
-    }
-
-    public BciBlock[] getBlocks() {
-        return blocks;
-    }
-
-    public Loop[] getLoops() {
-        return loops;
-    }
-
-    public BciBlock getStartBlock() {
-        if (blocks.length > 0) {
-            return blocks[0];
-        }
-        return null;
-    }
-
-}
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*
- * 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.baseline;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.java.*;
-
-public class LIRFrameStateBuilder extends AbstractFrameStateBuilder<Value> {
-
-    private final Value[] locals;
-    private final Value[] stack;
-    private Value[] lockedObjects;
-
-    public LIRFrameStateBuilder(ResolvedJavaMethod method) {
-        super(method);
-
-        this.locals = new Value[method.getMaxLocals()];
-        // we always need at least one stack slot (for exceptions)
-        this.stack = new Value[Math.max(1, method.getMaxStackSize())];
-    }
-
-    protected LIRFrameStateBuilder(LIRFrameStateBuilder other) {
-        super(other);
-        // TODO Auto-generated constructor stub
-        locals = other.locals;
-        stack = other.stack;
-        lockedObjects = other.lockedObjects;
-    }
-
-    @Override
-    public int localsSize() {
-        return locals.length;
-    }
-
-    @Override
-    public Value localAt(int i) {
-        return locals[i];
-    }
-
-    @Override
-    public Value stackAt(int i) {
-        return stack[i];
-    }
-
-    @Override
-    public Value loadLocal(int i) {
-        Value x = locals[i];
-        assert !isTwoSlot(x.getKind()) || locals[i + 1] == null;
-        assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind());
-        return x;
-    }
-
-    @Override
-    public void storeLocal(int i, Value x) {
-        assert x == null || x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x;
-        locals[i] = x;
-        if (x != null && isTwoSlot(x.getKind())) {
-            // if this is a double word, then kill i+1
-            locals[i + 1] = null;
-        }
-        if (x != null && i > 0) {
-            Value p = locals[i - 1];
-            if (p != null && isTwoSlot(p.getKind())) {
-                // if there was a double word at i - 1, then kill it
-                locals[i - 1] = null;
-            }
-        }
-    }
-
-    @Override
-    public void storeStack(int i, Value x) {
-        assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values";
-        stack[i] = x;
-    }
-
-    @Override
-    public void push(Kind kind, Value x) {
-        assert x.getKind() != Kind.Void && x.getKind() != Kind.Illegal;
-        xpush(assertKind(kind, x));
-        if (isTwoSlot(kind)) {
-            xpush(null);
-        }
-    }
-
-    @Override
-    public void xpush(Value x) {
-        assert x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal);
-        stack[stackSize++] = x;
-    }
-
-    @Override
-    public void ipush(Value x) {
-        xpush(assertInt(x));
-    }
-
-    @Override
-    public void fpush(Value x) {
-        xpush(assertFloat(x));
-    }
-
-    @Override
-    public void apush(Value x) {
-        xpush(assertObject(x));
-    }
-
-    @Override
-    public void lpush(Value x) {
-        xpush(assertLong(x));
-    }
-
-    @Override
-    public void dpush(Value x) {
-        xpush(assertDouble(x));
-
-    }
-
-    @Override
-    public void pushReturn(Kind kind, Value x) {
-        if (kind != Kind.Void) {
-            push(kind.getStackKind(), x);
-        }
-    }
-
-    @Override
-    public Value pop(Kind kind) {
-        assert kind != Kind.Void;
-        if (isTwoSlot(kind)) {
-            xpop();
-        }
-        return assertKind(kind, xpop());
-    }
-
-    @Override
-    public Value xpop() {
-        Value result = stack[--stackSize];
-        return result;
-    }
-
-    @Override
-    public Value ipop() {
-        return assertInt(xpop());
-    }
-
-    @Override
-    public Value fpop() {
-        return assertFloat(xpop());
-    }
-
-    @Override
-    public Value apop() {
-        return assertObject(xpop());
-    }
-
-    @Override
-    public Value lpop() {
-        assertHigh(xpop());
-        return assertLong(xpop());
-    }
-
-    @Override
-    public Value dpop() {
-        assertHigh(xpop());
-        return assertDouble(xpop());
-    }
-
-    @Override
-    public Value[] popArguments(int slotSize, int argSize) {
-        int base = stackSize - slotSize;
-        Value[] r = new Value[argSize];
-        int argIndex = 0;
-        int stackindex = 0;
-        while (stackindex < slotSize) {
-            Value element = stack[base + stackindex];
-            assert element != null;
-            r[argIndex++] = element;
-            stackindex += stackSlots(element.getKind());
-        }
-        stackSize = base;
-        return r;
-    }
-
-    @Override
-    public Value peek(int argumentNumber) {
-        int idx = stackSize() - 1;
-        for (int i = 0; i < argumentNumber; i++) {
-            if (stackAt(idx) == null) {
-                idx--;
-                assert isTwoSlot(stackAt(idx).getKind());
-            }
-            idx--;
-        }
-        return stackAt(idx);
-    }
-
-    private static Value assertKind(Kind kind, Value x) {
-        assert x != null && x.getKind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind());
-        return x;
-    }
-
-    private static Value assertLong(Value x) {
-        assert x != null && (x.getKind() == Kind.Long);
-        return x;
-    }
-
-    private static Value assertInt(Value x) {
-        assert x != null && (x.getKind() == Kind.Int);
-        return x;
-    }
-
-    private static Value assertFloat(Value x) {
-        assert x != null && (x.getKind() == Kind.Float);
-        return x;
-    }
-
-    private static Value assertObject(Value x) {
-        assert x != null && (x.getKind() == Kind.Object);
-        return x;
-    }
-
-    private static Value assertDouble(Value x) {
-        assert x != null && (x.getKind() == Kind.Double);
-        return x;
-    }
-
-    private static void assertHigh(Value x) {
-        assert x == null;
-    }
-}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,8 +35,9 @@
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.amd64.*;
@@ -51,6 +52,7 @@
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary1Op;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2MemoryOp;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2Op;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2RegOp;
 import com.oracle.graal.lir.amd64.AMD64Compare.CompareMemoryOp;
 import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
@@ -67,10 +69,7 @@
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp;
 import com.oracle.graal.lir.amd64.AMD64Move.ZeroExtendLoadOp;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -589,8 +588,7 @@
         append(new DivRemOp(op, rax, asAllocatable(b), state));
     }
 
-    public Value[] emitIntegerDivRem(Value a, Value b, DeoptimizingNode deopting) {
-        LIRFrameState state = state(deopting);
+    public Value[] emitIntegerDivRem(Value a, Value b, LIRFrameState state) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 emitDivRem(IDIVREM, a, b, state);
@@ -604,13 +602,13 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitDiv(Value a, Value b, LIRFrameState state) {
         switch (a.getKind().getStackKind()) {
             case Int:
-                emitDivRem(IDIV, a, b, state(deopting));
+                emitDivRem(IDIV, a, b, state);
                 return emitMove(RAX_I);
             case Long:
-                emitDivRem(LDIV, a, b, state(deopting));
+                emitDivRem(LDIV, a, b, state);
                 return emitMove(RAX_L);
             case Float: {
                 Variable result = newVariable(a.getPlatformKind());
@@ -628,13 +626,13 @@
     }
 
     @Override
-    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitRem(Value a, Value b, LIRFrameState state) {
         switch (a.getKind().getStackKind()) {
             case Int:
-                emitDivRem(IREM, a, b, state(deopting));
+                emitDivRem(IREM, a, b, state);
                 return emitMove(RDX_I);
             case Long:
-                emitDivRem(LREM, a, b, state(deopting));
+                emitDivRem(LREM, a, b, state);
                 return emitMove(RDX_L);
             case Float: {
                 Variable result = newVariable(a.getPlatformKind());
@@ -652,8 +650,7 @@
     }
 
     @Override
-    public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
-        LIRFrameState state = state(deopting);
+    public Variable emitUDiv(Value a, Value b, LIRFrameState state) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 emitDivRem(IUDIV, a, b, state);
@@ -667,8 +664,7 @@
     }
 
     @Override
-    public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
-        LIRFrameState state = state(deopting);
+    public Variable emitURem(Value a, Value b, LIRFrameState state) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 emitDivRem(IUREM, a, b, state);
@@ -765,9 +761,9 @@
         }
     }
 
-    private AllocatableValue emitConvert1Op(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) {
+    private AllocatableValue emitConvert2RegOp(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) {
         Variable result = newVariable(kind);
-        append(new Unary1Op(op, result, input));
+        append(new Unary2RegOp(op, result, input));
         return result;
     }
 
@@ -850,7 +846,7 @@
     public Value emitNarrow(Value inputVal, int bits) {
         if (inputVal.getKind() == Kind.Long && bits <= 32) {
             // TODO make it possible to reinterpret Long as Int in LIR without move
-            return emitConvert1Op(Kind.Int, L2I, asAllocatable(inputVal));
+            return emitConvert2RegOp(Kind.Int, L2I, asAllocatable(inputVal));
         } else {
             return inputVal;
         }
@@ -1020,7 +1016,7 @@
     }
 
     @Override
-    protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
+    public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
         // a temp is needed for loading object constants
         boolean needsTemp = key.getKind() == Kind.Object;
         append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL));
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,26 +23,26 @@
 
 package com.oracle.graal.compiler.amd64;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class AMD64MemoryPeephole implements MemoryArithmeticLIRLowerer {
     protected final AMD64NodeLIRBuilder gen;
@@ -71,13 +71,17 @@
 
     protected LIRFrameState getState(Access access) {
         if (access instanceof DeoptimizingNode) {
-            return gen.getLIRGenerator().state((DeoptimizingNode) access);
+            return gen.state((DeoptimizingNode) access);
         }
         return null;
     }
 
+    protected Kind getMemoryKind(Access access) {
+        return (Kind) gen.getLIRGenerator().getPlatformKind(access.asNode().stamp());
+    }
+
     protected AMD64AddressValue makeAddress(Access access) {
-        return (AMD64AddressValue) access.accessLocation().generateAddress(gen, gen.operand(access.object()));
+        return (AMD64AddressValue) access.accessLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(access.object()));
     }
 
     protected Value emitBinaryMemory(AMD64Arithmetic op, boolean commutative, ValueNode x, ValueNode y, Access access) {
@@ -90,7 +94,7 @@
             }
         }
         ensureEvaluated(other);
-        return gen.getLIRGenerator().emitBinaryMemory(op, access.accessLocation().getValueKind(), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access));
+        return gen.getLIRGenerator().emitBinaryMemory(op, getMemoryKind(access), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access));
     }
 
     /**
@@ -129,7 +133,7 @@
 
     @Override
     public Value emitAddMemory(ValueNode x, ValueNode y, Access access) {
-        switch (access.accessLocation().getValueKind()) {
+        switch (getMemoryKind(access)) {
             case Int:
                 return emitBinaryMemory(IADD, true, x, y, access);
             case Long:
@@ -145,7 +149,7 @@
 
     @Override
     public Value emitSubMemory(ValueNode x, ValueNode y, Access access) {
-        switch (access.accessLocation().getValueKind()) {
+        switch (getMemoryKind(access)) {
             case Int:
                 return emitBinaryMemory(ISUB, false, x, y, access);
             case Long:
@@ -161,7 +165,7 @@
 
     @Override
     public Value emitMulMemory(ValueNode x, ValueNode y, Access access) {
-        switch (access.accessLocation().getValueKind()) {
+        switch (getMemoryKind(access)) {
             case Int:
                 return emitBinaryMemory(IMUL, true, x, y, access);
             case Long:
@@ -187,7 +191,7 @@
 
     @Override
     public Value emitAndMemory(ValueNode x, ValueNode y, Access access) {
-        Kind kind = access.accessLocation().getValueKind();
+        Kind kind = getMemoryKind(access);
         switch (kind) {
             case Int:
                 return emitBinaryMemory(IAND, true, x, y, access);
@@ -224,7 +228,7 @@
 
     @Override
     public Value emitOrMemory(ValueNode x, ValueNode y, Access access) {
-        switch (access.accessLocation().getValueKind()) {
+        switch (getMemoryKind(access)) {
             case Int:
                 return emitBinaryMemory(IOR, true, x, y, access);
             case Long:
@@ -236,7 +240,7 @@
 
     @Override
     public Value emitXorMemory(ValueNode x, ValueNode y, Access access) {
-        switch (access.accessLocation().getValueKind()) {
+        switch (getMemoryKind(access)) {
             case Int:
                 return emitBinaryMemory(IXOR, true, x, y, access);
             case Long:
@@ -249,7 +253,7 @@
     @Override
     public Value emitReinterpretMemory(Stamp stamp, Access access) {
         PlatformKind to = gen.getLIRGenerator().getPlatformKind(stamp);
-        Kind from = access.accessLocation().getValueKind();
+        Kind from = getMemoryKind(access);
         assert to != from : "should have been eliminated";
 
         /*
@@ -353,10 +357,10 @@
     }
 
     @Override
-    public Value emitZeroExtendMemory(int inputBits, int resultBits, Access access) {
-        assert resultBits == 32 || resultBits == 64;
-        Kind memoryKind = access.accessLocation().getValueKind();
-        if (memoryKind.getBitCount() != inputBits && !memoryKind.isUnsigned()) {
+    public Value emitZeroExtendMemory(int fromBits, int toBits, Access access) {
+        assert fromBits != toBits;
+        Kind memoryKind = getMemoryKind(access);
+        if (memoryKind.getBitCount() != fromBits && !memoryKind.isUnsigned()) {
             // The memory being read from is signed and smaller than the result size so
             // this is a sign extension to inputBits followed by a zero extension to resultBits
             // which can't be expressed in a memory operation.
@@ -366,7 +370,7 @@
             memoryKind = Kind.Char;
         }
         evaluateDeferred();
-        return gen.getLIRGenerator().emitZeroExtendMemory(memoryKind, resultBits, makeAddress(access), getState(access));
+        return gen.getLIRGenerator().emitZeroExtendMemory(memoryKind, toBits, makeAddress(access), getState(access));
     }
 
     public boolean emitIfMemory(IfNode x, Access access) {
@@ -399,7 +403,7 @@
 
     private boolean emitIntegerTestBranchMemory(ValueNode left, ValueNode right, Access access, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) {
         ValueNode other = selectOtherInput(left, right, access);
-        Kind kind = access.accessLocation().getValueKind();
+        Kind kind = getMemoryKind(access);
         if (other.isConstant()) {
             if (kind != kind.getStackKind()) {
                 return false;
@@ -439,7 +443,7 @@
     protected boolean emitCompareBranchMemory(ValueNode left, ValueNode right, Access access, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel,
                     double trueLabelProbability) {
         ValueNode other = selectOtherInput(left, right, access);
-        Kind kind = access.accessLocation().getValueKind();
+        Kind kind = getMemoryKind(access);
         boolean mirrored = false;
 
         if (other.isConstant()) {
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -60,7 +61,7 @@
     @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) {
         assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt;
-        append(new AMD64Move.NullCheckOp(gen.load(operand(v)), gen.state(deopt)));
+        append(new AMD64Move.NullCheckOp(gen.load(operand(v)), state(deopt)));
     }
 
     @Override
@@ -73,7 +74,7 @@
                 if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
                     FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
                     if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && !hasOperand(otherDivRem)) {
-                        Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode);
+                        Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), state((DeoptimizingNode) valueNode));
                         if (divRem instanceof IntegerDivNode) {
                             setResult(divRem, results[0]);
                             setResult(otherDivRem, results[1]);
@@ -103,7 +104,7 @@
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        append(new InfopointOp(gen.stateFor(i.getState()), i.reason));
+        append(new InfopointOp(stateFor(i.getState()), i.reason));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.common;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+public abstract class FieldIntrospection extends UnsafeAccess {
+
+    /**
+     * Interface used by {@link #rescanAllFieldOffsets(CalcOffset)} to determine the offset (in
+     * bytes) of a field.
+     */
+    public interface CalcOffset {
+
+        long getOffset(Field field);
+    }
+
+    public static class DefaultCalcOffset implements CalcOffset {
+
+        @Override
+        public long getOffset(Field field) {
+            return unsafe.objectFieldOffset(field);
+        }
+    }
+
+    protected static final ConcurrentHashMap<Class<?>, FieldIntrospection> allClasses = new ConcurrentHashMap<>();
+
+    private final Class<?> clazz;
+    protected long[] dataOffsets;
+    protected Map<Long, String> fieldNames;
+    protected Map<Long, Class<?>> fieldTypes;
+
+    public FieldIntrospection(Class<?> clazz) {
+        this.clazz = clazz;
+    }
+
+    public Class<?> getClazz() {
+        return clazz;
+    }
+
+    public static void rescanAllFieldOffsets(CalcOffset calc) {
+        for (FieldIntrospection nodeClass : allClasses.values()) {
+            nodeClass.rescanFieldOffsets(calc);
+        }
+    }
+
+    protected abstract void rescanFieldOffsets(CalcOffset calc);
+
+    public abstract static class BaseFieldScanner {
+
+        private final CalcOffset calc;
+
+        /** The offsets of fields that are not specially handled by subclasses. */
+        public final ArrayList<Long> dataOffsets = new ArrayList<>();
+
+        public final Map<Long, String> fieldNames = new HashMap<>();
+        public final Map<Long, Class<?>> fieldTypes = new HashMap<>();
+
+        protected BaseFieldScanner(CalcOffset calc) {
+            this.calc = calc;
+        }
+
+        public void scan(Class<?> clazz) {
+            Class<?> currentClazz = clazz;
+            do {
+                for (Field field : currentClazz.getDeclaredFields()) {
+                    if (Modifier.isStatic(field.getModifiers())) {
+                        continue;
+                    }
+                    Class<?> type = field.getType();
+                    long offset = calc.getOffset(field);
+
+                    // scanField() may overwrite the name with a customized name.
+                    fieldNames.put(offset, field.getName());
+                    fieldTypes.put(offset, type);
+
+                    scanField(field, type, offset);
+                }
+                currentClazz = currentClazz.getSuperclass();
+            } while (currentClazz.getSuperclass() != Object.class);
+        }
+
+        protected abstract void scanField(Field field, Class<?> type, long offset);
+    }
+
+    protected static void copyInto(long[] dest, long[] src) {
+        assert dest.length == src.length;
+        for (int i = 0; i < dest.length; i++) {
+            dest[i] = src[i];
+        }
+    }
+
+    protected static <T> void copyInto(T[] dest, T[] src) {
+        assert dest.length == src.length;
+        for (int i = 0; i < dest.length; i++) {
+            dest[i] = src[i];
+        }
+    }
+
+    protected static <T> void copyInto(T[] dest, List<T> src) {
+        assert dest.length == src.size();
+        for (int i = 0; i < dest.length; i++) {
+            dest[i] = src.get(i);
+        }
+    }
+
+    protected static <T> T[] arrayUsingSortedOffsets(Map<Long, T> map, long[] sortedOffsets, T[] result) {
+        for (int i = 0; i < sortedOffsets.length; i++) {
+            result[i] = map.get(sortedOffsets[i]);
+        }
+        return result;
+    }
+
+    protected static long[] sortedLongCopy(ArrayList<Long> list1) {
+        Collections.sort(list1);
+        long[] result = new long[list1.size()];
+        for (int i = 0; i < list1.size(); i++) {
+            result[i] = list1.get(i);
+        }
+        return result;
+    }
+
+    protected static long[] sortedLongCopy(ArrayList<Long> list1, ArrayList<Long> list2) {
+        Collections.sort(list1);
+        Collections.sort(list2);
+        long[] result = new long[list1.size() + list2.size()];
+        for (int i = 0; i < list1.size(); i++) {
+            result[i] = list1.get(i);
+        }
+        for (int i = 0; i < list2.size(); i++) {
+            result[list1.size() + i] = list2.get(i);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalInternalError.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2011, 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.compiler.common;
+
+import java.util.*;
+
+/**
+ * This error represents a conditions that should never occur during normal operation.
+ */
+public class GraalInternalError extends Error {
+
+    private static final long serialVersionUID = 531632331813456233L;
+    private final ArrayList<String> context = new ArrayList<>();
+
+    public static RuntimeException unimplemented() {
+        throw new GraalInternalError("unimplemented");
+    }
+
+    public static RuntimeException unimplemented(String msg) {
+        throw new GraalInternalError("unimplemented: %s", msg);
+    }
+
+    public static RuntimeException shouldNotReachHere() {
+        throw new GraalInternalError("should not reach here");
+    }
+
+    public static RuntimeException shouldNotReachHere(String msg) {
+        throw new GraalInternalError("should not reach here: %s", msg);
+    }
+
+    /**
+     * Checks a given condition and throws a {@link GraalInternalError} if it is false. Guarantees
+     * are stronger than assertions in that they are always checked. Error messages for guarantee
+     * violations should clearly indicate the nature of the problem as well as a suggested solution
+     * if possible.
+     *
+     * @param condition the condition to check
+     * @param msg the message that will be associated with the error, in
+     *            {@link String#format(String, Object...)} syntax
+     * @param args arguments to the format string
+     */
+    public static void guarantee(boolean condition, String msg, Object... args) {
+        if (!condition) {
+            throw new GraalInternalError("failed guarantee: " + msg, args);
+        }
+    }
+
+    /**
+     * This constructor creates a {@link GraalInternalError} with a message assembled via
+     * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to
+     * always generate the same output.
+     *
+     * @param msg the message that will be associated with the error, in String.format syntax
+     * @param args parameters to String.format - parameters that implement {@link Iterable} will be
+     *            expanded into a [x, x, ...] representation.
+     */
+    public GraalInternalError(String msg, Object... args) {
+        super(format(msg, args));
+    }
+
+    /**
+     * This constructor creates a {@link GraalInternalError} for a given causing Throwable instance.
+     *
+     * @param cause the original exception that contains additional information on this error
+     */
+    public GraalInternalError(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * This constructor creates a {@link GraalInternalError} from a given GraalInternalError
+     * instance.
+     *
+     * @param e the original GraalInternalError
+     */
+    public GraalInternalError(GraalInternalError e) {
+        super(e);
+        context.addAll(e.context);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append(super.toString());
+        for (String s : context) {
+            str.append("\n\tat ").append(s);
+        }
+        return str.toString();
+    }
+
+    private static String format(String msg, Object... args) {
+        if (args != null) {
+            // expand Iterable parameters into a list representation
+            for (int i = 0; i < args.length; i++) {
+                if (args[i] instanceof Iterable<?>) {
+                    ArrayList<Object> list = new ArrayList<>();
+                    for (Object o : (Iterable<?>) args[i]) {
+                        list.add(o);
+                    }
+                    args[i] = list.toString();
+                }
+            }
+        }
+        return String.format(Locale.ENGLISH, msg, args);
+    }
+
+    public GraalInternalError addContext(String newContext) {
+        this.context.add(newContext);
+        return this;
+    }
+
+    public GraalInternalError addContext(String name, Object obj) {
+        return addContext(format("%s: %s", name, obj));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2009, 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.compiler.common;
+
+import com.oracle.graal.options.*;
+
+/**
+ * This class encapsulates options that control the behavior of the Graal compiler.
+ */
+// @formatter:off
+public final class GraalOptions {
+
+    @Option(help = "Use baseline compiler configuration")
+    public static final OptionValue<Boolean> UseBaselineCompiler = new OptionValue<>(false);
+    @Option(help = "Enable use of compiler intrinsics")
+    public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true);
+    @Option(help = "Enable inlining of monomorphic calls")
+    public static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true);
+    @Option(help = "Enable inlining of polymorphic calls")
+    public static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true);
+    @Option(help = "Enable inlining of megamorphic calls")
+    public static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(20000);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(5);
+
+    // inlining settings
+    @Option(help = "")
+    public static final OptionValue<Float> BoostInliningForEscapeAnalysis = new OptionValue<>(2f);
+    @Option(help = "")
+    public static final OptionValue<Float> RelevanceCapForInlining = new OptionValue<>(1f);
+    @Option(help = "")
+    public static final OptionValue<Float> CapInheritedRelevance = new OptionValue<>(1f);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IterativeInlining = new OptionValue<>(false);
+
+    @Option(help = "")
+    public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0);
+    @Option(help = "")
+    public static final OptionValue<Boolean> InlineEverything = new OptionValue<>(false);
+
+    // escape analysis settings
+    @Option(help = "")
+    public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2);
+    @Option(help = "")
+    public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false);
+
+    @Option(help = "")
+    public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5);
+    @Option(help = "")
+    public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1);
+
+    // profiling information
+    @Option(help = "")
+    public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40);
+
+    // graph caching
+    @Option(help = "")
+    public static final OptionValue<Boolean> CacheGraphs = new OptionValue<>(true);
+
+    //loop transform settings TODO (gd) tune
+    @Option(help = "")
+    public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> FullUnrollMaxNodes = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Integer> ExactFullUnrollMaxNodes = new OptionValue<>(1200);
+    @Option(help = "")
+    public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(50);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopUnswitchUncertaintyBoost = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true);
+
+    // debugging settings
+    @Option(help = "")
+    public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false);
+
+    @Option(help = "")
+    public static final OptionValue<String> PrintFilter = new OptionValue<>(null);
+
+    // Debug settings:
+    @Option(help = "")
+    public static final OptionValue<Boolean> BootstrapReplacements = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Integer> GCDebugStartCycle = new OptionValue<>(-1);
+    // Ideal graph visualizer output settings
+    @Option(help = "Dump IdealGraphVisualizer output in binary format")
+    public static final OptionValue<Boolean> PrintBinaryGraphs = new OptionValue<>(true);
+    @Option(help = "Output probabilities for fixed nodes during binary graph dumping")
+    public static final OptionValue<Boolean> PrintGraphProbabilities = new OptionValue<>(false);
+    @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.")
+    public static final OptionValue<Boolean> PrintCFG = new OptionValue<>(false);
+    @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.")
+    public static final OptionValue<Boolean> PrintBackendCFG = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintIdealGraphFile = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<String> PrintIdealGraphAddress = new OptionValue<>("127.0.0.1");
+    @Option(help = "")
+    public static final OptionValue<Integer> PrintIdealGraphPort = new OptionValue<>(4444);
+    @Option(help = "")
+    public static final OptionValue<Integer> PrintBinaryGraphPort = new OptionValue<>(4445);
+
+    // Other printing settings
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false);
+    @Option(help = "Print profiling information when parsing a method's bytecode")
+    public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintCodeBytes = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TraceEscapeAnalysis = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
+    @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required")
+    public static final OptionValue<String> DecompileAfterPhase = new OptionValue<>(null);
+
+    // HotSpot command line options
+    @Option(help = "")
+    public static final OptionValue<Boolean> HotSpotPrintCompilation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> HotSpotCIPrintCompilerName = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false);
+
+    // Register allocator debugging
+    @Option(help = "")
+    public static final OptionValue<String> RegisterPressure = new OptionValue<>(null);
+
+    // Code generator settings
+    @Option(help = "")
+    public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenAssertionCode = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> AlignCallsForPatching = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true);
+
+    @Option(help = "")
+    public static final OptionValue<Boolean> MemoryAwareScheduling = new OptionValue<>(true);
+
+    // Translating tableswitch instructions
+    @Option(help = "")
+    public static final OptionValue<Integer> MinimumJumpTableSize = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Integer> RangeTestsSwitchDensity = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Double> MinTableSwitchDensity = new OptionValue<>(0.5);
+
+    // Ahead of time compilation
+    @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);
+
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptDeoptimizationGrouping = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
+    @Option(help = "Allow backend to emit arithmetic and compares directly against memory.")
+    public static final OptionValue<Boolean> OptFoldMemory = new OptionValue<>(true);
+
+
+    /**
+     * Counts the various paths taken through snippets.
+     */
+    @Option(help = "")
+    public static final OptionValue<Boolean> SnippetCounters = new OptionValue<>(false);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.common;
+
+import java.lang.reflect.*;
+
+import sun.misc.*;
+
+public class UnsafeAccess {
+
+    /**
+     * An instance of {@link Unsafe} for use within Graal.
+     */
+    public static final Unsafe unsafe = getUnsafe();
+
+    private static Unsafe getUnsafe() {
+        try {
+            // this will fail if Graal is not part of the boot class path
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+            // nothing to do
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            // currently we rely on being able to use Unsafe...
+            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));
+    }
+
+    /**
+     * Reads a {@code '\0'} terminated C string from native memory and converts it to a
+     * {@link String}.
+     * 
+     * @return a Java string
+     */
+    public static String readCString(long address) {
+        if (address == 0) {
+            return null;
+        }
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0;; i++) {
+            char c = (char) unsafe.getByte(address + i);
+            if (c == 0) {
+                break;
+            }
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/Condition.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2009, 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.compiler.common.calc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+
+/**
+ * Condition codes used in conditionals.
+ */
+public enum Condition {
+    /**
+     * Equal.
+     */
+    EQ("=="),
+
+    /**
+     * Not equal.
+     */
+    NE("!="),
+
+    /**
+     * Signed less than.
+     */
+    LT("<"),
+
+    /**
+     * Signed less than or equal.
+     */
+    LE("<="),
+
+    /**
+     * Signed greater than.
+     */
+    GT(">"),
+
+    /**
+     * Signed greater than or equal.
+     */
+    GE(">="),
+
+    /**
+     * Unsigned greater than or equal ("above than or equal").
+     */
+    AE("|>=|"),
+
+    /**
+     * Unsigned less than or equal ("below than or equal").
+     */
+    BE("|<=|"),
+
+    /**
+     * Unsigned greater than ("above than").
+     */
+    AT("|>|"),
+
+    /**
+     * Unsigned less than ("below than").
+     */
+    BT("|<|");
+
+    public final String operator;
+
+    private Condition(String operator) {
+        this.operator = operator;
+    }
+
+    public boolean check(int left, int right) {
+        switch (this) {
+            case EQ:
+                return left == right;
+            case NE:
+                return left != right;
+            case LT:
+                return left < right;
+            case LE:
+                return left <= right;
+            case GT:
+                return left > right;
+            case GE:
+                return left >= right;
+            case AE:
+                return UnsignedMath.aboveOrEqual(left, right);
+            case BE:
+                return UnsignedMath.belowOrEqual(left, right);
+            case AT:
+                return UnsignedMath.aboveThan(left, right);
+            case BT:
+                return UnsignedMath.belowThan(left, right);
+        }
+        throw new IllegalArgumentException(this.toString());
+    }
+
+    /**
+     * Given a condition and its negation, this method returns true for one of the two and false for
+     * the other one. This can be used to keep comparisons in a canonical form.
+     *
+     * @return true if this condition is considered to be the canonical form, false otherwise.
+     */
+    public boolean isCanonical() {
+        switch (this) {
+            case EQ:
+                return true;
+            case NE:
+                return false;
+            case LT:
+                return true;
+            case LE:
+                return false;
+            case GT:
+                return false;
+            case GE:
+                return false;
+            case BT:
+                return true;
+            case BE:
+                return false;
+            case AT:
+                return false;
+            case AE:
+                return false;
+        }
+        throw new IllegalArgumentException(this.toString());
+    }
+
+    /**
+     * Returns true if the condition needs to be mirrored to get to a canonical condition. The
+     * result of the mirroring operation might still need to be negated to achieve a canonical form.
+     */
+    public boolean canonicalMirror() {
+        switch (this) {
+            case EQ:
+                return false;
+            case NE:
+                return false;
+            case LT:
+                return false;
+            case LE:
+                return true;
+            case GT:
+                return true;
+            case GE:
+                return false;
+            case BT:
+                return false;
+            case BE:
+                return true;
+            case AT:
+                return true;
+            case AE:
+                return false;
+        }
+        throw new IllegalArgumentException(this.toString());
+    }
+
+    /**
+     * Returns true if the condition needs to be negated to get to a canonical condition. The result
+     * of the negation might still need to be mirrored to achieve a canonical form.
+     */
+    public boolean canonicalNegate() {
+        switch (this) {
+            case EQ:
+                return false;
+            case NE:
+                return true;
+            case LT:
+                return false;
+            case LE:
+                return true;
+            case GT:
+                return false;
+            case GE:
+                return true;
+            case BT:
+                return false;
+            case BE:
+                return true;
+            case AT:
+                return false;
+            case AE:
+                return true;
+        }
+        throw new IllegalArgumentException(this.toString());
+    }
+
+    /**
+     * Negate this conditional.
+     *
+     * @return the condition that represents the negation
+     */
+    public final Condition negate() {
+        switch (this) {
+            case EQ:
+                return NE;
+            case NE:
+                return EQ;
+            case LT:
+                return GE;
+            case LE:
+                return GT;
+            case GT:
+                return LE;
+            case GE:
+                return LT;
+            case BT:
+                return AE;
+            case BE:
+                return AT;
+            case AT:
+                return BE;
+            case AE:
+                return BT;
+        }
+        throw new IllegalArgumentException(this.toString());
+    }
+
+    public boolean implies(Condition other) {
+        if (other == this) {
+            return true;
+        }
+        switch (this) {
+            case EQ:
+                return other == LE || other == GE || other == BE || other == AE;
+            case NE:
+                return false;
+            case LT:
+                return other == LE || other == NE;
+            case LE:
+                return false;
+            case GT:
+                return other == GE || other == NE;
+            case GE:
+                return false;
+            case BT:
+                return other == BE || other == NE;
+            case BE:
+                return false;
+            case AT:
+                return other == AE || other == NE;
+            case AE:
+                return false;
+        }
+        throw new IllegalArgumentException(this.toString());
+    }
+
+    /**
+     * Mirror this conditional (i.e. commute "a op b" to "b op' a")
+     *
+     * @return the condition representing the equivalent commuted operation
+     */
+    public final Condition mirror() {
+        switch (this) {
+            case EQ:
+                return EQ;
+            case NE:
+                return NE;
+            case LT:
+                return GT;
+            case LE:
+                return GE;
+            case GT:
+                return LT;
+            case GE:
+                return LE;
+            case BT:
+                return AT;
+            case BE:
+                return AE;
+            case AT:
+                return BT;
+            case AE:
+                return BE;
+        }
+        throw new IllegalArgumentException();
+    }
+
+    /**
+     * Returns true if this condition represents an unsigned comparison. EQ and NE are not
+     * considered to be unsigned.
+     */
+    public final boolean isUnsigned() {
+        return this == Condition.BT || this == Condition.BE || this == Condition.AT || this == Condition.AE;
+    }
+
+    /**
+     * Checks if this conditional operation is commutative.
+     *
+     * @return {@code true} if this operation is commutative
+     */
+    public final boolean isCommutative() {
+        return this == EQ || this == NE;
+    }
+
+    /**
+     * Attempts to fold a comparison between two constants and return the result.
+     *
+     * @param lt the constant on the left side of the comparison
+     * @param rt the constant on the right side of the comparison
+     * @param constantReflection needed to compare constants
+     * @return {@link Boolean#TRUE} if the comparison is known to be true, {@link Boolean#FALSE} if
+     *         the comparison is known to be false
+     */
+    public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection) {
+        assert !lt.getKind().isNumericFloat() && !rt.getKind().isNumericFloat();
+        return foldCondition(lt, rt, constantReflection, false);
+    }
+
+    /**
+     * Attempts to fold a comparison between two constants and return the result.
+     *
+     * @param lt the constant on the left side of the comparison
+     * @param rt the constant on the right side of the comparison
+     * @param constantReflection needed to compare constants
+     * @param unorderedIsTrue true if an undecided float comparison should result in "true"
+     * @return true if the comparison is known to be true, false if the comparison is known to be
+     *         false
+     */
+    public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
+        switch (lt.getKind()) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int: {
+                int x = lt.asInt();
+                int y = rt.asInt();
+                switch (this) {
+                    case EQ:
+                        return x == y;
+                    case NE:
+                        return x != y;
+                    case LT:
+                        return x < y;
+                    case LE:
+                        return x <= y;
+                    case GT:
+                        return x > y;
+                    case GE:
+                        return x >= y;
+                    case AE:
+                        return UnsignedMath.aboveOrEqual(x, y);
+                    case BE:
+                        return UnsignedMath.belowOrEqual(x, y);
+                    case AT:
+                        return UnsignedMath.aboveThan(x, y);
+                    case BT:
+                        return UnsignedMath.belowThan(x, y);
+                    default:
+                        throw new GraalInternalError("expected condition: %s", this);
+                }
+            }
+            case Long: {
+                long x = lt.asLong();
+                long y = rt.asLong();
+                switch (this) {
+                    case EQ:
+                        return x == y;
+                    case NE:
+                        return x != y;
+                    case LT:
+                        return x < y;
+                    case LE:
+                        return x <= y;
+                    case GT:
+                        return x > y;
+                    case GE:
+                        return x >= y;
+                    case AE:
+                        return UnsignedMath.aboveOrEqual(x, y);
+                    case BE:
+                        return UnsignedMath.belowOrEqual(x, y);
+                    case AT:
+                        return UnsignedMath.aboveThan(x, y);
+                    case BT:
+                        return UnsignedMath.belowThan(x, y);
+                    default:
+                        throw new GraalInternalError("expected condition: %s", this);
+                }
+            }
+            case Object: {
+                Boolean equal = constantReflection.constantEquals(lt, rt);
+                if (equal != null) {
+                    switch (this) {
+                        case EQ:
+                            return equal.booleanValue();
+                        case NE:
+                            return !equal.booleanValue();
+                        default:
+                            throw new GraalInternalError("expected condition: %s", this);
+                    }
+                }
+            }
+            case Float: {
+                float x = lt.asFloat();
+                float y = rt.asFloat();
+                if (Float.isNaN(x) || Float.isNaN(y)) {
+                    return unorderedIsTrue;
+                }
+                switch (this) {
+                    case EQ:
+                        return x == y;
+                    case NE:
+                        return x != y;
+                    case LT:
+                        return x < y;
+                    case LE:
+                        return x <= y;
+                    case GT:
+                        return x > y;
+                    case GE:
+                        return x >= y;
+                    default:
+                        throw new GraalInternalError("expected condition: %s", this);
+                }
+            }
+            case Double: {
+                double x = lt.asDouble();
+                double y = rt.asDouble();
+                if (Double.isNaN(x) || Double.isNaN(y)) {
+                    return unorderedIsTrue;
+                }
+                switch (this) {
+                    case EQ:
+                        return x == y;
+                    case NE:
+                        return x != y;
+                    case LT:
+                        return x < y;
+                    case LE:
+                        return x <= y;
+                    case GT:
+                        return x > y;
+                    case GE:
+                        return x >= y;
+                    default:
+                        throw new GraalInternalError("expected condition: %s", this);
+                }
+            }
+            default:
+                throw new GraalInternalError("expected value kind %s while folding condition: %s", lt.getKind(), this);
+        }
+    }
+
+    public Condition join(Condition other) {
+        if (other == this) {
+            return this;
+        }
+        switch (this) {
+            case EQ:
+                if (other == LE || other == GE || other == BE || other == AE) {
+                    return EQ;
+                } else {
+                    return null;
+                }
+            case NE:
+                if (other == LT || other == GT || other == BT || other == AT) {
+                    return other;
+                } else if (other == LE) {
+                    return LT;
+                } else if (other == GE) {
+                    return GT;
+                } else if (other == BE) {
+                    return BT;
+                } else if (other == AE) {
+                    return AT;
+                } else {
+                    return null;
+                }
+            case LE:
+                if (other == GE || other == EQ) {
+                    return EQ;
+                } else if (other == NE || other == LT) {
+                    return LT;
+                } else {
+                    return null;
+                }
+            case LT:
+                if (other == NE || other == LE) {
+                    return LT;
+                } else {
+                    return null;
+                }
+            case GE:
+                if (other == LE || other == EQ) {
+                    return EQ;
+                } else if (other == NE || other == GT) {
+                    return GT;
+                } else {
+                    return null;
+                }
+            case GT:
+                if (other == NE || other == GE) {
+                    return GT;
+                } else {
+                    return null;
+                }
+            case BE:
+                if (other == AE || other == EQ) {
+                    return EQ;
+                } else if (other == NE || other == BT) {
+                    return BT;
+                } else {
+                    return null;
+                }
+            case BT:
+                if (other == NE || other == BE) {
+                    return BT;
+                } else {
+                    return null;
+                }
+            case AE:
+                if (other == BE || other == EQ) {
+                    return EQ;
+                } else if (other == NE || other == AT) {
+                    return AT;
+                } else {
+                    return null;
+                }
+            case AT:
+                if (other == NE || other == AE) {
+                    return AT;
+                } else {
+                    return null;
+                }
+        }
+        throw new IllegalArgumentException(this.toString());
+    }
+
+    public Condition meet(Condition other) {
+        if (other == this) {
+            return this;
+        }
+        switch (this) {
+            case EQ:
+                if (other == LE || other == GE || other == BE || other == AE) {
+                    return other;
+                } else if (other == LT) {
+                    return LE;
+                } else if (other == GT) {
+                    return GE;
+                } else if (other == BT) {
+                    return BE;
+                } else if (other == AT) {
+                    return AE;
+                } else {
+                    return null;
+                }
+            case NE:
+                if (other == LT || other == GT || other == BT || other == AT) {
+                    return NE;
+                } else {
+                    return null;
+                }
+            case LE:
+                if (other == EQ || other == LT) {
+                    return LE;
+                } else {
+                    return null;
+                }
+            case LT:
+                if (other == EQ || other == LE) {
+                    return LE;
+                } else if (other == NE || other == GT) {
+                    return NE;
+                } else {
+                    return null;
+                }
+            case GE:
+                if (other == EQ || other == GT) {
+                    return GE;
+                } else {
+                    return null;
+                }
+            case GT:
+                if (other == EQ || other == GE) {
+                    return GE;
+                } else if (other == NE || other == LT) {
+                    return NE;
+                } else {
+                    return null;
+                }
+            case BE:
+                if (other == EQ || other == BT) {
+                    return BE;
+                } else {
+                    return null;
+                }
+            case BT:
+                if (other == EQ || other == BE) {
+                    return BE;
+                } else if (other == NE || other == AT) {
+                    return NE;
+                } else {
+                    return null;
+                }
+            case AE:
+                if (other == EQ || other == AT) {
+                    return AE;
+                } else {
+                    return null;
+                }
+            case AT:
+                if (other == EQ || other == AE) {
+                    return AE;
+                } else if (other == NE || other == BT) {
+                    return NE;
+                } else {
+                    return null;
+                }
+        }
+        throw new IllegalArgumentException(this.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/FloatConvert.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.compiler.common.calc;
+
+import com.oracle.graal.compiler.common.*;
+
+public enum FloatConvert {
+    F2I,
+    D2I,
+    F2L,
+    D2L,
+    I2F,
+    L2F,
+    D2F,
+    I2D,
+    L2D,
+    F2D;
+
+    public FloatConvert reverse() {
+        switch (this) {
+            case D2F:
+                return F2D;
+            case D2I:
+                return I2D;
+            case D2L:
+                return L2D;
+            case F2D:
+                return D2F;
+            case F2I:
+                return I2F;
+            case F2L:
+                return L2F;
+            case I2D:
+                return D2I;
+            case I2F:
+                return F2I;
+            case L2D:
+                return D2L;
+            case L2F:
+                return F2L;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.compiler.common.cfg;
+
+import java.util.*;
+
+public interface AbstractBlock<T extends AbstractBlock<T>> {
+
+    int getId();
+
+    Loop<T> getLoop();
+
+    int getLoopDepth();
+
+    boolean isLoopHeader();
+
+    boolean isLoopEnd();
+
+    boolean isExceptionEntry();
+
+    List<T> getPredecessors();
+
+    int getPredecessorCount();
+
+    List<T> getSuccessors();
+
+    int getSuccessorCount();
+
+    int getLinearScanNumber();
+
+    void setLinearScanNumber(int linearScanNumber);
+
+    boolean isAligned();
+
+    void setAlign(boolean align);
+
+    T getDominator();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,104 @@
+/*
+ * 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.common.cfg;
+
+import java.util.*;
+
+public abstract class AbstractBlockBase<T extends AbstractBlock<T>> implements AbstractBlock<T> {
+
+    protected int id;
+
+    protected List<T> predecessors;
+    protected List<T> successors;
+
+    private T dominator;
+
+    private boolean align;
+    private int linearScanNumber;
+
+    protected AbstractBlockBase() {
+        this.id = AbstractControlFlowGraph.BLOCK_ID_INITIAL;
+        this.linearScanNumber = -1;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public List<T> getPredecessors() {
+        return predecessors;
+    }
+
+    public void setPredecessors(List<T> predecessors) {
+        this.predecessors = predecessors;
+    }
+
+    public List<T> getSuccessors() {
+        return successors;
+    }
+
+    public void setSuccessors(List<T> successors) {
+        this.successors = successors;
+    }
+
+    public T getDominator() {
+        return dominator;
+    }
+
+    public void setDominator(T dominator) {
+        this.dominator = dominator;
+    }
+
+    @Override
+    public String toString() {
+        return "B" + id;
+    }
+
+    public int getPredecessorCount() {
+        return getPredecessors().size();
+    }
+
+    public int getSuccessorCount() {
+        return getSuccessors().size();
+    }
+
+    public int getLinearScanNumber() {
+        return linearScanNumber;
+    }
+
+    public void setLinearScanNumber(int linearScanNumber) {
+        this.linearScanNumber = linearScanNumber;
+    }
+
+    public boolean isAligned() {
+        return align;
+    }
+
+    public void setAlign(boolean align) {
+        this.align = align;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.compiler.common.cfg;
+
+import java.util.*;
+
+public interface AbstractControlFlowGraph<T extends AbstractBlock<T>> {
+
+    static final int BLOCK_ID_INITIAL = -1;
+    static final int BLOCK_ID_VISITED = -2;
+
+    T[] getBlocks();
+
+    Collection<Loop<T>> getLoops();
+
+    T getStartBlock();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/BlockMap.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.common.cfg;
+
+public class BlockMap<T> {
+
+    private final T[] data;
+
+    @SuppressWarnings("unchecked")
+    public BlockMap(AbstractControlFlowGraph<?> cfg) {
+        data = (T[]) new Object[cfg.getBlocks().length];
+    }
+
+    public T get(AbstractBlock<?> block) {
+        return data[block.getId()];
+    }
+
+    public void put(AbstractBlock<?> block, T value) {
+        data[block.getId()] = value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/Loop.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.compiler.common.cfg;
+
+import java.util.*;
+
+public abstract class Loop<T extends AbstractBlock<T>> {
+
+    public final Loop<T> parent;
+    public final List<Loop<T>> children;
+
+    public final int depth;
+    public final int index;
+    public final T header;
+    public final List<T> blocks;
+    public final List<T> exits;
+
+    protected Loop(Loop<T> parent, int index, T header) {
+        this.parent = parent;
+        if (parent != null) {
+            this.depth = parent.depth + 1;
+            parent.children.add(this);
+        } else {
+            this.depth = 1;
+        }
+        this.index = index;
+        this.header = header;
+        this.blocks = new ArrayList<>();
+        this.children = new ArrayList<>();
+        this.exits = new ArrayList<>();
+    }
+
+    public abstract long numBackedges();
+
+    @Override
+    public String toString() {
+        return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/CodeGenProviders.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.graal.compiler.common.spi;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+/**
+ * A set of providers which are required for LIR and/or code generation. Some may not be present
+ * (i.e., null).
+ */
+public interface CodeGenProviders {
+
+    MetaAccessProvider getMetaAccess();
+
+    CodeCacheProvider getCodeCache();
+
+    ForeignCallsProvider getForeignCalls();
+
+    ConstantReflectionProvider getConstantReflection();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/PlatformKindTool.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.compiler.common.spi;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * This interface can be used to access platform and VM specific kinds.
+ */
+public interface PlatformKindTool {
+
+    PlatformKind getIntegerKind(int bits);
+
+    PlatformKind getFloatingKind(int bits);
+
+    PlatformKind getObjectKind();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2012, 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.compiler.common.type;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.spi.*;
+
+public class FloatStamp extends PrimitiveStamp {
+
+    private final double lowerBound;
+    private final double upperBound;
+    private final boolean nonNaN;
+
+    protected FloatStamp(int bits) {
+        this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false);
+    }
+
+    public FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) {
+        super(bits);
+        this.lowerBound = lowerBound;
+        this.upperBound = upperBound;
+        this.nonNaN = nonNaN;
+    }
+
+    @Override
+    public Stamp unrestricted() {
+        return new FloatStamp(getBits());
+    }
+
+    @Override
+    public Stamp illegal() {
+        return new FloatStamp(getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, true);
+    }
+
+    @Override
+    public boolean isLegal() {
+        return lowerBound <= upperBound || !nonNaN;
+    }
+
+    @Override
+    public Kind getStackKind() {
+        if (getBits() > 32) {
+            return Kind.Double;
+        } else {
+            return Kind.Float;
+        }
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+        return tool.getFloatingKind(getBits());
+    }
+
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        switch (getBits()) {
+            case 32:
+                return metaAccess.lookupJavaType(Float.TYPE);
+            case 64:
+                return metaAccess.lookupJavaType(Double.TYPE);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    /**
+     * The (inclusive) lower bound on the value described by this stamp.
+     */
+    public double lowerBound() {
+        return lowerBound;
+    }
+
+    /**
+     * The (inclusive) upper bound on the value described by this stamp.
+     */
+    public double upperBound() {
+        return upperBound;
+    }
+
+    public boolean isNonNaN() {
+        return nonNaN;
+    }
+
+    public boolean isUnrestricted() {
+        return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
+    }
+
+    public boolean contains(double value) {
+        if (Double.isNaN(value)) {
+            return !nonNaN;
+        } else {
+            return value >= lowerBound && value <= upperBound;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append('f');
+        str.append(getBits());
+        str.append(nonNaN ? "!" : "");
+        if (lowerBound == upperBound) {
+            str.append(" [").append(lowerBound).append(']');
+        } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) {
+            str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
+        }
+        return str.toString();
+    }
+
+    @Override
+    public Stamp meet(Stamp otherStamp) {
+        if (otherStamp == this) {
+            return this;
+        }
+        if (!(otherStamp instanceof FloatStamp)) {
+            return StampFactory.illegal(Kind.Illegal);
+        }
+        FloatStamp other = (FloatStamp) otherStamp;
+        assert getBits() == other.getBits();
+        double meetUpperBound = Math.max(upperBound, other.upperBound);
+        double meetLowerBound = Math.min(lowerBound, other.lowerBound);
+        boolean meetNonNaN = nonNaN && other.nonNaN;
+        if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) {
+            return this;
+        } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) {
+            return other;
+        } else {
+            return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN);
+        }
+    }
+
+    @Override
+    public Stamp join(Stamp otherStamp) {
+        if (otherStamp == this) {
+            return this;
+        }
+        if (!(otherStamp instanceof FloatStamp)) {
+            return StampFactory.illegal(Kind.Illegal);
+        }
+        FloatStamp other = (FloatStamp) otherStamp;
+        assert getBits() == other.getBits();
+        double joinUpperBound = Math.min(upperBound, other.upperBound);
+        double joinLowerBound = Math.max(lowerBound, other.lowerBound);
+        boolean joinNonNaN = nonNaN || other.nonNaN;
+        if (joinLowerBound == lowerBound && joinUpperBound == upperBound && joinNonNaN == nonNaN) {
+            return this;
+        } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) {
+            return other;
+        } else {
+            return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        long temp;
+        result = prime * result + super.hashCode();
+        temp = Double.doubleToLongBits(lowerBound);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        result = prime * result + (nonNaN ? 1231 : 1237);
+        temp = Double.doubleToLongBits(upperBound);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean isCompatible(Stamp stamp) {
+        if (this == stamp) {
+            return true;
+        }
+        if (stamp instanceof FloatStamp) {
+            FloatStamp other = (FloatStamp) stamp;
+            return getBits() == other.getBits();
+        }
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) {
+            return false;
+        }
+        FloatStamp other = (FloatStamp) obj;
+        if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) {
+            return false;
+        }
+        if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) {
+            return false;
+        }
+        if (nonNaN != other.nonNaN) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public Constant asConstant() {
+        if (nonNaN && lowerBound == upperBound) {
+            switch (getBits()) {
+                case 32:
+                    return Constant.forFloat((float) lowerBound);
+                case 64:
+                    return Constant.forDouble(lowerBound);
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, 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.compiler.common.type;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.spi.*;
+
+/**
+ * This stamp represents the illegal type. Values with this type can not exist at run time.
+ */
+public final class IllegalStamp extends Stamp {
+
+    private IllegalStamp() {
+    }
+
+    @Override
+    public Kind getStackKind() {
+        return Kind.Illegal;
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+        throw GraalInternalError.shouldNotReachHere("illegal stamp should not reach backend");
+    }
+
+    @Override
+    public Stamp unrestricted() {
+        return this;
+    }
+
+    @Override
+    public Stamp illegal() {
+        return this;
+    }
+
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        throw GraalInternalError.shouldNotReachHere("illegal stamp has no Java type");
+    }
+
+    @Override
+    public Stamp meet(Stamp other) {
+        return this;
+    }
+
+    @Override
+    public Stamp join(Stamp other) {
+        return this;
+    }
+
+    @Override
+    public boolean isCompatible(Stamp stamp) {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "ILLEGAL";
+    }
+
+    @Override
+    public boolean isLegal() {
+        return false;
+    }
+
+    private static IllegalStamp instance = new IllegalStamp();
+
+    static IllegalStamp getInstance() {
+        return instance;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2012, 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.compiler.common.type;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.spi.*;
+
+/**
+ * Describes the possible values of a {@link ValueNode} that produces an int or long result.
+ *
+ * The description consists of (inclusive) lower and upper bounds and up (may be set) and down
+ * (always set) bit-masks.
+ */
+@SuppressWarnings("javadoc")
+public class IntegerStamp extends PrimitiveStamp {
+
+    private final long lowerBound;
+    private final long upperBound;
+    private final long downMask;
+    private final long upMask;
+
+    public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) {
+        super(bits);
+        this.lowerBound = lowerBound;
+        this.upperBound = upperBound;
+        this.downMask = downMask;
+        this.upMask = upMask;
+        assert lowerBound >= defaultMinValue(bits) : this;
+        assert upperBound <= defaultMaxValue(bits) : this;
+        assert (downMask & defaultMask(bits)) == downMask : this;
+        assert (upMask & defaultMask(bits)) == upMask : this;
+    }
+
+    @Override
+    public Stamp unrestricted() {
+        return new IntegerStamp(getBits(), defaultMinValue(getBits()), defaultMaxValue(getBits()), 0, defaultMask(getBits()));
+    }
+
+    @Override
+    public Stamp illegal() {
+        return new IntegerStamp(getBits(), defaultMaxValue(getBits()), defaultMinValue(getBits()), defaultMask(getBits()), 0);
+    }
+
+    @Override
+    public boolean isLegal() {
+        return lowerBound <= upperBound;
+    }
+
+    @Override
+    public Kind getStackKind() {
+        if (getBits() > 32) {
+            return Kind.Long;
+        } else {
+            return Kind.Int;
+        }
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+        return tool.getIntegerKind(getBits());
+    }
+
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        switch (getBits()) {
+            case 1:
+                return metaAccess.lookupJavaType(Boolean.TYPE);
+            case 8:
+                return metaAccess.lookupJavaType(Byte.TYPE);
+            case 16:
+                return metaAccess.lookupJavaType(Short.TYPE);
+            case 32:
+                return metaAccess.lookupJavaType(Integer.TYPE);
+            case 64:
+                return metaAccess.lookupJavaType(Long.TYPE);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    /**
+     * The signed inclusive lower bound on the value described by this stamp.
+     */
+    public long lowerBound() {
+        return lowerBound;
+    }
+
+    /**
+     * The signed inclusive upper bound on the value described by this stamp.
+     */
+    public long upperBound() {
+        return upperBound;
+    }
+
+    /**
+     * This bit-mask describes the bits that are always set in the value described by this stamp.
+     */
+    public long downMask() {
+        return downMask;
+    }
+
+    /**
+     * This bit-mask describes the bits that can be set in the value described by this stamp.
+     */
+    public long upMask() {
+        return upMask;
+    }
+
+    public boolean isUnrestricted() {
+        return lowerBound == defaultMinValue(getBits()) && upperBound == defaultMaxValue(getBits()) && downMask == 0 && upMask == defaultMask(getBits());
+    }
+
+    public boolean contains(long value) {
+        return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & defaultMask(getBits()));
+    }
+
+    public boolean isPositive() {
+        return lowerBound() >= 0;
+    }
+
+    public boolean isNegative() {
+        return upperBound() <= 0;
+    }
+
+    public boolean isStrictlyPositive() {
+        return lowerBound() > 0;
+    }
+
+    public boolean isStrictlyNegative() {
+        return upperBound() < 0;
+    }
+
+    public boolean canBePositive() {
+        return upperBound() > 0;
+    }
+
+    public boolean canBeNegative() {
+        return lowerBound() < 0;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append('i');
+        str.append(getBits());
+        if (lowerBound == upperBound) {
+            str.append(" [").append(lowerBound).append(']');
+        } else if (lowerBound != defaultMinValue(getBits()) || upperBound != defaultMaxValue(getBits())) {
+            str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
+        }
+        if (downMask != 0) {
+            str.append(" \u21ca");
+            new Formatter(str).format("%016x", downMask);
+        }
+        if (upMask != defaultMask(getBits())) {
+            str.append(" \u21c8");
+            new Formatter(str).format("%016x", upMask);
+        }
+        return str.toString();
+    }
+
+    private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) {
+        assert getBits() == other.getBits();
+        if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0) {
+            return illegal();
+        } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) {
+            return this;
+        } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) {
+            return other;
+        } else {
+            return new IntegerStamp(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask);
+        }
+    }
+
+    @Override
+    public Stamp meet(Stamp otherStamp) {
+        if (otherStamp == this) {
+            return this;
+        }
+        if (!(otherStamp instanceof IntegerStamp)) {
+            return StampFactory.illegal(Kind.Illegal);
+        }
+        IntegerStamp other = (IntegerStamp) otherStamp;
+        return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask);
+    }
+
+    @Override
+    public Stamp join(Stamp otherStamp) {
+        if (otherStamp == this) {
+            return this;
+        }
+        if (!(otherStamp instanceof IntegerStamp)) {
+            return StampFactory.illegal(Kind.Illegal);
+        }
+        IntegerStamp other = (IntegerStamp) otherStamp;
+        long newDownMask = downMask | other.downMask;
+        long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask;
+        return createStamp(other, Math.min(upperBound, other.upperBound), newLowerBound, newDownMask, upMask & other.upMask);
+    }
+
+    @Override
+    public boolean isCompatible(Stamp stamp) {
+        if (this == stamp) {
+            return true;
+        }
+        if (stamp instanceof IntegerStamp) {
+            IntegerStamp other = (IntegerStamp) stamp;
+            return getBits() == other.getBits();
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + super.hashCode();
+        result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32));
+        result = prime * result + (int) (upperBound ^ (upperBound >>> 32));
+        result = prime * result + (int) (downMask ^ (downMask >>> 32));
+        result = prime * result + (int) (upMask ^ (upMask >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) {
+            return false;
+        }
+        IntegerStamp other = (IntegerStamp) obj;
+        if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) {
+            return false;
+        }
+        return true;
+    }
+
+    public static long defaultMask(int bits) {
+        assert 0 <= bits && bits <= 64;
+        if (bits == 64) {
+            return 0xffffffffffffffffL;
+        } else {
+            return (1L << bits) - 1;
+        }
+    }
+
+    public static long defaultMinValue(int bits) {
+        return -1L << (bits - 1);
+    }
+
+    public static long defaultMaxValue(int bits) {
+        return defaultMask(bits - 1);
+    }
+
+    public static long upMaskFor(int bits, long lowerBound, long upperBound) {
+        long mask = lowerBound | upperBound;
+        if (mask == 0) {
+            return 0;
+        } else {
+            return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & defaultMask(bits);
+        }
+    }
+
+    /**
+     * Checks if the 2 stamps represent values of the same sign. Returns true if the two stamps are
+     * both positive of null or if they are both strictly negative
+     *
+     * @return true if the two stamps are both positive of null or if they are both strictly
+     *         negative
+     */
+    public static boolean sameSign(IntegerStamp s1, IntegerStamp s2) {
+        return s1.isPositive() && s2.isPositive() || s1.isStrictlyNegative() && s2.isStrictlyNegative();
+    }
+
+    @Override
+    public Constant asConstant() {
+        if (lowerBound == upperBound) {
+            switch (getBits()) {
+                case 1:
+                    return Constant.forBoolean(lowerBound != 0);
+                case 8:
+                    return Constant.forByte((byte) lowerBound);
+                case 16:
+                    return Constant.forShort((short) lowerBound);
+                case 32:
+                    return Constant.forInt((int) lowerBound);
+                case 64:
+                    return Constant.forLong(lowerBound);
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2012, 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.compiler.common.type;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.spi.*;
+
+public class ObjectStamp extends Stamp {
+
+    private final ResolvedJavaType type;
+    private final boolean exactType;
+    private final boolean nonNull;
+    private final boolean alwaysNull;
+
+    public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
+        this.type = type;
+        this.exactType = exactType;
+        this.nonNull = nonNull;
+        this.alwaysNull = alwaysNull;
+    }
+
+    @Override
+    public Stamp unrestricted() {
+        return StampFactory.object();
+    }
+
+    @Override
+    public Stamp illegal() {
+        return new ObjectStamp(null, true, true, false);
+    }
+
+    @Override
+    public boolean isLegal() {
+        return !exactType || (type != null && (isConcreteType(type)));
+    }
+
+    @Override
+    public Kind getStackKind() {
+        return Kind.Object;
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+        return tool.getObjectKind();
+    }
+
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        if (type != null) {
+            return type;
+        }
+        return metaAccess.lookupJavaType(Object.class);
+    }
+
+    public boolean nonNull() {
+        return nonNull;
+    }
+
+    public boolean alwaysNull() {
+        return alwaysNull;
+    }
+
+    public ResolvedJavaType type() {
+        return type;
+    }
+
+    public boolean isExactType() {
+        return exactType;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append('a');
+        str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.getName()).append(alwaysNull ? " NULL" : "");
+        return str.toString();
+    }
+
+    @Override
+    public Stamp meet(Stamp otherStamp) {
+        if (this == otherStamp) {
+            return this;
+        }
+        if (!(otherStamp instanceof ObjectStamp)) {
+            return StampFactory.illegal(Kind.Illegal);
+        }
+        ObjectStamp other = (ObjectStamp) otherStamp;
+        ResolvedJavaType meetType;
+        boolean meetExactType;
+        boolean meetNonNull;
+        boolean meetAlwaysNull;
+        if (other.alwaysNull) {
+            meetType = type();
+            meetExactType = exactType;
+            meetNonNull = false;
+            meetAlwaysNull = alwaysNull;
+        } else if (alwaysNull) {
+            meetType = other.type();
+            meetExactType = other.exactType;
+            meetNonNull = false;
+            meetAlwaysNull = other.alwaysNull;
+        } else {
+            meetType = meetTypes(type(), other.type());
+            meetExactType = exactType && other.exactType;
+            if (meetExactType && type != null && other.type != null) {
+                // meeting two valid exact types may result in a non-exact type
+                meetExactType = Objects.equals(meetType, type) && Objects.equals(meetType, other.type);
+            }
+            meetNonNull = nonNull && other.nonNull;
+            meetAlwaysNull = false;
+        }
+
+        if (Objects.equals(meetType, type) && meetExactType == exactType && meetNonNull == nonNull && meetAlwaysNull == alwaysNull) {
+            return this;
+        } else if (Objects.equals(meetType, other.type) && meetExactType == other.exactType && meetNonNull == other.nonNull && meetAlwaysNull == other.alwaysNull) {
+            return other;
+        } else {
+            return new ObjectStamp(meetType, meetExactType, meetNonNull, meetAlwaysNull);
+        }
+    }
+
+    @Override
+    public Stamp join(Stamp otherStamp) {
+        return join0(otherStamp, false);
+    }
+
+    @Override
+    public boolean isCompatible(Stamp other) {
+        if (this == other) {
+            return true;
+        }
+        if (other instanceof ObjectStamp) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the stamp representing the type of this stamp after a cast to the type represented by
+     * the {@code to} stamp. While this is very similar to a {@link #join} operation, in the case
+     * where both types are not obviously related, the cast operation will prefer the type of the
+     * {@code to} stamp. This is necessary as long as ObjectStamps are not able to accurately
+     * represent intersection types.
+     *
+     * For example when joining the {@link RandomAccess} type with the {@link AbstractList} type,
+     * without intersection types, this would result in the most generic type ({@link Object} ). For
+     * this reason, in some cases a {@code castTo} operation is preferable in order to keep at least
+     * the {@link AbstractList} type.
+     *
+     * @param to the stamp this stamp should be casted to
+     * @return This stamp casted to the {@code to} stamp
+     */
+    public Stamp castTo(ObjectStamp to) {
+        return join0(to, true);
+    }
+
+    private Stamp join0(Stamp otherStamp, boolean castToOther) {
+        if (this == otherStamp) {
+            return this;
+        }
+        if (!(otherStamp instanceof ObjectStamp)) {
+            return StampFactory.illegal(Kind.Illegal);
+        }
+        ObjectStamp other = (ObjectStamp) otherStamp;
+        if (!isLegal()) {
+            return this;
+        } else if (!other.isLegal()) {
+            return other;
+        }
+
+        ResolvedJavaType joinType;
+        boolean joinAlwaysNull = alwaysNull || other.alwaysNull;
+        boolean joinNonNull = nonNull || other.nonNull;
+        boolean joinExactType = exactType || other.exactType;
+        if (Objects.equals(type, other.type)) {
+            joinType = type;
+        } else if (type == null && other.type == null) {
+            joinType = null;
+        } else if (type == null) {
+            joinType = other.type;
+        } else if (other.type == null) {
+            joinType = type;
+        } else {
+            // both types are != null and different
+            if (type.isAssignableFrom(other.type)) {
+                joinType = other.type;
+                if (exactType) {
+                    joinAlwaysNull = true;
+                }
+            } else if (other.type.isAssignableFrom(type)) {
+                joinType = type;
+                if (other.exactType) {
+                    joinAlwaysNull = true;
+                }
+            } else {
+                if (castToOther) {
+                    joinType = other.type;
+                    joinExactType = other.exactType;
+                } else {
+                    joinType = null;
+                }
+                if (joinExactType || (!type.isInterface() && !other.type.isInterface())) {
+                    joinAlwaysNull = true;
+                }
+            }
+        }
+        if (joinAlwaysNull) {
+            joinType = null;
+            joinExactType = false;
+        }
+        if (joinExactType && joinType == null) {
+            return StampFactory.illegal(Kind.Object);
+        }
+        if (joinAlwaysNull && joinNonNull) {
+            return StampFactory.illegal(Kind.Object);
+        } else if (joinExactType && !isConcreteType(joinType)) {
+            return StampFactory.illegal(Kind.Object);
+        }
+        if (Objects.equals(joinType, type) && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) {
+            return this;
+        } else if (Objects.equals(joinType, other.type) && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) {
+            return other;
+        } else {
+            return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
+        }
+    }
+
+    public static boolean isConcreteType(ResolvedJavaType type) {
+        return !(type.isAbstract() && !type.isArray());
+    }
+
+    private static ResolvedJavaType meetTypes(ResolvedJavaType a, ResolvedJavaType b) {
+        if (Objects.equals(a, b)) {
+            return a;
+        } else if (a == null || b == null) {
+            return null;
+        } else {
+            return a.findLeastCommonAncestor(b);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (exactType ? 1231 : 1237);
+        result = prime * result + (nonNull ? 1231 : 1237);
+        result = prime * result + (alwaysNull ? 1231 : 1237);
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        ObjectStamp other = (ObjectStamp) obj;
+        if (exactType != other.exactType || nonNull != other.nonNull || alwaysNull != other.alwaysNull) {
+            return false;
+        }
+        if (type == null) {
+            if (other.type != null) {
+                return false;
+            }
+        } else if (!type.equals(other.type)) {
+            return false;
+        }
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.compiler.common.type;
+
+/**
+ * Describes the possible values of a {@link ValueNode} that produces a primitive value as result.
+ */
+@SuppressWarnings("javadoc")
+public abstract class PrimitiveStamp extends Stamp {
+
+    private final int bits;
+
+    protected PrimitiveStamp(int bits) {
+        this.bits = bits;
+    }
+
+    /**
+     * The width in bits of the value described by this stamp.
+     */
+    public int getBits() {
+        return bits;
+    }
+
+    public static int getBits(Stamp stamp) {
+        if (stamp instanceof PrimitiveStamp) {
+            return ((PrimitiveStamp) stamp).getBits();
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + bits;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof PrimitiveStamp) {
+            PrimitiveStamp other = (PrimitiveStamp) obj;
+            return bits == other.bits;
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2011, 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.compiler.common.type;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.spi.*;
+
+/**
+ * A stamp is the basis for a type system over the nodes in a graph.
+ */
+public abstract class Stamp {
+
+    protected Stamp() {
+    }
+
+    /**
+     * Returns the type of the stamp, guaranteed to be non-null. In some cases, this requires the
+     * lookup of class meta data, therefore the {@link MetaAccessProvider} is mandatory.
+     */
+    public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess);
+
+    public boolean alwaysDistinct(Stamp other) {
+        return !join(other).isLegal();
+    }
+
+    /**
+     * Gets a Java {@link Kind} that can be used to store a value of this stamp on the Java bytecode
+     * stack. Returns {@link Kind#Illegal} if a value of this stamp can not be stored on the
+     * bytecode stack.
+     */
+    public abstract Kind getStackKind();
+
+    /**
+     * Gets a platform dependent {@link PlatformKind} that can be used to store a value of this
+     * stamp.
+     */
+    public abstract PlatformKind getPlatformKind(PlatformKindTool tool);
+
+    /**
+     * Returns the union of this stamp and the given stamp. Typically used to create stamps for
+     * {@link ValuePhiNode}s.
+     *
+     * @param other The stamp that will enlarge this stamp.
+     * @return The union of this stamp and the given stamp.
+     */
+    @SuppressWarnings("javadoc")
+    public abstract Stamp meet(Stamp other);
+
+    /**
+     * Returns the intersection of this stamp and the given stamp.
+     *
+     * @param other The stamp that will tighten this stamp.
+     * @return The intersection of this stamp and the given stamp.
+     */
+    public abstract Stamp join(Stamp other);
+
+    /**
+     * Returns a stamp of the same kind, but allowing the full value range of the kind.
+     *
+     * {@link #unrestricted()} is the neutral element of the {@link #join(Stamp)} operation.
+     */
+    public abstract Stamp unrestricted();
+
+    /**
+     * Returns a stamp of the same kind, but with no allowed values.
+     *
+     * {@link #illegal()} is the neutral element of the {@link #meet(Stamp)} operation.
+     */
+    public abstract Stamp illegal();
+
+    /**
+     * Test whether two stamps have the same base type.
+     */
+    public abstract boolean isCompatible(Stamp other);
+
+    /**
+     * Test whether this stamp has legal values.
+     */
+    public abstract boolean isLegal();
+
+    /**
+     * If this stamp represents a single value, the methods returns this single value. It returns
+     * null otherwise.
+     *
+     * @return the constant corresponding to the single value of this stamp and null if this stamp
+     *         can represent less or more than one value.
+     */
+    public Constant asConstant() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.common.type;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+
+public class StampFactory {
+
+    // JaCoCo Exclude
+
+    private static final Stamp[] stampCache = new Stamp[Kind.values().length];
+    private static final Stamp[] illegalStampCache = new Stamp[Kind.values().length];
+    private static final Stamp objectStamp = new ObjectStamp(null, false, false, false);
+    private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false);
+    private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true);
+    private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false);
+    private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
+
+    private static void setCache(Kind kind, Stamp stamp) {
+        stampCache[kind.ordinal()] = stamp;
+    }
+
+    private static void setIntCache(Kind kind) {
+        int bits = kind.getStackKind().getBitCount();
+        long mask;
+        if (kind.isUnsigned()) {
+            mask = IntegerStamp.defaultMask(kind.getBitCount());
+        } else {
+            mask = IntegerStamp.defaultMask(bits);
+        }
+        setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask));
+    }
+
+    private static void setFloatCache(Kind kind) {
+        setCache(kind, new FloatStamp(kind.getBitCount()));
+    }
+
+    static {
+        setIntCache(Kind.Boolean);
+        setIntCache(Kind.Byte);
+        setIntCache(Kind.Short);
+        setIntCache(Kind.Char);
+        setIntCache(Kind.Int);
+        setIntCache(Kind.Long);
+
+        setFloatCache(Kind.Float);
+        setFloatCache(Kind.Double);
+
+        setCache(Kind.Object, objectStamp);
+        setCache(Kind.Void, VoidStamp.getInstance());
+
+        for (Kind k : Kind.values()) {
+            if (stampCache[k.ordinal()] != null) {
+                illegalStampCache[k.ordinal()] = stampCache[k.ordinal()].illegal();
+            } else {
+                illegalStampCache[k.ordinal()] = IllegalStamp.getInstance();
+            }
+        }
+    }
+
+    /**
+     * Return a stamp for a Java kind, as it would be represented on the bytecode stack.
+     */
+    public static Stamp forKind(Kind kind) {
+        assert stampCache[kind.ordinal()] != null : "unexpected forKind(" + kind + ")";
+        return stampCache[kind.ordinal()];
+    }
+
+    /**
+     * Return the stamp for the {@code void} type. This will return a singleton instance than can be
+     * compared using {@code ==}.
+     */
+    public static Stamp forVoid() {
+        return VoidStamp.getInstance();
+    }
+
+    /**
+     * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an
+     * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated.
+     */
+    public static Stamp forNodeIntrinsic() {
+        return nodeIntrinsicStamp;
+    }
+
+    public static Stamp intValue() {
+        return forKind(Kind.Int);
+    }
+
+    public static Stamp positiveInt() {
+        return positiveInt;
+    }
+
+    public static Stamp illegal() {
+        return illegal(Kind.Illegal);
+    }
+
+    public static Stamp illegal(Kind kind) {
+        return illegalStampCache[kind.ordinal()];
+    }
+
+    public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) {
+        return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask);
+    }
+
+    public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound) {
+        return forInteger(kind.getBitCount(), lowerBound, upperBound);
+    }
+
+    public static IntegerStamp forInteger(int bits) {
+        return new IntegerStamp(bits, IntegerStamp.defaultMinValue(bits), IntegerStamp.defaultMaxValue(bits), 0, IntegerStamp.defaultMask(bits));
+    }
+
+    public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) {
+        long defaultMask = IntegerStamp.defaultMask(bits);
+        if (lowerBound == upperBound) {
+            return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask);
+        }
+        final long downMask;
+        final long upMask;
+        if (lowerBound >= 0) {
+            int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound);
+            long differentBits = lowerBound ^ upperBound;
+            int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros);
+
+            upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount);
+            downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount));
+        } else {
+            if (upperBound >= 0) {
+                upMask = defaultMask;
+                downMask = 0;
+            } else {
+                int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound);
+                long differentBits = lowerBound ^ upperBound;
+                int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes);
+
+                upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes);
+                downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes);
+            }
+        }
+        return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask);
+    }
+
+    public static FloatStamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
+        assert kind.isNumericFloat();
+        return new FloatStamp(kind.getBitCount(), lowerBound, upperBound, nonNaN);
+    }
+
+    public static Stamp forConstant(Constant value) {
+        Kind kind = value.getKind();
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+                long mask = value.asLong() & IntegerStamp.defaultMask(kind.getBitCount());
+                return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), mask, mask);
+            case Float:
+                return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
+            case Double:
+                return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
+            case Illegal:
+                return illegal(Kind.Illegal);
+            case Object:
+                if (value.isNull()) {
+                    return alwaysNull();
+                } else {
+                    return objectNonNull();
+                }
+            default:
+                throw new GraalInternalError("unexpected kind: %s", kind);
+        }
+    }
+
+    public static Stamp forConstant(Constant value, MetaAccessProvider metaAccess) {
+        assert value.getKind() == Kind.Object;
+        if (value.getKind() == Kind.Object) {
+            ResolvedJavaType type = value.isNull() ? null : metaAccess.lookupJavaType(value);
+            return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull());
+        } else {
+            throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.getKind());
+        }
+    }
+
+    public static Stamp object() {
+        return objectStamp;
+    }
+
+    public static Stamp objectNonNull() {
+        return objectNonNullStamp;
+    }
+
+    public static Stamp alwaysNull() {
+        return objectAlwaysNullStamp;
+    }
+
+    public static Stamp declared(ResolvedJavaType type) {
+        return declared(type, false);
+    }
+
+    public static Stamp declaredNonNull(ResolvedJavaType type) {
+        return declared(type, true);
+    }
+
+    public static Stamp declared(ResolvedJavaType type, boolean nonNull) {
+        return object(type, false, nonNull);
+    }
+
+    public static Stamp object(ResolvedJavaType type, boolean exactType, boolean nonNull) {
+        assert type != null;
+        assert type.getKind() == Kind.Object;
+        ResolvedJavaType exact = type.asExactType();
+        if (exact != null) {
+            assert !exactType || type.equals(exact);
+            return new ObjectStamp(exact, true, nonNull, false);
+        } else {
+            return new ObjectStamp(type, exactType, nonNull, false);
+        }
+    }
+
+    public static Stamp exactNonNull(ResolvedJavaType type) {
+        if (ObjectStamp.isConcreteType(type)) {
+            return new ObjectStamp(type, true, true, false);
+        } else {
+            return illegal(Kind.Object);
+        }
+    }
+
+    public static Stamp exact(ResolvedJavaType type) {
+        return new ObjectStamp(type, true, false, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.common.type;
+
+public interface StampProvider {
+
+    Stamp stamp();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,110 @@
+/*
+ * 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.compiler.common.type;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.spi.*;
+
+/**
+ * Singleton stamp representing the value of type {@code void}.
+ */
+public final class VoidStamp extends Stamp {
+
+    private VoidStamp() {
+    }
+
+    @Override
+    public Stamp unrestricted() {
+        return this;
+    }
+
+    @Override
+    public Kind getStackKind() {
+        return Kind.Void;
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+        throw GraalInternalError.shouldNotReachHere("void stamp has no value");
+    }
+
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        return metaAccess.lookupJavaType(Void.TYPE);
+    }
+
+    @Override
+    public String toString() {
+        return "void";
+    }
+
+    @Override
+    public boolean alwaysDistinct(Stamp other) {
+        return this != other;
+    }
+
+    @Override
+    public Stamp meet(Stamp other) {
+        if (other instanceof IllegalStamp) {
+            return other.join(this);
+        }
+        if (this == other) {
+            return this;
+        }
+        return StampFactory.illegal(Kind.Illegal);
+    }
+
+    @Override
+    public Stamp join(Stamp other) {
+        if (other instanceof IllegalStamp) {
+            return other.join(this);
+        }
+        if (this == other) {
+            return this;
+        }
+        return StampFactory.illegal(Kind.Illegal);
+    }
+
+    @Override
+    public boolean isCompatible(Stamp stamp) {
+        return this == stamp;
+    }
+
+    @Override
+    public Stamp illegal() {
+        // there is no illegal void stamp
+        return this;
+    }
+
+    @Override
+    public boolean isLegal() {
+        return true;
+    }
+
+    private static VoidStamp instance = new VoidStamp();
+
+    static VoidStamp getInstance() {
+        return instance;
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,8 +27,8 @@
  * This class extends KernelTester and provides a base class
  * for which the HSAIL code comes from the Graal compiler.
  */
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 import static org.junit.Assume.*;
 
 import java.io.*;
@@ -38,16 +38,15 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.gpu.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.hsail.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hsail.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.options.OptionValue.OverrideScope;
-import com.oracle.graal.phases.*;
 
 public abstract class GraalKernelTester extends KernelTester {
 
@@ -103,6 +102,40 @@
         return (canGenerateCalls && canExecuteCalls);
     }
 
+    private static boolean supportsObjectAllocation() {
+        return true;
+    }
+
+    /**
+     * Determines if the runtime supports object allocation in HSAIL code.
+     */
+    public boolean canHandleObjectAllocation() {
+        return supportsObjectAllocation() && canDeoptimize();
+    }
+
+    /**
+     * Determines if the runtime supports deoptimization in HSAIL code.
+     */
+    public boolean canDeoptimize() {
+        return getHSAILBackend().getRuntime().getConfig().useHSAILDeoptimization;
+    }
+
+    /**
+     * Determines if the runtime supports {@link VirtualObject}s in {@link DebugInfo} associated
+     * with HSAIL code.
+     */
+    public boolean canHandleDeoptVirtualObjects() {
+        return false;
+    }
+
+    /**
+     * Determines if the runtime supports {@link StackSlot}s in {@link DebugInfo} associated with
+     * HSAIL code.
+     */
+    public boolean canHandleDeoptStackSlots() {
+        return false;
+    }
+
     /**
      * Determines if the runtime has the capabilities required by this test.
      */
@@ -126,7 +159,7 @@
         }
     }
 
-    public static OptionValue<?> getOptionFromField(Class declaringClass, String fieldName) {
+    public static OptionValue<?> getOptionFromField(Class<?> declaringClass, String fieldName) {
         try {
             Field f = declaringClass.getDeclaredField(fieldName);
             f.setAccessible(true);
@@ -156,8 +189,8 @@
     @Override
     public void testGeneratedHsailUsingLambdaMethod() {
         try (OverrideScope s = getOverrideScope()) {
+            assumeTrue(supportsRequiredCapabilities());
             super.testGeneratedHsailUsingLambdaMethod();
         }
     }
-
 }
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java	Wed Apr 23 15:48:38 2014 +0200
@@ -416,9 +416,9 @@
     }
 
     /**
-     * The dispatchLambdaKernel dispatches the lambda version of a kernel where the "kernel" is for
-     * the xxx$$Lambda.accept method in the wrapper for the lambda. Note that the useLambdaMethod
-     * boolean provides a way of actually invoking dispatchLambdaMethodKernel from this API.
+     * Dispatches the lambda version of a kernel where the "kernel" is for the xxx$$Lambda.accept
+     * method in the wrapper for the lambda. Note that the useLambdaMethod boolean provides a way of
+     * actually invoking dispatchLambdaMethodKernel from this API.
      */
     public void dispatchLambdaKernel(int range, MyIntConsumer consumer) {
         if (useLambdaMethod) {
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicReferenceGetAndSetTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicReferenceGetAndSetTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -96,6 +96,7 @@
     }
 
     @Test
+    @Ignore
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.hsail.test;
 
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
 import java.lang.reflect.*;
 
 import org.junit.*;
@@ -343,12 +345,14 @@
     }
 
     private void test(final String snippet) {
-        try (Scope s = Debug.scope("HSAILCodeGen")) {
-            Method method = getMethod(snippet);
-            ExternalCompilationResult hsailCode = getBackend().compileKernel(getMetaAccess().lookupJavaMethod(method), false);
-            Debug.log("HSAIL code generated for %s:%n%s", snippet, hsailCode.getCodeString());
-        } catch (Throwable e) {
-            throw Debug.handle(e);
+        try (DebugConfigScope dcs = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
+            try (Scope s = Debug.scope("HSAILCodeGen")) {
+                Method method = getMethod(snippet);
+                ExternalCompilationResult hsailCode = getBackend().compileKernel(getMetaAccess().lookupJavaMethod(method), false);
+                Debug.log("HSAIL code generated for %s:%n%s", snippet, hsailCode.getCodeString());
+            } catch (Throwable e) {
+                throw Debug.handle(e);
+            }
         }
     }
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BoundsCatchBase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BoundsCatchBase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -56,7 +56,7 @@
 
     @Override
     protected boolean supportsRequiredCapabilities() {
-        return getHSAILBackend().getRuntime().getConfig().useHSAILDeoptimization;
+        return canDeoptimize();
     }
 
     @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/EscapingNewBase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,81 @@
+/*
+ * 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.compiler.hsail.test;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import java.util.Arrays;
+
+/**
+ * Base Class for tests that allocate escaping objects.
+ */
+
+public class EscapingNewBase extends GraalKernelTester {
+
+    final int NUM = getRange();
+
+    int getRange() {
+        return 24;
+    }
+
+    @Result public Object[] outArray = new Object[NUM];
+    public Object[] savedOutArray;
+    @Result public boolean savedOutArrayMatch1;
+    @Result public boolean savedOutArrayMatch2;
+    @Result public boolean savedOutArrayMatch3;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = null;
+        }
+    }
+
+    int getDispatches() {
+        return 1;
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return canHandleObjectAllocation();
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchMethodKernel(NUM);
+        // use System.gc() to ensure new objects are in form that gc likes
+        System.gc();
+        savedOutArray = Arrays.copyOf(outArray, NUM);
+        savedOutArrayMatch1 = Arrays.equals(outArray, savedOutArray);
+        if (getDispatches() > 1) {
+            // redispatch kernel without gc
+            dispatchMethodKernel(NUM);
+            savedOutArrayMatch2 = Arrays.equals(outArray, savedOutArray);
+            // and one more time with gc
+            dispatchMethodKernel(NUM);
+            savedOutArrayMatch3 = Arrays.equals(outArray, savedOutArray);
+            System.gc();
+        }
+    }
+
+}
--- /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/EscapingNewFloatStringTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests creating a new String from a float.
+ */
+
+public class EscapingNewFloatStringTest extends EscapingNewBase {
+
+    @Result public String[] myOutArray = new String[NUM];
+
+    public void run(int gid) {
+        outArray[gid] = Float.toString(gid * 1.11f);
+        myOutArray[gid] = Float.toString(gid * 2.22f);
+    }
+
+    @Ignore("problems runs out of memory space while inlining")
+    @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/EscapingNewFloatTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+public class EscapingNewFloatTest extends EscapingNewBase {
+    @Result Float[] myOutArray = new Float[NUM];
+
+    public void run(int gid) {
+        outArray[gid] = (gid + 1) * 1.11f;
+        myOutArray[gid] = (gid + 1) * 2.22f;
+    }
+
+    @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/EscapingNewIntArrayTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of an integer array per workitem.
+ */
+
+public class EscapingNewIntArrayTest extends EscapingNewBase {
+
+    public void run(int gid) {
+        int size = gid + 1;
+        int[] ary = new int[size];
+        for (int i = 0; i < ary.length; i++) {
+            ary[i] = i * 3;
+        }
+        outArray[gid] = ary;
+    }
+
+    private static final boolean DEBUG = Boolean.getBoolean("hsail.debug");
+
+    @Override
+    public void runTest() {
+        super.runTest();
+        if (DEBUG) {
+            for (int i = 0; i < NUM; i++) {
+                int[] ary = (int[]) outArray[i];
+                System.out.print("ary len " + ary.length + ":  ");
+                for (int val : ary) {
+                    System.out.print(val + ",");
+                }
+                System.out.println();
+            }
+        }
+    }
+
+    @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/EscapingNewIntegerTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a java.lang.Integer per workitem.
+ */
+
+public class EscapingNewIntegerTest extends EscapingNewBase {
+    @Result Integer[] myOutArray = new Integer[NUM];
+
+    public void run(int gid) {
+        outArray[gid] = (gid + 1) * 111;
+        myOutArray[gid] = (gid + 1) * 222;
+    }
+
+    @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/EscapingNewStoreFieldTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,72 @@
+/*
+ * 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.compiler.hsail.test;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests allocation of a Vec3 object stored in a field by workitem #1.
+ */
+
+public class EscapingNewStoreFieldTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    public float[] inArray = new float[NUM];
+    @Result public Vec3 outField;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+        }
+    }
+
+    public void run(int gid) {
+        if (gid == 1) {
+            float inval = inArray[gid];
+            outField = new Vec3(inval + 1, inval + 2, inval + 3);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchMethodKernel(NUM);
+
+        // see what happens if we do it again
+        dispatchMethodKernel(NUM);
+        System.gc();
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return canHandleObjectAllocation();
+    }
+
+    @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/EscapingNewStringConcatTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.compiler.hsail.test;
+
+import static com.oracle.graal.debug.Debug.*;
+
+import org.junit.Test;
+
+import com.oracle.graal.debug.*;
+
+/**
+ * Tests allocation of a new String based on string concatenation.
+ */
+
+public class EscapingNewStringConcatTest extends EscapingNewBase {
+
+    @Result public String[] myOutArray = new String[NUM];
+    public String[] inArray = new String[NUM];
+
+    @Override
+    void setupArrays() {
+        super.setupArrays();
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = Integer.toString(i + 100);
+        }
+    }
+
+    public void run(int gid) {
+        outArray[gid] = inArray[gid] + inArray[(gid + NUM / 2) % NUM];
+        myOutArray[gid] = inArray[(gid + NUM / 2) % NUM] + inArray[gid];
+    }
+
+    // Node implementing Lowerable not handled in HSAIL Backend: 6274|MonitorEnter
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void test() {
+        try (DebugConfigScope s = disableIntercept()) {
+            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/EscapingNewStringInternTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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.compiler.hsail.test;
+
+import static com.oracle.graal.debug.Debug.*;
+
+import org.junit.Test;
+
+import com.oracle.graal.debug.*;
+
+/**
+ * Tests allocation of a new String based on string interning.
+ */
+
+public class EscapingNewStringInternTest extends EscapingNewBase {
+
+    public void run(int gid) {
+        outArray[gid] = Integer.toString(gid * 111).intern();
+    }
+
+    // at node: 12|Invoke#Direct#intern
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void test() {
+        try (DebugConfigScope s = disableIntercept()) {
+            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/EscapingNewStringLargeRangeTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,43 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a new String from integer with a large range of workitems.
+ */
+
+public class EscapingNewStringLargeRangeTest extends EscapingNewStringTest {
+
+    @Override
+    int getRange() {
+        return 125000;
+    }
+
+    @Override
+    @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/EscapingNewStringTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a new String from an integer per workitem.
+ */
+
+public class EscapingNewStringTest extends EscapingNewBase {
+
+    @Result public String[] myOutArray = new String[NUM];
+
+    public void run(int gid) {
+        outArray[gid] = Integer.toString(gid * 111);
+        myOutArray[gid] = Integer.toString(gid * 222);
+    }
+
+    @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/EscapingNewVec3ArrayTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of an array of Vec3 objects per workitem.
+ */
+
+public class EscapingNewVec3ArrayTest extends EscapingNewBase {
+
+    public void run(int gid) {
+        int size = gid + 1;
+        Vec3[] vec3ary = new Vec3[size];
+        for (int i = 0; i < vec3ary.length; i++) {
+            vec3ary[i] = new Vec3(size + i + 1.1f, size + i + 2.2f, size + i + 3.3f);
+        }
+        outArray[gid] = vec3ary;
+    }
+
+    private static final boolean DEBUG = Boolean.getBoolean("hsail.debug");
+
+    @Override
+    public void runTest() {
+        super.runTest();
+        if (DEBUG) {
+            System.out.println("dumping results");
+            for (int i = 0; i < NUM; i++) {
+                Vec3[] ary = (Vec3[]) outArray[i];
+                System.out.print("ary len " + ary.length + ":  ");
+                for (Vec3 val : ary) {
+                    System.out.print(val + ", ");
+                }
+                System.out.println();
+            }
+        }
+    }
+
+    @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/EscapingNewVec3Base.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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.compiler.hsail.test;
+
+/**
+ * Base class for Vec3 object allocation tests.
+ */
+
+public class EscapingNewVec3Base extends EscapingNewBase {
+
+    float[] inArray = new float[NUM];
+    @Result Vec3[] myOutArray = new Vec3[NUM];
+
+    @Override
+    void setupArrays() {
+        super.setupArrays();
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            myOutArray[i] = null;
+        }
+    }
+
+    public void run(int gid) {
+        float inval = inArray[gid];
+        // allocate and store in Object array
+        outArray[gid] = new Vec3(inval + 1.1f, inval + 2.1f, inval + 3.1f);
+        // allocate and store in Vec3 array
+        myOutArray[gid] = new Vec3(inval + 4.1f, inval + 5.1f, inval + 6.1f);
+    }
+}
--- /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/EscapingNewVec3LargeRangeDisp3Test.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a new Vec3 object with a large range of workitems with 3 dispatches.
+ */
+
+public class EscapingNewVec3LargeRangeDisp3Test extends EscapingNewVec3Test {
+
+    @Override
+    int getRange() {
+        return 250000;
+    }
+
+    @Override
+    int getDispatches() {
+        return 3;
+    }
+
+    @Override
+    @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/EscapingNewVec3LargeRangeTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a new Vec3 object with a large range of workitems.
+ */
+
+public class EscapingNewVec3LargeRangeTest extends EscapingNewVec3Test {
+
+    @Override
+    int getRange() {
+        return 250000;
+    }
+
+    @Override
+    @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/EscapingNewVec3MediumRangeTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a new Vec3 object with a medium range of workitems.
+ */
+
+public class EscapingNewVec3MediumRangeTest extends EscapingNewVec3Test {
+
+    @Override
+    int getRange() {
+        return 100000;
+    }
+
+    @Override
+    @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/EscapingNewVec3Partial2Test.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a new Vec3 object but skipping one workitem.
+ */
+
+public class EscapingNewVec3Partial2Test extends EscapingNewVec3Base {
+
+    int testGid = NUM / 2;
+
+    @Override
+    public void run(int gid) {
+        float inval = inArray[gid];
+        if (gid != testGid) {
+            outArray[gid] = new Vec3(inval + 1.1f, inval + 2.1f, inval + 3.1f);
+            myOutArray[gid] = new Vec3(inval + 4.1f, inval + 5.1f, inval + 6.1f);
+        }
+    }
+
+    @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/EscapingNewVec3PartialTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a new Vec3 object but only for half of the workitems.
+ */
+
+public class EscapingNewVec3PartialTest extends EscapingNewVec3Base {
+
+    @Override
+    public void run(int gid) {
+        float inval = inArray[gid];
+        outArray[gid] = (gid % 2 == 0 ? new Vec3(inval + 1.1f, inval + 2.1f, inval + 3.1f) : null);
+        myOutArray[gid] = (gid % 2 != 0 ? new Vec3(inval + 4.1f, inval + 5.1f, inval + 6.1f) : null);
+    }
+
+    @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/EscapingNewVec3Test.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests allocation of a new Vec3 object per workitem.
+ */
+
+public class EscapingNewVec3Test extends EscapingNewVec3Base {
+
+    @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/FloatSqrtTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests floating point square root.
+ */
+public class FloatSqrtTest extends GraalKernelTester {
+
+    static final int size = 64;
+    float[] input = new float[size];
+    @Result float[] output = new float[size];
+    {
+        for (int i = 0; i < size; i++) {
+            input[i] = i;
+            output[i] = -1.0f;
+        }
+
+    }
+
+    public static void run(float[] input1, float[] output1, int gid) {
+        output1[gid] = (float) Math.sqrt(input1[gid]);
+    }
+
+    @Override
+    public void runTest() {
+        dispatchMethodKernel(size, input, output);
+    }
+
+    @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/InstanceOfTwoLevelTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,118 @@
+/*
+ * 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 InstanceOfTwoLevelTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    static abstract class Shape {
+        abstract public float getArea();
+    }
+
+    static class Ellipse extends Shape {
+        private float major;
+        private float minor;
+
+        Ellipse(float major, float minor) {
+            this.major = major;
+            this.minor = minor;
+        }
+
+        public float getEccentricity() {
+            float a = major / 2;
+            float b = minor / 2;
+            return (float) Math.sqrt(1 - (b / a) * (b / a));
+        }
+
+        @Override
+        public float getArea() {
+            float a = major / 2;
+            float b = minor / 2;
+            return (float) (Math.PI * a * b);
+        }
+    }
+
+    static class Circle extends Ellipse {
+        Circle(float r) {
+            super(2 * r, 2 * r);
+        }
+    }
+
+    static class Square extends Shape {
+        private float len;
+
+        Square(float _len) {
+            len = _len;
+        }
+
+        @Override
+        public float getArea() {
+            return len * len;
+        }
+    }
+
+    @Result public float[] outArray = new float[NUM];
+    public Object[] inShapeArray = new Object[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            switch (i % 4) {
+                case 0:
+                    inShapeArray[i] = new Circle(i + 1);
+                    break;
+                case 1:
+                    inShapeArray[i] = new Square(i + 1);
+                    break;
+                case 2:
+                    inShapeArray[i] = new Ellipse(i + 1, i + 2);
+                    break;
+                case 3:
+                    inShapeArray[i] = new Object();
+                    break;
+            }
+            outArray[i] = -i;
+        }
+    }
+
+    public void run(int gid) {
+        outArray[gid] = (inShapeArray[gid] instanceof Shape ? 1.0f : 2.0f);
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchMethodKernel(NUM);
+    }
+
+    @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/IntTestBranchTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.Test;
+
+/**
+ * Tests code generation for IntegerTestNode for HSAIL backend.
+ */
+public class IntTestBranchTest extends StaticMethodTwoIntArrays {
+
+    /**
+     * The static "kernel" method we will be testing. By convention the gid is the last parameter.
+     * 
+     * @param out
+     * @param in
+     * @param gid
+     */
+    public static void run(int[] out, int[] in, int gid) {
+        if ((in[gid] & 3) != 0) {
+            out[gid] = in[gid] * 2;
+        } else {
+            out[gid] = in[gid] * 3;
+        }
+    }
+
+    @Test
+    public void test() {
+        super.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/NestedStaticCallTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,85 @@
+/*
+ * 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.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Tests direct method calls.
+ */
+public class NestedStaticCallTest extends GraalKernelTester {
+
+    static final int width = 768;
+    static final int height = width;
+    private int iterations = 100;
+    static final int range = width * height;
+    @Result public float[] outArray = new float[range];
+
+    public static int a(int i) {
+        if (i < 2) {
+            return b(i);
+        } else {
+            return i;
+        }
+    }
+
+    public static int b(int i) {
+        if (i < 90) {
+            return c(i) + i;
+        } else {
+            return d(i) - i;
+        }
+    }
+
+    public static int c(int i) {
+
+        return d(i) + 5;
+    }
+
+    public static int d(int i) {
+
+        return e(i) + 10;
+    }
+
+    public static int e(int i) {
+        return 52 + i;
+    }
+
+    public void run(int gid) {
+        for (int i = 0; i < iterations; i++) {
+            outArray[gid] = a(gid) + i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        dispatchMethodKernel(range);
+    }
+
+    @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/NestedVirtualCallTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,85 @@
+/*
+ * 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.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Tests direct method calls.
+ */
+public class NestedVirtualCallTest extends GraalKernelTester {
+
+    static final int width = 768;
+    static final int height = width;
+    private int iterations = 100;
+    static final int range = width * height;
+    @Result public float[] outArray = new float[range];
+
+    public int a(int i) {
+        if (i < 2) {
+            return b(i);
+        } else {
+            return i;
+        }
+    }
+
+    public int b(int i) {
+        if (i < 90) {
+            return c(i) + i;
+        } else {
+            return d(i) - i;
+        }
+    }
+
+    public int c(int i) {
+
+        return d(i) + 5;
+    }
+
+    public int d(int i) {
+
+        return e(i) + 10;
+    }
+
+    public int e(int i) {
+        return 52 + i;
+    }
+
+    public void run(int gid) {
+        for (int i = 0; i < iterations; i++) {
+            outArray[gid] = a(gid) + i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        dispatchMethodKernel(range);
+    }
+
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/SingleExceptionTestBase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/SingleExceptionTestBase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -37,7 +37,7 @@
 
     @Override
     protected boolean supportsRequiredCapabilities() {
-        return getHSAILBackend().getRuntime().getConfig().useHSAILDeoptimization;
+        return canDeoptimize();
     }
 
     void recordException(Exception e) {
--- /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/StaticCallTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Tests direct method calls.
+ */
+public class StaticCallTest extends GraalKernelTester {
+
+    static final int width = 768;
+    static final int height = width;
+    private int iterations = 100;
+    static final int range = width * height;
+    @Result public float[] outArray = new float[range];
+
+    public static int foo(int gid, int i) {
+        if (gid < 2) {
+            return bar(gid, i);
+        } else {
+            return gid + i;
+        }
+    }
+
+    public static int bar(int gid, int i) {
+        if (gid < 90) {
+            return gid + i;
+        } else {
+            return gid - i;
+        }
+    }
+
+    public void run(int gid) {
+        for (int i = 0; i < iterations; i++) {
+            outArray[gid] = bar(gid, i);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        dispatchMethodKernel(range);
+    }
+
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelBoundsCheckTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelBoundsCheckTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,6 @@
 
 package com.oracle.graal.compiler.hsail.test;
 
-import static org.junit.Assume.*;
-
 import org.junit.*;
 
 /**
@@ -84,7 +82,6 @@
 
     @Test
     public void test() {
-        assumeTrue(runningOnSimulator());
         testGeneratedHsail();
     }
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,7 @@
 
 package com.oracle.graal.compiler.hsail.test;
 
-import static org.junit.Assume.*;
-
 import org.junit.*;
-
 import com.oracle.graal.compiler.hsail.test.infra.*;
 
 /**
@@ -82,7 +79,6 @@
 
     @Test
     public void test() {
-        assumeTrue(runningOnSimulator());
         testGeneratedHsail();
     }
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMethod16InArraysTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMethod16InArraysTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,11 @@
 
 package com.oracle.graal.compiler.hsail.test;
 
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
 import org.junit.*;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
 
 /**
  * Tests the addition of elements from sixteen input arrays.
@@ -64,15 +65,7 @@
     @Test(expected = java.lang.ClassCastException.class)
     @Ignore("until GPU backends can co-exist")
     public void test() {
-        DebugConfig debugConfig = DebugScope.getConfig();
-        DebugConfig noInterceptConfig = new DelegatingDebugConfig(debugConfig) {
-            @Override
-            public RuntimeException interceptException(Throwable e) {
-                return null;
-            }
-        };
-
-        try (DebugConfigScope s = Debug.setConfig(noInterceptConfig)) {
+        try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
             testGeneratedHsail();
         }
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyCallTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyCallTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,6 @@
 
 package com.oracle.graal.compiler.hsail.test;
 
-import static org.junit.Assume.*;
-
 import org.junit.*;
 
 /**
@@ -39,7 +37,6 @@
 
     @Override
     public void runTest() {
-        assumeTrue(aggressiveInliningEnabled() || canHandleHSAILMethodCalls());
         super.runTest();
     }
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsAcceptTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsAcceptTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,6 @@
 
 package com.oracle.graal.compiler.hsail.test;
 
-import static org.junit.Assume.*;
-
 import org.junit.*;
 
 /**
@@ -42,7 +40,6 @@
 
     @Override
     public void runTest() {
-        assumeTrue(aggressiveInliningEnabled() || canHandleHSAILMethodCalls());
         setupArrays();
 
         dispatchMethodKernel(NUM);
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringSwitchTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringSwitchTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,9 @@
 
 package com.oracle.graal.compiler.hsail.test;
 
-import static org.junit.Assume.*;
-
 import org.junit.*;
 
-import com.oracle.graal.compiler.hsail.test.infra.*;
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
 
 /**
  * Tests switch statement with String literal keys.
@@ -121,14 +119,8 @@
         }
     }
 
-    /**
-     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
-     * code with the result of executing a sequential Java version of this unit test.
-     */
     @Test
     public void test() {
-        // This test is only run if inlining is enabled since it requires method call support.
-        assumeTrue(aggressiveInliningEnabled() || canHandleHSAILMethodCalls());
         super.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/VolatileIntTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+/**
+ * 
+ * @author ecaspole
+ */
+public class VolatileIntTest extends GraalKernelTester {
+
+    static final int num = 20;
+    @Result protected int[] outArray = new int[num];
+
+    volatile int theVolatileInt = 42;
+
+    /**
+     * The static "kernel" method we will be testing. By convention the gid is the last parameter.
+     * 
+     */
+    public void run(int[] out, int[] ina, int[] inb, int gid) {
+
+        // Note these array ops are not really part of the test results
+        int x = theVolatileInt;
+
+        out[gid] = ina[gid] + inb[gid];
+
+        theVolatileInt = x;
+    }
+
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+
+    void setupArrays(int[] in, int[] in2) {
+        for (int i = 0; i < num; i++) {
+            in[i] = 1;
+            in2[i] = 2;
+            outArray[i] = 0;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        int[] inArray = new int[num];
+        int[] inArray2 = new int[num];
+        setupArrays(inArray, inArray2);
+
+        dispatchMethodKernel(num, outArray, inArray, inArray2);
+    }
+
+}
--- /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/lambda/ArrayFieldAccessTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests accessing a field which is an array.
+ */
+public class ArrayFieldAccessTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid] * 3;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/ArrayListGetTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import static com.oracle.graal.debug.Debug.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+/**
+ * Tests calling ArrayList.get().
+ */
+public class ArrayListGetTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public ArrayList<Integer> inList = new ArrayList<>();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inList.add(i);
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            int val = inList.get(gid);
+            outArray[gid] = val * val + 1;
+        });
+    }
+
+    // NYI emitForeignCall charAlignedDisjointArraycopy
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void testUsingLambdaMethod() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
+    }
+
+}
--- /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/lambda/ArrayListStreamTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,190 @@
+/*
+ * 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.lambda;
+
+import java.util.ArrayList;
+import java.util.stream.Stream;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+/**
+ * Tests using ArrayLists as streams.
+ */
+public class ArrayListStreamTest {
+
+    // Static and instance fields to test codegen for
+    // each type of variable
+    static int staticSize = 16;
+    final int size = staticSize;
+
+    static int staticFactor = 3;
+    final int factor = staticFactor;
+
+    class MyPoint {
+
+        int x;
+        int y;
+
+        public MyPoint(int _x, int _y) {
+            x = _x;
+            y = _y;
+        }
+    }
+
+    public ArrayList<MyPoint> buildMyPointInputArray() {
+        ArrayList<MyPoint> inputs = new ArrayList<>(size);
+
+        for (int i = 0; i < size; i++) {
+            inputs.add(new MyPoint(i, i + 1));
+        }
+        return inputs;
+    }
+
+    public int[] buildIntInputArray() {
+        int[] inputs = new int[size];
+
+        for (int i = 0; i < size; i++) {
+            inputs[i] = i * 4;
+        }
+        return inputs;
+    }
+
+    @Test
+    public void testForEachObjectStreamNoCaptures() {
+        ArrayList<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            // Swap the values
+            int tmp = p.x;
+            p.x = p.y + factor;
+            p.y = tmp;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.x == (p.y + 1 + factor));
+        }
+    }
+
+    @Test
+    public void testForEachObjectStreamNoCapturesUseStatic() {
+        ArrayList<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            // Swap the values
+            int tmp = p.x;
+            p.x = p.y + staticFactor;
+            p.y = tmp;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.x == (p.y + 1 + staticFactor));
+        }
+    }
+
+    @Test
+    public void testForEachObjectStreamOneCapture() {
+        int[] data = buildIntInputArray();
+        ArrayList<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            p.y = data[p.x];
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x]);
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamOneCaptureUseStatic() {
+        int[] data = buildIntInputArray();
+        ArrayList<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            p.y = data[p.x] + staticFactor;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == (data[p.x] + +staticFactor));
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamTwoCaptures() {
+        int[] data = buildIntInputArray();
+        int[] data2 = buildIntInputArray();
+        ArrayList<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            p.y = data[p.x] + data2[p.x];
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x] + data2[p.x]);
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamTwoCapturesUseStatic() {
+        int[] data = buildIntInputArray();
+        int[] data2 = buildIntInputArray();
+        ArrayList<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            p.y = data[p.x] + data2[p.x] + staticFactor;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x] + data2[p.x] + staticFactor);
+        }
+
+    }
+}
--- /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/lambda/AtomicIntAddAndGetGidTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,84 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicInteger#addAndGet(int)} with a variable delta.
+ */
+public class AtomicIntAddAndGetGidTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    public int[] outArray = new int[NUM];
+    @Result public int[] gaps = new int[NUM];
+    AtomicInteger atomicInt;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+        atomicInt = new AtomicInteger(0);
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicInt.addAndGet(gid);
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+        // System.out.print("outArray: ");
+        // for (int val : outArray) {
+        // System.out.print(val + ", ");
+        // }
+        // System.out.println();
+        // create array of gaps
+        gaps[0] = outArray[0] - 0;
+        for (int i = 1; i < NUM; i++) {
+            gaps[i] = outArray[i] - outArray[i - 1];
+        }
+        Arrays.sort(gaps);
+
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicIntAddAndGetTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicInteger#addAndGet(int)} with the delta being a constant.
+ */
+public class AtomicIntAddAndGetTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    AtomicInteger atomicInt = new AtomicInteger();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicInt.addAndGet(0x7);
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicIntDecAndGetTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicInteger#decrementAndGet()}.
+ */
+public class AtomicIntDecAndGetTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    AtomicInteger atomicInt = new AtomicInteger();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicInt.decrementAndGet();
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicIntGetAndAddTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicInteger#getAndAdd(int)} with the delta being a constant.
+ */
+public class AtomicIntGetAndAddTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    AtomicInteger atomicInt = new AtomicInteger();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicInt.getAndAdd(0x7);
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicIntGetAndDecTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicInteger#getAndDecrement()}.
+ */
+public class AtomicIntGetAndDecTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    AtomicInteger atomicInt = new AtomicInteger();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicInt.getAndDecrement();
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicIntGetAndIncTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicInteger#getAndIncrement()}.
+ */
+public class AtomicIntGetAndIncTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    AtomicInteger atomicInt = new AtomicInteger();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicInt.getAndIncrement();
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicIntIncAndGetTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicInteger#incrementAndGet()}.
+ */
+public class AtomicIntIncAndGetTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    AtomicInteger atomicInt = new AtomicInteger();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicInt.incrementAndGet();
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicLongAddAndGetTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+import org.junit.Test;
+
+import java.util.concurrent.atomic.*;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicLong#addAndGet(long)} with the delta being a constant.
+ */
+public class AtomicLongAddAndGetTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    AtomicLong atomicLong = new AtomicLong();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicLong.addAndGet(0x7);
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicLongGetAndAddTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicLong#getAndAdd(long)} with the delta being a constant.
+ */
+public class AtomicLongGetAndAddTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    AtomicLong atomicLong = new AtomicLong();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicLong.getAndAdd(0x7);
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicLongGetAndIncTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicLong#getAndIncrement()}.
+ */
+public class AtomicLongGetAndIncTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    AtomicLong atomicLong = new AtomicLong();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicLong.getAndIncrement();
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/AtomicLongIncAndGetTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.Arrays;
+
+/**
+ * Tests {@link AtomicLong#incrementAndGet()}.
+ */
+public class AtomicLongIncAndGetTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    AtomicLong atomicLong = new AtomicLong();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = atomicLong.incrementAndGet();
+        });
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/BigIntegerSquaredTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import java.math.BigInteger;
+
+/**
+ * Tests squaring a BigInteger.
+ */
+public class BigIntegerSquaredTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public BigInteger[] inArray = new BigInteger[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new BigInteger(Integer.toString(i));
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid].multiply(inArray[gid]).intValue();
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        // recursive calls
+        return (canHandleHSAILMethodCalls());
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/Body.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,113 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * A Body object derived from Vec3 used in NBody tests.
+ */
+public class Body extends Vec3 {
+
+    public Body(float _x, float _y, float _z, float _m) {
+        super(_x, _y, _z);
+        m = _m;
+        v = new Vec3(0, 0, 0);
+    }
+
+    float m;
+    Vec3 v;
+
+    public float getX() {
+        return x;
+    }
+
+    public float getY() {
+        return y;
+    }
+
+    public float getZ() {
+        return z;
+    }
+
+    public float getVx() {
+        return v.x;
+    }
+
+    public float getVy() {
+        return v.y;
+    }
+
+    public float getVz() {
+        return v.z;
+    }
+
+    public float getM() {
+        return m;
+    }
+
+    public void setM(float _m) {
+        m = _m;
+    }
+
+    public void setX(float _x) {
+        x = _x;
+    }
+
+    public void setY(float _y) {
+        y = _y;
+    }
+
+    public void setZ(float _z) {
+        z = _z;
+    }
+
+    public void setVx(float _vx) {
+        v.x = _vx;
+    }
+
+    public void setVy(float _vy) {
+        v.y = _vy;
+    }
+
+    public void setVz(float _vz) {
+        v.z = _vz;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof Body)) {
+            return false;
+        }
+        Body oth = (Body) other;
+        return (oth.x == x && oth.y == y && oth.z == z && oth.m == m && v.equals(oth.v));
+    }
+
+    @Override
+    public int hashCode() {
+        // TODO Auto-generated method stub
+        return super.hashCode();
+    }
+
+}
--- /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/lambda/ByteArrayTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests reading from a byte array.
+ */
+public class ByteArrayTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public byte[] inArray = new byte[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = (byte) ((i + 1) * (i % 3 == 0 ? 1 : -1));
+            outArray[i] = 99;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid];
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/CountMatchesBase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Base class for tests that use Apache StringUtils.countMatches().
+ */
+public abstract class CountMatchesBase extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[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 % 10));
+        }
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new String(chars, i, 40);
+        }
+    }
+
+}
--- /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/lambda/DoubleFieldAccessTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests accessing a double field.
+ */
+public class DoubleFieldAccessTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public double[] outArray = new double[NUM];
+    public double[] inArray = new double[NUM];
+
+    double doubleField = 7.0;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        double[] out = outArray;
+        double[] in = inArray;
+        dispatchLambdaKernel(NUM, (gid) -> {
+            out[gid] = in[gid] + doubleField;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/FibRecursionTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests a recursive method invocation.
+ */
+public class FibRecursionTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    int fib(int n) {
+        return (n <= 2 ? 1 : fib(n - 2) + fib(n - 1));
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = fib(inArray[gid]);
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        // recursive calls
+        return (canHandleHSAILMethodCalls());
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/Float2DMatrixBase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Base class for 2D float matrix tests.
+ */
+public abstract class Float2DMatrixBase extends GraalKernelTester {
+
+    float[][] matrixA;
+    float[][] matrixB;
+    @Result float[][] outMatrix;
+
+    public void setupArrays(int range) {
+        matrixA = new float[range][];
+        matrixB = new float[range][];
+        outMatrix = new float[range][];
+        for (int j = 0; j < range; j++) {
+            matrixA[j] = new float[range];
+            matrixB[j] = new float[range];
+            outMatrix[j] = new float[range];
+            for (int k = 0; k < range; k++) {
+                matrixA[j][k] = (j + k) % 7;
+                matrixB[j][k] = (j + k + 1) % 8;
+            }
+        }
+    }
+}
--- /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/lambda/Float2DMatrixMultiplyRangeFinalTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -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.lambda;
+
+import org.junit.Test;
+
+/**
+ * Tests 2D float matrix multiply with range being final.
+ */
+public class Float2DMatrixMultiplyRangeFinalTest extends Float2DMatrixBase {
+
+    static final int range = 6;
+
+    @Override
+    public void runTest() {
+        setupArrays(range);
+
+        dispatchLambdaKernel(range, (gid) -> {
+            for (int j = 0; j < range; j++) {
+                float sum = 0;
+                for (int k = 0; k < range; k++) {
+                    sum += (matrixA[gid][k] * matrixB[k][j]);
+                }
+                outMatrix[gid][j] = sum;
+            }
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/Float2DMatrixMultiplySingleOutTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.lambda;
+
+import org.junit.Test;
+
+/**
+ * Tests 2D float matrix multiply with each workitem outputting one entry of the result matrix.
+ */
+public class Float2DMatrixMultiplySingleOutTest extends Float2DMatrixBase {
+
+    @Override
+    public void runTest() {
+        int range = 20;
+        setupArrays(range);
+
+        dispatchLambdaKernel(range * range, (gid) -> {
+            int i = gid % range;
+            int j = gid / range;
+            float sum = 0;
+            for (int k = 0; k < range; k++) {
+                sum += (matrixA[i][k] * matrixB[k][j]);
+            }
+            outMatrix[i][j] = sum;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/Float2DMatrixMultiplyTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.lambda;
+
+import org.junit.Test;
+
+/**
+ * Tests 2D float matrix multiply with each workitem outputting one row of the result matrix.
+ */
+public class Float2DMatrixMultiplyTest extends Float2DMatrixBase {
+
+    @Override
+    public void runTest() {
+        int range = 20;
+        setupArrays(range);
+
+        dispatchLambdaKernel(range, (gid) -> {
+            for (int j = 0; j < range; j++) {
+                float sum = 0;
+                for (int k = 0; k < range; k++) {
+                    sum += (matrixA[gid][k] * matrixB[k][j]);
+                }
+                outMatrix[gid][j] = sum;
+            }
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/FloatCondMoveTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests conditional move of a float value.
+ */
+public class FloatCondMoveTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public float[] outArray = new float[NUM];
+    public float[] inArray = new float[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = (gid > 9 ? 2.0f : 3.0f);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/FloatFieldAccessTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests accessing a float field.
+ */
+public class FloatFieldAccessTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public float[] outArray = new float[NUM];
+    public int[] inArray = new int[NUM];
+
+    float floatField = 7f;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        float[] out = outArray;
+        int[] in = inArray;
+        dispatchLambdaKernel(NUM, (gid) -> {
+            out[gid] = in[gid] + floatField;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/FloatFieldWriteTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests writing a float field.
+ */
+public class FloatFieldWriteTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Body[] bodyArray = new Body[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            Body b = new Body(i, i + 1, -i, 0);
+            bodyArray[i] = b;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            Body b = bodyArray[gid];
+            b.z = b.x * b.y;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/ForEachToGraalTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,311 @@
+/*
+ * 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.lambda;
+
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+/**
+ * Several tests for the Sumatra APIs.
+ */
+public class ForEachToGraalTest {
+
+    // Static and instance fields to test codegen for
+    // each type of variable
+    static int staticSize = 16;
+    final int size = staticSize;
+
+    static int printSize = 4;
+
+    static int staticFactor = 3;
+    final int factor = staticFactor;
+
+    class MyPoint {
+
+        int x;
+        int y;
+
+        public MyPoint(int _x, int _y) {
+            x = _x;
+            y = _y;
+        }
+
+        public int getX() {
+            return x;
+        }
+
+        public int getY() {
+            return y;
+        }
+    }
+
+    public MyPoint[] buildMyPointInputArray() {
+        MyPoint[] inputs = new MyPoint[size];
+
+        for (int i = 0; i < size; i++) {
+            inputs[i] = new MyPoint(i, i + 1);
+        }
+        return inputs;
+    }
+
+    public int[] buildIntInputArray() {
+        int[] inputs = new int[size];
+
+        for (int i = 0; i < size; i++) {
+            inputs[i] = i * 4;
+        }
+        return inputs;
+    }
+
+    @Test
+    public void testForEachIntRangeNoCaptures() {
+        int[] dest = new int[size];
+        IntStream range = IntStream.range(0, dest.length).parallel();
+
+        // System.out.println("testForEachIntRangeNoCaptures");
+
+        range.forEach(p -> {
+            dest[p] = p * factor;
+        });
+
+        for (int k = 0; k < dest.length; k++) {
+            if (k < printSize) {
+                // System.out.println(k + " ... " + dest[k]);
+            }
+            assertTrue(dest[k] == k * factor);
+        }
+    }
+
+    @Test
+    public void testForEachIntRangeNoCapturesUseStatic() {
+        int[] dest = new int[size];
+        IntStream range = IntStream.range(0, dest.length).parallel();
+
+        // System.out.println("testForEachIntRangeNoCapturesUseStatic");
+
+        range.forEach(p -> {
+            dest[p] = p * staticFactor;
+        });
+
+        for (int k = 0; k < dest.length; k++) {
+            if (k < printSize) {
+                // System.out.println(k + " ... " + dest[k]);
+            }
+            assertTrue(dest[k] == k * staticFactor);
+        }
+    }
+
+    @Test
+    public void testForEachIntRangeOneCapture() {
+        int[] dest = new int[size];
+        IntStream range = IntStream.range(0, dest.length).parallel();
+        int[] data = buildIntInputArray();
+
+        range.forEach(p -> {
+            dest[p] = p * factor + data[p];
+        });
+
+        for (int k = 0; k < dest.length; k++) {
+            if (k < printSize) {
+                // System.out.println(k + " ... " + dest[k]);
+            }
+            assertTrue(dest[k] == k * 3 + data[k]);
+        }
+
+    }
+
+    @Test
+    public void testForEachIntRangeOneCaptureUseStatic() {
+        int[] dest = new int[size];
+        IntStream range = IntStream.range(0, dest.length).parallel();
+        int[] data = buildIntInputArray();
+
+        range.forEach(p -> {
+            dest[p] = p * staticFactor + data[p];
+        });
+
+        for (int k = 0; k < dest.length; k++) {
+            // System.out.println( k + " ... " + dest[k] );
+            assertTrue(dest[k] == k * staticFactor + data[k]);
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamNoCaptures() {
+        MyPoint[] inputs = buildMyPointInputArray();
+
+        Arrays.stream(inputs).parallel().forEach(p -> {
+            // Swap the values
+                        int tmp = p.x;
+                        p.x = p.y + factor;
+                        p.y = tmp;
+                    });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs[k];
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.x == (p.y + 1 + factor));
+        }
+    }
+
+    @Test
+    public void testForEachObjectStreamNoCapturesUseStatic() {
+        MyPoint[] inputs = buildMyPointInputArray();
+
+        Arrays.stream(inputs).parallel().forEach(p -> {
+            // Swap the values
+                        int tmp = p.x;
+                        p.x = p.y + staticFactor;
+                        p.y = tmp;
+                    });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs[k];
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.x == (p.y + 1 + staticFactor));
+        }
+    }
+
+    @Test
+    public void testForEachObjectStreamOneCapture() {
+        MyPoint[] inputs = buildMyPointInputArray();
+        int[] data = buildIntInputArray();
+
+        Arrays.stream(inputs).parallel().forEach(p -> {
+            p.y = data[p.x];
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs[k];
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x]);
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamOneCaptureUseStatic() {
+        MyPoint[] inputs = buildMyPointInputArray();
+        int[] data = buildIntInputArray();
+
+        Arrays.stream(inputs).parallel().forEach(p -> {
+            p.y = data[p.x] + staticFactor;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs[k];
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == (data[p.x] + +staticFactor));
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamTwoCaptures() {
+        MyPoint[] inputs = buildMyPointInputArray();
+        int[] data = buildIntInputArray();
+        int[] data2 = buildIntInputArray();
+
+        Arrays.stream(inputs).parallel().forEach(p -> {
+            p.y = data[p.x] + data2[p.x];
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs[k];
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x] + data2[p.x]);
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamTwoCapturesUseStatic() {
+        MyPoint[] inputs = buildMyPointInputArray();
+        int[] data = buildIntInputArray();
+        int[] data2 = buildIntInputArray();
+
+        Arrays.stream(inputs).parallel().forEach(p -> {
+            p.y = data[p.x] + data2[p.x] + staticFactor;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs[k];
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x] + data2[p.x] + staticFactor);
+        }
+
+    }
+
+    // This test should fall back to the regular Java path if
+    // Graal throws NYI
+    @Test
+    public void testForEachIntRangeNoCapturesUseEscapingNew() {
+        MyPoint[] dest = new MyPoint[size];
+        IntStream range = IntStream.range(0, dest.length).parallel();
+
+        range.forEach(p -> {
+            dest[p] = new MyPoint(p + p, p);
+        });
+
+        for (int k = 0; k < dest.length; k++) {
+            if (k < printSize) {
+                // System.out.println(k + " ... " + dest[k]);
+            }
+            assertTrue(dest[k].getX() == (k + k));
+        }
+    }
+
+    // This test should fall back to the regular Java path if
+    // Graal throws NYI
+    @Test
+    public void testForEachIntRangeNoCapturesUseCall() {
+        MyPoint[] dest = new MyPoint[size];
+        ArrayList<MyPoint> list = new ArrayList<>(size);
+        IntStream range = IntStream.range(0, dest.length).parallel();
+
+        for (int i = 0; i < dest.length; i++) {
+            list.add(new MyPoint(i + i, i));
+        }
+
+        range.forEach(p -> {
+            dest[p] = list.get(p);
+        });
+
+        for (int k = 0; k < dest.length; k++) {
+            if (k < printSize) {
+                // System.out.println(k + " ... " + dest[k]);
+            }
+            assertTrue(dest[k].getX() == (k + k));
+        }
+    }
+    // public static void main(String args[]) {
+    // (new ForEachToGraalTest()).testForEachIntRange();
+    // }
+
+}
--- /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/lambda/HashMapGetTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,108 @@
+/*
+ * 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.lambda;
+
+import static com.oracle.graal.debug.Debug.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
+import java.util.HashMap;
+
+import org.junit.Test;
+
+/**
+ * Tests calling HashMap.get().
+ */
+public class HashMapGetTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    static class MyObj {
+        public MyObj(int id) {
+            this.id = id;
+        }
+
+        int id;
+
+        public int getId() {
+            return id;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof MyObj)) {
+                return false;
+            }
+            MyObj othobj = (MyObj) other;
+            return (othobj.id == this.id);
+        }
+
+        @Override
+        public int hashCode() {
+            return 43 * (id % 7);
+        }
+
+    }
+
+    @Result public MyObj[] outArray = new MyObj[NUM];
+    MyObj[] inArray = new MyObj[NUM];
+    public HashMap<MyObj, MyObj> inMap = new HashMap<>();
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            MyObj myobj = new MyObj(i);
+            inMap.put(myobj, new MyObj(i * 3));
+            inArray[NUM - 1 - i] = myobj;
+            outArray[i] = null;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inMap.get(inArray[gid]);
+        });
+    }
+
+    // ForeignCall to Invoke#Direct#get
+    // not inlining HashMapGetTest.lambda$38@15: java.util.HashMap.get(Object):Object (20 bytes): no
+    // type profile exists
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void test() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
+    }
+
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void testUsingLambdaMethod() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
+    }
+
+}
--- /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/lambda/InstanceNBodyTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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.lambda;
+
+import java.util.*;
+import org.junit.*;
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Test intstream lambda version of nbody.
+ */
+public class InstanceNBodyTest extends GraalKernelTester {
+
+    static final int bodies = 1024;
+    static final float delT = .005f;
+    static final float espSqr = 1.0f;
+    static final float mass = 5f;
+    static final int width = 768;
+    static final int height = 768;
+
+    @Result float[] in_xyz = new float[bodies * 3]; // positions xy and z of bodies
+
+    @Result float[] out_xyz = new float[bodies * 3]; // positions xy and z of bodies
+
+    @Result float[] in_vxyz = new float[bodies * 3]; // velocity component of x,y and z of
+    // bodies
+
+    @Result float[] out_vxyz = new float[bodies * 3];
+
+    static float[] seed_xyz = new float[bodies * 3];
+    static {
+        final float maxDist = width / 4;
+        for (int body = 0; body < (bodies * 3); body += 3) {
+            final float theta = (float) (Math.random() * Math.PI * 2);
+            final float phi = (float) (Math.random() * Math.PI * 2);
+            final float radius = (float) (Math.random() * maxDist);
+            seed_xyz[body + 0] = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2;
+            seed_xyz[body + 1] = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2;
+            seed_xyz[body + 2] = (float) (radius * Math.cos(phi));
+        }
+    }
+
+    @Override
+    public void runTest() {
+        System.arraycopy(seed_xyz, 0, in_xyz, 0, seed_xyz.length);
+        Arrays.fill(out_xyz, 0f);
+        Arrays.fill(out_vxyz, 0f);
+        Arrays.fill(in_vxyz, 0f);
+
+        // no local copies to make it an instance lambda
+
+        dispatchLambdaKernel(bodies, (gid) -> {
+            final int count = bodies * 3;
+            final int globalId = gid * 3;
+
+            float accx = 0.f;
+            float accy = 0.f;
+            float accz = 0.f;
+            for (int i = 0; i < count; i += 3) {
+                final float dx = in_xyz[i + 0] - in_xyz[globalId + 0];
+                final float dy = in_xyz[i + 1] - in_xyz[globalId + 1];
+                final float dz = in_xyz[i + 2] - in_xyz[globalId + 2];
+                final float invDist = (float) (1.0 / (Math.sqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr)));
+                accx += mass * invDist * invDist * invDist * dx;
+                accy += mass * invDist * invDist * invDist * dy;
+                accz += mass * invDist * invDist * invDist * dz;
+            }
+            accx *= delT;
+            accy *= delT;
+            accz *= delT;
+            out_xyz[globalId + 0] = in_xyz[globalId + 0] + (in_vxyz[globalId + 0] * delT) + (accx * .5f * delT);
+            out_xyz[globalId + 1] = in_xyz[globalId + 1] + (in_vxyz[globalId + 1] * delT) + (accy * .5f * delT);
+            out_xyz[globalId + 2] = in_xyz[globalId + 2] + (in_vxyz[globalId + 2] * delT) + (accz * .5f * delT);
+
+            out_vxyz[globalId + 0] = in_vxyz[globalId + 0] + accx;
+            out_vxyz[globalId + 1] = in_vxyz[globalId + 1] + accy;
+            out_vxyz[globalId + 2] = in_vxyz[globalId + 2] + accz;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/InstanceOfNullTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.lambda;
+
+import org.junit.Test;
+
+/**
+ * Tests instanceof operator on a null object.
+ */
+public class InstanceOfNullTest extends VirtualCallTest {
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        // change some of the inShapes to null
+        for (int i = 0; i < NUM; i++) {
+            if (i % 3 == 0)
+                inShapeArray[i] = null;
+        }
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = (inShapeArray[gid] instanceof Circle ? 1.0f : 2.0f);
+        });
+    }
+
+    @Override
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Override
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/InstanceOfTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.lambda;
+
+import org.junit.Test;
+
+/**
+ * Tests instanceof operator.
+ */
+public class InstanceOfTest extends VirtualCallTest {
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = (inShapeArray[gid] instanceof Circle ? 1.0f : 2.0f);
+        });
+    }
+
+    @Override
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Override
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/InstanceOopNBodyAccTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,125 @@
+/*
+ * 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.lambda;
+
+import org.junit.*;
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests Oop NBody calling a method that returns acceleration.
+ */
+public class InstanceOopNBodyAccTest extends GraalKernelTester {
+
+    static final int bodies = 1024;
+    static final float delT = .005f;
+    static final float espSqr = 1.0f;
+    static final float mass = 5f;
+    static final int width = 768;
+    static final int height = 768;
+
+    static class Body extends com.oracle.graal.compiler.hsail.test.lambda.Body {
+
+        public Body(float x, float y, float z, float m) {
+            super(x, y, z, m);
+        }
+
+        public Vec3 computeAcc(Body[] in_bodies, float espSqr1, float delT1) {
+            float accx = 0.f;
+            float accy = 0.f;
+            float accz = 0.f;
+            float myPosx = x;
+            float myPosy = y;
+            float myPosz = z;
+
+            for (int b = 0; b < in_bodies.length; b++) {
+                float dx = in_bodies[b].getX() - myPosx;
+                float dy = in_bodies[b].getY() - myPosy;
+                float dz = in_bodies[b].getZ() - myPosz;
+                float invDist = 1.0f / (float) Math.sqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr1);
+                float s = in_bodies[b].getM() * invDist * invDist * invDist;
+                accx = accx + (s * dx);
+                accy = accy + (s * dy);
+                accz = accz + (s * dz);
+            }
+
+            // now return acc as a Vec3
+            return new Vec3(accx * delT1, accy * delT1, accz * delT1);
+        }
+    }
+
+    @Result Body[] in_bodies = new Body[bodies];
+    @Result Body[] out_bodies = new Body[bodies];
+
+    static Body[] seed_bodies = new Body[bodies];
+    static {
+        final float maxDist = width / 4;
+        for (int body = 0; body < bodies; body++) {
+            final float theta = (float) (Math.random() * Math.PI * 2);
+            final float phi = (float) (Math.random() * Math.PI * 2);
+            final float radius = (float) (Math.random() * maxDist);
+            float x = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2;
+            float y = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2;
+            float z = (float) (radius * Math.cos(phi));
+            seed_bodies[body] = new Body(x, y, z, mass);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        System.arraycopy(seed_bodies, 0, in_bodies, 0, seed_bodies.length);
+        for (int b = 0; b < bodies; b++) {
+            out_bodies[b] = new Body(0, 0, 0, mass);
+        }
+        // no local copies of arrays so we make it an instance lambda
+
+        dispatchLambdaKernel(bodies, (gid) -> {
+            Body bin = in_bodies[gid];
+            Body bout = out_bodies[gid];
+            Vec3 acc = bin.computeAcc(in_bodies, espSqr, delT);
+
+            float myPosx = bin.getX();
+            float myPosy = bin.getY();
+            float myPosz = bin.getZ();
+            bout.setX(myPosx + (bin.getVx() * delT) + (acc.x * .5f * delT));
+            bout.setY(myPosy + (bin.getVy() * delT) + (acc.y * .5f * delT));
+            bout.setZ(myPosz + (bin.getVz() * delT) + (acc.z * .5f * delT));
+
+            bout.setVx(bin.getVx() + acc.x);
+            bout.setVy(bin.getVy() + acc.y);
+            bout.setVz(bin.getVz() + acc.z);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/InstanceOopNBodyTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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.lambda;
+
+import org.junit.*;
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Tests OopStream NBody as an instance lambda.
+ */
+public class InstanceOopNBodyTest extends GraalKernelTester {
+
+    static final int bodies = 1024;
+    static final float delT = .005f;
+    static final float espSqr = 1.0f;
+    static final float mass = 5f;
+    static final int width = 768;
+    static final int height = 768;
+
+    @Result Body[] in_bodies = new Body[bodies];
+
+    @Result Body[] out_bodies = new Body[bodies];
+
+    static Body[] seed_bodies = new Body[bodies];
+    static {
+        final float maxDist = width / 4;
+        for (int body = 0; body < bodies; body++) {
+            final float theta = (float) (Math.random() * Math.PI * 2);
+            final float phi = (float) (Math.random() * Math.PI * 2);
+            final float radius = (float) (Math.random() * maxDist);
+            float x = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2;
+            float y = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2;
+            float z = (float) (radius * Math.cos(phi));
+            seed_bodies[body] = new Body(x, y, z, mass);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        System.arraycopy(seed_bodies, 0, in_bodies, 0, seed_bodies.length);
+        for (int b = 0; b < bodies; b++) {
+            out_bodies[b] = new Body(0, 0, 0, mass);
+        }
+        // no local copies of arrays so we make it an instance lambda
+
+        dispatchLambdaKernel(bodies, (gid) -> {
+            float accx = 0.f;
+            float accy = 0.f;
+            float accz = 0.f;
+            Body inb = in_bodies[gid];
+            Body outb = out_bodies[gid];
+            float myPosx = inb.getX();
+            float myPosy = inb.getY();
+            float myPosz = inb.getZ();
+
+            for (Body b : in_bodies) {
+                final float dx = b.getX() - myPosx;
+                final float dy = b.getY() - myPosy;
+                final float dz = b.getZ() - myPosz;
+                final float invDist = 1.0f / (float) Math.sqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr);
+                final float s = b.getM() * invDist * invDist * invDist;
+                accx = accx + (s * dx);
+                accy = accy + (s * dy);
+                accz = accz + (s * dz);
+            }
+
+            accx = accx * delT;
+            accy = accy * delT;
+            accz = accz * delT;
+            outb.setX(myPosx + (inb.getVx() * delT) + (accx * .5f * delT));
+            outb.setY(myPosy + (inb.getVy() * delT) + (accy * .5f * delT));
+            outb.setZ(myPosz + (inb.getVz() * delT) + (accz * .5f * delT));
+
+            outb.setVx(inb.getVx() + accx);
+            outb.setVy(inb.getVy() + accy);
+            outb.setVz(inb.getVz() + accz);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/IntCondMoveTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests conditional move of an int value.
+ */
+public class IntCondMoveTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid] * (gid > 9 ? 2 : 3);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/IntFieldAccessTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests accessing an integer field.
+ */
+public class IntFieldAccessTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    int intField = 7;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        int[] out = outArray;
+        int[] in = inArray;
+        dispatchLambdaKernel(NUM, (gid) -> {
+            out[gid] = in[gid] + intField;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/IntNegateInstanceTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests integer negation.
+ */
+public class IntNegateInstanceTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = 0;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = -inArray[gid];
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/IntSquaredInstanceTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests squaring an integer as an instance lambda.
+ */
+public class IntSquaredInstanceTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid] * inArray[gid] + 1;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/IntSquaredStaticTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests squaring an integer as a static lambda.
+ */
+public class IntSquaredStaticTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        int[] out = outArray;
+        int[] in = inArray;
+        dispatchLambdaKernel(NUM, (gid) -> {
+            out[gid] = in[gid] * in[gid] + 1;
+        });
+    }
+
+    @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/lambda/IntToLongTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests conversion an int to a long.
+ */
+public class IntToLongTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = ((i + 1) * (i % 3 == 0 ? 1 : -1));
+            outArray[i] = 99;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid];
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/IntegerObjectCreateTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests allocation of an Integer object.
+ */
+public class IntegerObjectCreateTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public Integer[] outArray = new Integer[NUM];
+    public Integer[] inArray = new Integer[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            int val = inArray[gid];
+            outArray[gid] = val * val + 1;
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return canHandleObjectAllocation();
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- /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/lambda/IntegerObjectReadTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests reading and unboxing of an Integer object.
+ */
+public class IntegerObjectReadTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public Integer[] inArray = new Integer[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            int val = inArray[gid];
+            outArray[gid] = val * val + 1;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/LongAdderTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -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.lambda;
+
+import static com.oracle.graal.debug.Debug.*;
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+import java.util.concurrent.atomic.LongAdder;
+
+import org.junit.Test;
+
+/**
+ * Tests calling LongAdder.add().
+ */
+public class LongAdderTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long finalSum;
+    LongAdder adder = new LongAdder();
+
+    void setupArrays() {
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            adder.add(gid);
+        });
+
+        finalSum = adder.sum();
+    }
+
+    // cannot handle node: CurrentJavaThread
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void test() {
+        try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
+            testGeneratedHsail();
+        }
+    }
+
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void testUsingLambdaMethod() {
+        try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
+    }
+}
--- /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/lambda/LongCmpTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests comparing a long to a constant.
+ */
+public class LongCmpTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    public long[] inArray = new long[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            long val = inArray[gid];
+            long result = val * val;
+            if (val > 9)
+                result++;
+            outArray[gid] = result;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/LongCondMoveTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests conditional move of a long value.
+ */
+public class LongCondMoveTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    public long[] inArray = new long[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid] * (gid > 9 ? 0x123456789L : 0x123456780L);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/LongNegateInstanceTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests negation of a long.
+ */
+public class LongNegateInstanceTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    public long[] inArray = new long[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = 0;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = -inArray[gid];
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/LongSquaredInstanceTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests squaring of a long as an instance lambda.
+ */
+public class LongSquaredInstanceTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public long[] outArray = new long[NUM];
+    public long[] inArray = new long[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid] * inArray[gid] + 1;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/Main.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.lambda;
+
+/**
+ * a place to put a direct call to a test if you don't want to go thru junit.
+ */
+
+public class Main {
+
+    public static void main(String[] args) {
+        // new StaticIntFieldAccessTest().test();
+    }
+}
--- /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/lambda/MandelInstanceTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests mandel as an instance lambda.
+ */
+
+public class MandelInstanceTest extends GraalKernelTester {
+
+    static final int WIDTH = 768;
+    static final int HEIGHT = WIDTH;
+    static final int maxIterations = 64;
+
+    static final int RANGE = WIDTH * HEIGHT;
+    @Result public int[] rgb = new int[RANGE];
+    int[] palette = new int[256];
+
+    void setupPalette(int[] in) {
+        for (int i = 0; i < in.length; i++) {
+            in[i] = i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupPalette(palette);
+
+        float x_offset = -1f;
+        float y_offset = 0f;
+        float scale = 3f;
+
+        // call it for a range, specifying the lambda
+        dispatchLambdaKernel(RANGE, (gid) -> {
+            final int width = WIDTH;
+            final int height = HEIGHT;
+            float lx = (((gid % width * scale) - ((scale / 2) * width)) / width) + x_offset;
+            float ly = (((gid / width * scale) - ((scale / 2) * height)) / height) + y_offset;
+
+            int count = 0;
+            float zx = lx;
+            float zy = ly;
+            float new_zx = 0f;
+
+            // Iterate until the algorithm converges or until maxIterations are reached.
+                        while (count < maxIterations && zx * zx + zy * zy < 8) {
+                            new_zx = zx * zx - zy * zy + lx;
+                            zy = 2 * zx * zy + ly;
+                            zx = new_zx;
+                            count++;
+                        }
+
+                        rgb[gid] = palette[count];
+                    });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/MandelStaticTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests static lambda version of Mandel.
+ */
+public class MandelStaticTest extends GraalKernelTester {
+
+    static final int WIDTH = 768;
+    static final int HEIGHT = WIDTH;
+    static final int maxIterations = 64;
+
+    static final int RANGE = WIDTH * HEIGHT;
+    @Result public int[] rgb = new int[RANGE];
+
+    void setupPalette(int[] in) {
+        for (int i = 0; i < in.length; i++) {
+            in[i] = i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        int[] palette = new int[256];
+        setupPalette(palette);
+
+        // since we want this to be a fully static lambda, make local copies
+        // of the arrays and values that will get captured by the lambda
+        int[] rgb1 = this.rgb;
+        float x_offset = -1f;
+        float y_offset = 0f;
+        float scale = 3f;
+
+        // call it for a range, specifying lambda
+        dispatchLambdaKernel(RANGE, (gid) -> {
+            final int width = WIDTH;
+            final int height = HEIGHT;
+            float lx = (((gid % width * scale) - ((scale / 2) * width)) / width) + x_offset;
+            float ly = (((gid / width * scale) - ((scale / 2) * height)) / height) + y_offset;
+
+            int count = 0;
+            float zx = lx;
+            float zy = ly;
+            float new_zx = 0f;
+
+            // Iterate until the algorithm converges or until maxIterations are reached.
+                        while (count < maxIterations && zx * zx + zy * zy < 8) {
+                            new_zx = zx * zx - zy * zy + lx;
+                            zy = 2 * zx * zy + ly;
+                            zx = new_zx;
+                            count++;
+                        }
+
+                        rgb1[gid] = palette[count];
+                    });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/NewStringEqualsTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,81 @@
+/*
+ * 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.lambda;
+
+import static com.oracle.graal.debug.Debug.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
+import org.junit.Test;
+
+/**
+ * Tests creating a String and calling .equals() on it.
+ */
+public class NewStringEqualsTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public boolean[] outArray = new boolean[NUM];
+    char[] chars = new char[100];
+
+    void setupArrays() {
+        for (int i = 0; i < chars.length; i++) {
+            chars[i] = (char) ('A' + i);
+        }
+        for (int i = 0; i < NUM; i++) {
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        String base = "ABCDEFGHIJ";
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = new String(chars, 0, 10 + (gid % 3)).equals(base);
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        // although not escaping, seems to require object allocation support
+        return (canHandleObjectAllocation());
+    }
+
+    // NYI emitForeignCall charAlignedDisjointArraycopy
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void test() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
+    }
+
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void testUsingLambdaMethod() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
+    }
+
+}
--- /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/lambda/NewStringLenTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests creating a String and calling .length() on it.
+ */
+public class NewStringLenTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+    char[] chars = new char[100];
+
+    void setupArrays() {
+        for (int i = 0; i < chars.length; i++) {
+            chars[i] = 'A';
+        }
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i + 10;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = Integer.toString(gid).length();
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        // although not escaping, seems to require object allocation support
+        return (canHandleObjectAllocation());
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/NonEscapingNewArrayTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests creating a non-escaping array and using it.
+ */
+public class NonEscapingNewArrayTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public float[] outArray = new float[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            float[] ary = {gid, gid + 1, gid + 2};
+            outArray[gid] = ary[0] * ary[1] * ary[2];
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/NonEscapingNewObjWithArrayTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,95 @@
+/*
+ * 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.lambda;
+
+import static com.oracle.graal.debug.Debug.*;
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+
+/**
+ * Tests non-escaping object creation and calling a method on it.
+ */
+public class NonEscapingNewObjWithArrayTest extends GraalKernelTester {
+    static final int NUM = 20;
+    @Result public float[] outArray = new float[NUM];
+
+    static class MyObj {
+        float a[];
+
+        public MyObj(float[] src, int ofst) {
+            a = Arrays.copyOfRange(src, ofst, ofst + 3);
+        }
+
+        public float productOf() {
+            return a[0] * a[1] * a[2];
+        }
+    }
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        float[] fsrc = new float[2 * NUM];
+        for (int i = 0; i < 2 * NUM; i++) {
+            fsrc[i] = i;
+        }
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = new MyObj(fsrc, gid).productOf();
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        // although not escaping, seems to require object allocation support
+        return (canHandleObjectAllocation());
+    }
+
+    // NYI emitForeignCall floatArraycopy
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void test() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
+    }
+
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void testUsingLambdaMethod() {
+        try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
+    }
+
+}
--- /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/lambda/NonEscapingNewTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests creation of three non-escaping objects.
+ */
+public class NonEscapingNewTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public float[] outArray = new float[NUM];
+    public Vec3[] inArray = new Vec3[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new Vec3(i, i + 1, i + 2);
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            Vec3 veca = inArray[gid];
+            Vec3 vecb = inArray[(gid + 1) % NUM];
+            Vec3 vecresult = Vec3.add(veca, vecb);
+            outArray[gid] = vecresult.z;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/ObjectArrayInstanceDerivedTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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.lambda;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Tests calling a method on an object when there are derived types of that object. Note: if you
+ * enable these tests, not only will these tests fail but other tests like ObjectArrayInstanceTest
+ * will also fail because they depend on there being no derived classes from Body.
+ */
+public class ObjectArrayInstanceDerivedTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    class DerivedBody extends Body {
+
+        DerivedBody(float x, float y, float z, float m) {
+            super(x, y, z, m);
+        }
+
+        @Override
+        public float getX() {
+            return 42.0f;
+        }
+    }
+
+    @Result public float[] outArray = new float[NUM];
+    public Body[] inBodyArray = new Body[NUM];
+    public Body[] unusedBodyArray = new Body[NUM];
+    public DerivedBody[] unusedDerivedBodyArray = new DerivedBody[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inBodyArray[i] = new Body(i, i + 1, i + 2, i + 3);
+            // unusedBodyArray[i] = new DerivedBody(i, i+1, i+2, i+3);
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            Body b = inBodyArray[gid];
+            outArray[gid] = b.getX() * b.getY();
+        });
+    }
+
+    @Ignore
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Ignore
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/ObjectArrayInstanceTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+import org.junit.*;
+
+/**
+ * Tests calling a method on an object when there are no derived types of that object.
+ */
+public class ObjectArrayInstanceTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public float[] outArray = new float[NUM];
+    public Body[] inBodyArray = new Body[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inBodyArray[i] = new Body(i, i + 1, i + 2, i + 3);
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            Body b = inBodyArray[gid];
+            outArray[gid] = b.getX() * b.getY();
+        });
+    }
+
+    @Ignore
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Ignore
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/ObjectStoreNullTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.lambda;
+
+import org.junit.Test;
+
+/**
+ * Tests the storing of null in an Object array
+ */
+public class ObjectStoreNullTest extends ObjectStoreTest {
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outBodyArray[gid] = (gid % 3 == 1 ? null : inBodyArray[gid]);
+        });
+    }
+
+    @Override
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Override
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/ObjectStoreTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests copying an object from one array to another.
+ */
+public class ObjectStoreTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Body[] outBodyArray = new Body[NUM];
+    public Body[] inBodyArray = new Body[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inBodyArray[i] = new Body(i, i + 1, i + 2, i + 3);
+            outBodyArray[i] = null;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outBodyArray[gid] = inBodyArray[gid];
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/OverloadMethodTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests calling methods with the same name but different signatures.
+ */
+public class OverloadMethodTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    int addArgs(int a, int b) {
+        return a + b;
+    }
+
+    int addArgs(int a, int b, int c) {
+        return a + b + c;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = (gid > 9 ? addArgs(inArray[gid], gid + 1) : addArgs(inArray[gid], gid - 1, gid - 2));
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/ShortArrayTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests accessing an array of shorts.
+ */
+public class ShortArrayTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public short[] inArray = new short[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = (short) ((i + 1) * (i % 3 == 0 ? 1 : -1));
+            outArray[i] = 99;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid];
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StaticFloatFieldReadTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests reading from a static float field.
+ */
+public class StaticFloatFieldReadTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public float[] outArray = new float[NUM];
+    public float[] inArray = new float[NUM];
+
+    static float floatField = 7.123f;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        float[] out = outArray;
+        float[] in = inArray;
+        dispatchLambdaKernel(NUM, (gid) -> {
+            out[gid] = in[gid] + floatField;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StaticIntField2ReadTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,56 @@
+/*
+ * 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.lambda;
+
+import org.junit.Test;
+
+/**
+ * Tests reading from a two static int fields in different classes.
+ */
+public class StaticIntField2ReadTest extends StaticIntFieldReadTest {
+
+    static int intField2 = 8;
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid] * intField1 + intField2;
+        });
+    }
+
+    @Override
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Override
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StaticIntFieldReadTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests reading from a static int field.
+ */
+public class StaticIntFieldReadTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    static int intField1 = 7;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid] + intField1;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StaticIntFieldSameClassTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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.lambda;
+
+import org.junit.Test;
+
+/**
+ * Tests reading from a two static int fields in the same class.
+ */
+public class StaticIntFieldSameClassTest extends StaticIntFieldReadTest {
+
+    static int myField1 = 5;
+    static int myField2 = -99;
+    @Result int fieldResult;
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        myField2 = -99;
+        dispatchLambdaKernel(NUM, (gid) -> {
+            int val = inArray[gid] * myField1;
+            outArray[gid] = val;
+            if (gid == 3)
+                myField2 = val + gid;
+        });
+        fieldResult = myField2;
+    }
+
+    @Override
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Override
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StaticIntFieldWriteTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,70 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests writing a static int field.
+ */
+public class StaticIntFieldWriteTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+    @Result int fieldResult;
+
+    static int intStaticField = -99;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        intStaticField = -99;
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid] * 2;
+            if (gid == 3)
+                intStaticField = outArray[gid];
+        });
+        fieldResult = intStaticField;   // save for kerneltester comparison
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StaticNBodyTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,116 @@
+/*
+ * 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.lambda;
+
+import java.util.*;
+import org.junit.*;
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Tests a static lambda version of nbody.
+ */
+public class StaticNBodyTest extends GraalKernelTester {
+
+    static final int bodies = 1024;
+    static final float delT = .005f;
+    static final float espSqr = 1.0f;
+    static final float mass = 5f;
+    static final int width = 768;
+    static final int height = 768;
+
+    @Result float[] in_xyz = new float[bodies * 3]; // positions xy and z of bodies
+
+    @Result float[] out_xyz = new float[bodies * 3]; // positions xy and z of bodies
+
+    @Result float[] in_vxyz = new float[bodies * 3]; // velocity component of x,y and z of
+    // bodies
+
+    @Result float[] out_vxyz = new float[bodies * 3];
+
+    static float[] seed_xyz = new float[bodies * 3];
+    static {
+        final float maxDist = width / 4;
+        for (int body = 0; body < (bodies * 3); body += 3) {
+            final float theta = (float) (Math.random() * Math.PI * 2);
+            final float phi = (float) (Math.random() * Math.PI * 2);
+            final float radius = (float) (Math.random() * maxDist);
+            seed_xyz[body + 0] = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2;
+            seed_xyz[body + 1] = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2;
+            seed_xyz[body + 2] = (float) (radius * Math.cos(phi));
+        }
+    }
+
+    @Override
+    public void runTest() {
+        System.arraycopy(seed_xyz, 0, in_xyz, 0, seed_xyz.length);
+        Arrays.fill(out_xyz, 0f);
+        Arrays.fill(out_vxyz, 0f);
+        Arrays.fill(in_vxyz, 0f);
+
+        // local copies for a static lambda
+        float[] in_xyz1 = this.in_xyz;
+        float[] out_xyz1 = this.out_xyz;
+        float[] in_vxyz1 = this.in_vxyz;
+        float[] out_vxyz1 = this.out_vxyz;
+
+        dispatchLambdaKernel(bodies, (gid) -> {
+            final int count = bodies * 3;
+            final int globalId = gid * 3;
+
+            float accx = 0.f;
+            float accy = 0.f;
+            float accz = 0.f;
+            for (int i = 0; i < count; i += 3) {
+                final float dx = in_xyz1[i + 0] - in_xyz1[globalId + 0];
+                final float dy = in_xyz1[i + 1] - in_xyz1[globalId + 1];
+                final float dz = in_xyz1[i + 2] - in_xyz1[globalId + 2];
+                final float invDist = (float) (1.0 / (Math.sqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr)));
+                accx += mass * invDist * invDist * invDist * dx;
+                accy += mass * invDist * invDist * invDist * dy;
+                accz += mass * invDist * invDist * invDist * dz;
+            }
+            accx *= delT;
+            accy *= delT;
+            accz *= delT;
+            out_xyz1[globalId + 0] = in_xyz1[globalId + 0] + (in_vxyz1[globalId + 0] * delT) + (accx * .5f * delT);
+            out_xyz1[globalId + 1] = in_xyz1[globalId + 1] + (in_vxyz1[globalId + 1] * delT) + (accy * .5f * delT);
+            out_xyz1[globalId + 2] = in_xyz1[globalId + 2] + (in_vxyz1[globalId + 2] * delT) + (accz * .5f * delT);
+
+            out_vxyz1[globalId + 0] = in_vxyz1[globalId + 0] + accx;
+            out_vxyz1[globalId + 1] = in_vxyz1[globalId + 1] + accy;
+            out_vxyz1[globalId + 2] = in_vxyz1[globalId + 2] + accz;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StringContainsTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests calling String.contains().
+ */
+public class StringContainsTest 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, i, 10);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        String base = "CDE";
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid].contains(base);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StringEqualsTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests calling String.equals().
+ */
+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));
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        String base = "ABCDEFGHIJ";
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid].equals(base);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StringHashTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests calling String.hashCode().
+ */
+public class StringHashTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[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, i + 1);
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid].hashCode();
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StringLenTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests calling String.length().
+ */
+public class StringLenTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public String[] inArray = new String[NUM];
+
+    void setupArrays() {
+        char[] chars = new char[100];
+        for (int i = 0; i < chars.length; i++) {
+            chars[i] = 'A';
+        }
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new String(chars, 0, i + 10);
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid].length();
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StringUtilsCountMatches2Test.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.lambda;
+
+import static com.oracle.graal.compiler.hsail.test.lambda.StringUtilsCountMatchesTest.*;
+
+import org.junit.*;
+
+/**
+ * Tests calling a method similar to {@code StringUtils.countMatches()} from the Apache commons-lang
+ * library. The second argument varies per workitem.
+ */
+public class StringUtilsCountMatches2Test extends CountMatchesBase {
+    @Override
+    void setupArrays() {
+        char[] chars = new char[100];
+        for (int i = 0; i < chars.length; i++) {
+            chars[i] = (char) ('A' + (i % 10));
+        }
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new String(chars, i, (i % 5 + 1));
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        String base = "ABCDE BCDEF CDEFG DEFGH EFGHI FGHIJ ABCDE BCDEF CDEFG DEFGH EFGHI FGHIJ ";
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = countMatches(base, inArray[gid]);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/StringUtilsCountMatchesTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.lambda;
+
+import org.junit.*;
+
+/**
+ * Tests calling a method similar to {@code StringUtils.countMatches()} from the Apache commons-lang
+ * library. The first argument varies per workitem.
+ */
+public class StringUtilsCountMatchesTest extends CountMatchesBase {
+
+    public static int countMatches(String str, String sub) {
+        if (isEmpty(str) || isEmpty(sub)) {
+            return 0;
+        }
+        int count = 0;
+        int idx = 0;
+        while ((idx = str.indexOf(sub, idx)) != -1) {
+            count++;
+            idx += sub.length();
+        }
+        return count;
+    }
+
+    private static boolean isEmpty(String str) {
+        return str == null || str.length() == 0;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        String base = "CDE";
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = countMatches(inArray[gid], base);
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/SynchronizedMethodTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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.lambda;
+
+import static com.oracle.graal.debug.Debug.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
+import org.junit.Test;
+
+/**
+ * Tests calling a synchronized method.
+ */
+public class SynchronizedMethodTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    synchronized int syncSquare(int n) {
+        return n * n;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = syncSquare(inArray[gid]);
+        });
+    }
+
+    // cannot handle the BeginLockScope node
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void test() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
+    }
+
+    // cannot handle the BeginLockScope node
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void testUsingLambdaMethod() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
+    }
+
+}
--- /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/lambda/TooSimpleNewTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests a very simple non-escaping object allocation.
+ */
+public class TooSimpleNewTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public float[] outArray = new float[NUM];
+    public float[] inArray = new float[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            float inval = inArray[gid];
+            Vec3 vec3 = new Vec3(inval + 1, inval + 2, inval + 3);
+            outArray[gid] = vec3.x;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/TwoDIntArrayTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests reading from a 2-D int array.
+ */
+public class TwoDIntArrayTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[][] inArray = new int[NUM][NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            for (int j = 0; j < NUM; j++) {
+                inArray[i][j] = i * j;
+            }
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = inArray[gid][gid] + 100;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/VarArgsTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests calling a varargs method.
+ */
+public class VarArgsTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public int[] outArray = new int[NUM];
+    public int[] inArray = new int[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = i;
+            outArray[i] = -i;
+        }
+    }
+
+    int addArgs(Object... args) {
+        int sum = 0;
+        for (Object n : args) {
+            sum += (Integer) n;
+        }
+        return sum;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            outArray[gid] = (gid > 9 ? addArgs(gid, gid + 1, gid + 2) : addArgs(inArray[gid], gid - 1, gid - 2, gid - 3));
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/Vec3ObjStreamFloatCaptureTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests codegen for a java 8 lambda style object array stream kernel, one float capture.
+ */
+public class Vec3ObjStreamFloatCaptureTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Vec3[] inArray = new Vec3[NUM];
+    float baseAdjustment = 0.5f;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new Vec3(i, i + 1, -1);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        float adjustment = baseAdjustment;
+        dispatchLambdaKernel(inArray, obj -> {
+            Vec3 vec3 = (Vec3) obj;
+            vec3.z = vec3.x + vec3.y - adjustment;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- /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/lambda/Vec3ObjStreamIntCaptureTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests codegen for a java 8 style object array stream kernel, one int capture.
+ */
+public class Vec3ObjStreamIntCaptureTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Vec3[] inArray = new Vec3[NUM];
+    int baseAdjustment = 7;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new Vec3(i, i + 1, -1);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        int adjustment = baseAdjustment;
+        dispatchLambdaKernel(inArray, obj -> {
+            Vec3 vec3 = (Vec3) obj;
+            vec3.z = vec3.x + vec3.y - adjustment;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- /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/lambda/Vec3ObjStreamIntFloatCaptureTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests codegen for a java 8 style object array stream kernel, one int and one float capture.
+ */
+public class Vec3ObjStreamIntFloatCaptureTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Vec3[] inArray = new Vec3[NUM];
+    int baseAdjustment = 7;
+    float baseMultiplier = 0.5f;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new Vec3(i, i + 1, -1);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        int adjustment = baseAdjustment;
+        float multiplier = baseMultiplier;
+
+        dispatchLambdaKernel(inArray, obj -> {
+            Vec3 vec3 = (Vec3) obj;
+            vec3.z = (vec3.x + vec3.y - adjustment) * multiplier;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- /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/lambda/Vec3ObjStreamObjCaptureTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests codegen for a java 8 lambda style object array stream kernel, one object capture.
+ */
+public class Vec3ObjStreamObjCaptureTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Vec3[] inArray = new Vec3[NUM];
+    float baseAdjustment = 0.5f;
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new Vec3(i, i + 1, -1);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        Vec3 basevec = new Vec3(1, 2, 3);
+        dispatchLambdaKernel(inArray, obj -> {
+            Vec3 vec3 = (Vec3) obj;
+            vec3.z = vec3.x + vec3.y - basevec.z;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- /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/lambda/Vec3ObjStreamObjFieldTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests codegen for a java 8 style object array stream kernel. Instance method which accesses an
+ * object field.
+ */
+public class Vec3ObjStreamObjFieldTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Vec3[] inArray = new Vec3[NUM];
+    Vec3 basevec = new Vec3(1, 2, 3);
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new Vec3(i, i + 1, -1);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchLambdaKernel(inArray, obj -> {
+            Vec3 vec3 = (Vec3) obj;
+            vec3.z = vec3.x + vec3.y - basevec.z;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- /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/lambda/Vec3ObjStreamTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.Vec3;
+
+/**
+ * Tests codegen for a java 8 style object array stream kernel, no captures.
+ */
+public class Vec3ObjStreamTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Vec3[] inArray = new Vec3[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new Vec3(i, i + 1, -1);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchLambdaKernel(inArray, obj -> {
+            Vec3 vec3 = (Vec3) obj;
+            vec3.z = vec3.x + vec3.y;
+        });
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- /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/lambda/VecmathNBodyTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,135 @@
+/*
+ * 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.lambda;
+
+import java.util.*;
+import org.junit.*;
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import javax.vecmath.*;
+
+/**
+ * Tests NBody algorithm using the javax.vecmath package (all objects non-escaping).
+ */
+public class VecmathNBodyTest extends GraalKernelTester {
+    static final int bodies = 1024;
+    static final float delT = .005f;
+    static final float espSqr = 1.0f;
+    static final float mass = 5f;
+    static final int width = 768;
+    static final int height = 768;
+
+    static class Body extends Vector3f {
+
+        /**
+         *
+         */
+        private static final long serialVersionUID = 1L;
+
+        public Body(float _x, float _y, float _z, float _m) {
+            super(_x, _y, _z);
+            m = _m;
+            v = new Vector3f(0, 0, 0);
+        }
+
+        float m;
+        Vector3f v;
+
+        public float getM() {
+            return m;
+        }
+
+        public Vector3f computeAcc(Body[] in_bodies, float espSqr1, float delT1) {
+            Vector3f acc = new Vector3f();
+
+            for (Body b : in_bodies) {
+                Vector3f d = new Vector3f();
+                d.sub(b, this);
+                float invDist = 1.0f / (float) Math.sqrt(d.lengthSquared() + espSqr1);
+                float s = b.getM() * invDist * invDist * invDist;
+                acc.scaleAdd(s, d, acc);
+            }
+
+            // now return acc scaled by delT
+            acc.scale(delT1);
+            return acc;
+        }
+    }
+
+    @Result Body[] in_bodies = new Body[bodies];
+    @Result Body[] out_bodies = new Body[bodies];
+
+    static Body[] seed_bodies = new Body[bodies];
+
+    static {
+        java.util.Random randgen = new Random(0);
+        final float maxDist = width / 4;
+        for (int body = 0; body < bodies; body++) {
+            final float theta = (float) (randgen.nextFloat() * Math.PI * 2);
+            final float phi = (float) (randgen.nextFloat() * Math.PI * 2);
+            final float radius = randgen.nextFloat() * maxDist;
+            float x = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2;
+            float y = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2;
+            float z = (float) (radius * Math.cos(phi));
+            seed_bodies[body] = new Body(x, y, z, mass);
+        }
+    }
+
+    @Override
+    public void runTest() {
+        System.arraycopy(seed_bodies, 0, in_bodies, 0, seed_bodies.length);
+        for (int b = 0; b < bodies; b++) {
+            out_bodies[b] = new Body(0, 0, 0, mass);
+        }
+        // no local copies of arrays so we make it an instance lambda
+
+        dispatchLambdaKernel(bodies, (gid) -> {
+            Body inb = in_bodies[gid];
+            Body outb = out_bodies[gid];
+            Vector3f acc = inb.computeAcc(in_bodies, espSqr, delT);
+
+            Vector3f tmpPos = new Vector3f();
+            tmpPos.scaleAdd(delT, inb.v, inb);
+            tmpPos.scaleAdd(0.5f * delT, acc, tmpPos);
+            outb.set(tmpPos);
+
+            outb.v.add(inb.v, acc);
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleDeoptVirtualObjects());
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+
+}
--- /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/lambda/VectorStreamTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,190 @@
+/*
+ * 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.lambda;
+
+import java.util.Vector;
+import java.util.stream.Stream;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+/**
+ * Sumatra API tests which use a Stream derived from a Vector.
+ */
+public class VectorStreamTest {
+
+    // Static and instance fields to test codegen for
+    // each type of variable
+    static int staticSize = 16;
+    final int size = staticSize;
+
+    static int staticFactor = 3;
+    final int factor = staticFactor;
+
+    class MyPoint {
+
+        int x;
+        int y;
+
+        public MyPoint(int _x, int _y) {
+            x = _x;
+            y = _y;
+        }
+    }
+
+    public Vector<MyPoint> buildMyPointInputArray() {
+        Vector<MyPoint> inputs = new Vector<>(size);
+
+        for (int i = 0; i < size; i++) {
+            inputs.add(new MyPoint(i, i + 1));
+        }
+        return inputs;
+    }
+
+    public int[] buildIntInputArray() {
+        int[] inputs = new int[size];
+
+        for (int i = 0; i < size; i++) {
+            inputs[i] = i * 4;
+        }
+        return inputs;
+    }
+
+    @Test
+    public void testForEachObjectStreamNoCaptures() {
+        Vector<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            // Swap the values
+            int tmp = p.x;
+            p.x = p.y + factor;
+            p.y = tmp;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.x == (p.y + 1 + factor));
+        }
+    }
+
+    @Test
+    public void testForEachObjectStreamNoCapturesUseStatic() {
+        Vector<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            // Swap the values
+            int tmp = p.x;
+            p.x = p.y + staticFactor;
+            p.y = tmp;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.x == (p.y + 1 + staticFactor));
+        }
+    }
+
+    @Test
+    public void testForEachObjectStreamOneCapture() {
+        int[] data = buildIntInputArray();
+        Vector<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            p.y = data[p.x];
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x]);
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamOneCaptureUseStatic() {
+        int[] data = buildIntInputArray();
+        Vector<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            p.y = data[p.x] + staticFactor;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == (data[p.x] + +staticFactor));
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamTwoCaptures() {
+        int[] data = buildIntInputArray();
+        int[] data2 = buildIntInputArray();
+        Vector<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            p.y = data[p.x] + data2[p.x];
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x] + data2[p.x]);
+        }
+
+    }
+
+    @Test
+    public void testForEachObjectStreamTwoCapturesUseStatic() {
+        int[] data = buildIntInputArray();
+        int[] data2 = buildIntInputArray();
+        Vector<MyPoint> inputs = buildMyPointInputArray();
+
+        Stream<MyPoint> s = inputs.stream();
+        s = s.parallel();
+        s.forEach(p -> {
+            p.y = data[p.x] + data2[p.x] + staticFactor;
+        });
+
+        for (int k = 0; k < size; k++) {
+            MyPoint p = inputs.get(k);
+            // System.out.println( k + " ... p.x=" + p.x );
+            assertTrue(p.y == data[p.x] + data2[p.x] + staticFactor);
+        }
+
+    }
+}
--- /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/lambda/VirtualCallTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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.lambda;
+
+import static com.oracle.graal.debug.Debug.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
+import org.junit.Test;
+
+/**
+ * Tests a true virtual method call.
+ */
+public class VirtualCallTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    static abstract class Shape {
+
+        abstract public float getArea();
+    }
+
+    static class Circle extends Shape {
+
+        private float radius;
+
+        Circle(float r) {
+            radius = r;
+        }
+
+        @Override
+        public float getArea() {
+            return (float) (Math.PI * radius * radius);
+        }
+    }
+
+    static class Square extends Shape {
+
+        private float len;
+
+        Square(float _len) {
+            len = _len;
+        }
+
+        @Override
+        public float getArea() {
+            return len * len;
+        }
+    }
+
+    @Result public float[] outArray = new float[NUM];
+    public Shape[] inShapeArray = new Shape[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            if (i % 2 == 0)
+                inShapeArray[i] = new Circle(i + 1);
+            else
+                inShapeArray[i] = new Square(i + 1);
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchLambdaKernel(NUM, (gid) -> {
+            Shape shape = inShapeArray[gid];
+            outArray[gid] = shape.getArea();
+        });
+    }
+
+    // graal says not inlining getArea():float (0 bytes): no type profile exists
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void test() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
+    }
+
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void testUsingLambdaMethod() {
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,10 +31,11 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.lir.hsail.HSAILArithmetic.ConvertOp;
 import com.oracle.graal.lir.hsail.HSAILArithmetic.Op1Stack;
@@ -50,9 +51,6 @@
 import com.oracle.graal.lir.hsail.HSAILMove.MembarOp;
 import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp;
 import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -93,7 +91,7 @@
 
     @Override
     public Variable emitMove(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getPlatformKind());
         emitMove(result, input);
         return result;
     }
@@ -148,8 +146,7 @@
                 finalDisp += asConstant(index).asLong() * scale;
             } else {
                 Value indexRegister;
-                Value convertedIndex;
-                convertedIndex = this.emitSignExtend(index, 32, 64);
+                Value convertedIndex = index.getKind() == Kind.Long ? index : this.emitSignExtend(index, 32, 64);
                 if (scale != 1) {
                     indexRegister = emitUMul(convertedIndex, Constant.forInt(scale));
                 } else {
@@ -221,7 +218,9 @@
 
     @Override
     public void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
-        throw GraalInternalError.unimplemented();
+        Variable result = emitAnd(left, right);
+        Variable dummyResult = newVariable(left.getKind());
+        append(new CompareBranchOp(mapKindToCompareOp(left.getKind()), Condition.EQ, result, Constant.forInt(0), dummyResult, dummyResult, trueDestination, falseDestination, false));
     }
 
     @Override
@@ -415,7 +414,7 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitDiv(Value a, Value b, LIRFrameState state) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -438,7 +437,7 @@
     }
 
     @Override
-    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitRem(Value a, Value b, LIRFrameState state) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -460,12 +459,12 @@
     }
 
     @Override
-    public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
+    public Variable emitUDiv(Value a, Value b, LIRFrameState state) {
         throw GraalInternalError.unimplemented();
     }
 
     @Override
-    public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
+    public Variable emitURem(Value a, Value b, LIRFrameState state) {
         throw GraalInternalError.unimplemented();
     }
 
@@ -683,7 +682,7 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
@@ -830,7 +829,7 @@
      * Graal generates for any switch construct appearing in Java bytecode.
      */
     @Override
-    protected void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) {
+    public void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) {
         emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget);
     }
 
@@ -855,7 +854,7 @@
      * @param key the key that is compared against the key constants in the case statements.
      */
     @Override
-    protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
+    public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
         if ((key.getKind() == Kind.Int) || (key.getKind() == Kind.Long)) {
             // Append the LIR instruction for generating compare and branch instructions.
             append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key));
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,13 +24,13 @@
 package com.oracle.graal.compiler.hsail;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This class implements the HSAIL specific portion of the LIR generator.
@@ -63,20 +63,16 @@
     }
 
     @Override
-    public void visitSafepointNode(SafepointNode i) {
-        Debug.log("visitSafePointNode unimplemented");
-    }
-
-    @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
         assert v.stamp() instanceof ObjectStamp;
         Variable obj = newVariable(Kind.Object);
         gen.emitMove(obj, operand(v));
-        append(new HSAILMove.NullCheckOp(obj, gen.state(deopting)));
+        append(new HSAILMove.NullCheckOp(obj, state(deopting)));
     }
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
+        // TODO Auto-generated method stub
         throw GraalInternalError.unimplemented();
     }
 }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,6 +35,7 @@
         test("testIfElse2I", 19, 64);
     }
 
+    @Ignore("PTXHotSpotLIRGenerator.emitCompress is unimplemented")
     @Test
     public void testControl2() {
         compileKernel("testStatic");
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ObjectPTXTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ObjectPTXTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -151,7 +151,7 @@
     @Ignore("Object return values not yet supported")
     @Test
     public void test9() {
-        for (Object o : new Object[]{null, "object", new Object(), new HashMap()}) {
+        for (Object o : new Object[]{null, "object", new Object(), new HashMap<>()}) {
             A a = new A();
             a.o = o;
             test("testObject", a);
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -32,10 +32,12 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.ptx.*;
 import com.oracle.graal.lir.ptx.PTXArithmetic.ConvertOp;
 import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack;
@@ -57,11 +59,6 @@
 import com.oracle.graal.lir.ptx.PTXMemOp.StoreReturnValOp;
 import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp;
 import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -232,25 +229,17 @@
     }
 
     @Override
-    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) {
         PTXAddressValue loadAddress = asAddress(address);
         Variable result = newVariable(kind);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
         append(new LoadOp((Kind) kind, result, loadAddress, state));
         return result;
     }
 
     @Override
-    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) {
         PTXAddressValue storeAddress = asAddress(address);
         Variable input = load(inputVal);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
         append(new StoreOp((Kind) kind, storeAddress, input, state));
     }
 
@@ -376,7 +365,6 @@
 
     @Override
     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
-
         emitIntegerTest(left, right);
         Variable result = newVariable(trueValue.getKind());
         append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue), nextPredRegNum));
@@ -386,7 +374,6 @@
     }
 
     private void emitIntegerTest(Value a, Value b) {
-
         assert a.getKind().isNumericInteger();
 
         if (LIRValueUtil.isVariable(b)) {
@@ -498,7 +485,7 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitDiv(Value a, Value b, LIRFrameState state) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -520,7 +507,7 @@
     }
 
     @Override
-    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitRem(Value a, Value b, LIRFrameState state) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -536,12 +523,12 @@
     }
 
     @Override
-    public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
+    public Variable emitUDiv(Value a, Value b, LIRFrameState state) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUDiv()");
     }
 
     @Override
-    public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
+    public Variable emitURem(Value a, Value b, LIRFrameState state) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitURem()");
     }
 
@@ -555,7 +542,6 @@
             case Long:
                 append(new Op2Stack(LAND, result, a, loadNonConst(b)));
                 break;
-
             default:
                 throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
         }
@@ -754,7 +740,7 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
@@ -830,13 +816,12 @@
 
     @Override
     public void emitReturn(Value input) {
-        AllocatableValue operand = Value.ILLEGAL;
         if (input != null) {
-            operand = resultOperandFor(input.getKind());
+            AllocatableValue operand = resultOperandFor(input.getKind());
             // Load the global memory address from return parameter
             Variable loadVar = emitLoadReturnAddress(operand.getKind(), operand, null);
-            // Store result in global memory whose location is loadVar
-            emitStoreReturnValue(operand.getKind(), loadVar, operand, null);
+            // Store input in global memory whose location is loadVar
+            emitStoreReturnValue(operand.getKind(), loadVar, input, null);
         }
         emitReturnNoVal();
     }
@@ -846,7 +831,7 @@
     }
 
     @Override
-    protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
+    public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
         boolean needsTemp = key.getKind() == Kind.Object;
         append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL, nextPredRegNum++));
     }
@@ -864,17 +849,16 @@
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUnwind()");
     }
 
-    public Variable emitLoadParam(Kind kind, Value address, DeoptimizingNode deopting) {
+    public Variable emitLoadParam(Kind kind, Value address, LIRFrameState state) {
 
         PTXAddressValue loadAddress = asAddress(address);
         Variable result = newVariable(kind);
-        append(new LoadParamOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
+        append(new LoadParamOp(kind, result, loadAddress, state));
 
         return result;
     }
 
-    public Variable emitLoadReturnAddress(Kind kind, Value address, DeoptimizingNode deopting) {
-
+    public Variable emitLoadReturnAddress(Kind kind, Value address, LIRFrameState state) {
         PTXAddressValue loadAddress = asAddress(address);
         Variable result;
         switch (kind) {
@@ -886,18 +870,16 @@
                 break;
             default:
                 result = newVariable(kind);
-
         }
-        append(new LoadReturnAddrOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
+        append(new LoadReturnAddrOp(kind, result, loadAddress, state));
 
         return result;
     }
 
-    public void emitStoreReturnValue(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
-
+    public void emitStoreReturnValue(Kind kind, Value address, Value inputVal, LIRFrameState state) {
         PTXAddressValue storeAddress = asAddress(address);
         Variable input = load(inputVal);
-        append(new StoreReturnValOp(kind, storeAddress, input, deopting != null ? state(deopting) : null));
+        append(new StoreReturnValOp(kind, storeAddress, input, state));
     }
 
     @Override
@@ -908,4 +890,8 @@
         return (new Variable(kind, 0));
     }
 
+    public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        throw GraalInternalError.unimplemented();
+    }
+
 }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,13 +27,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.ptx.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 
 /**
  * This class implements the PTX specific portion of the LIR generator.
@@ -122,11 +122,6 @@
     }
 
     @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitCompareAndSwap()");
-    }
-
-    @Override
     public void visitBreakpointNode(BreakpointNode node) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.visitBreakpointNode()");
     }
@@ -141,7 +136,7 @@
     @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
         assert v.getKind() == Kind.Object;
-        append(new PTXMove.NullCheckOp(gen.load(operand(v)), gen.state(deopting)));
+        append(new PTXMove.NullCheckOp(gen.load(operand(v)), state(deopting)));
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -33,10 +33,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryCommutative;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegConst;
@@ -57,10 +59,6 @@
 import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp;
 import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -362,7 +360,7 @@
     }
 
     @Override
-    protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
+    public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
         // a temp is needed for loading long and object constants
         boolean needsTemp = key.getKind() == Kind.Long || key.getKind() == Kind.Object;
         append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL));
@@ -593,7 +591,7 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitDiv(Value a, Value b, LIRFrameState state) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind().getStackKind()) {
             case Int:
@@ -615,8 +613,7 @@
     }
 
     @Override
-    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
-        LIRFrameState state = state(deopting);
+    public Value emitRem(Value a, Value b, LIRFrameState state) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind().getStackKind()) {
             case Int:
@@ -632,7 +629,7 @@
     }
 
     @Override
-    public Value emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitUDiv(Value a, Value b, LIRFrameState state) {
         // LIRFrameState state = state(deopting);
         switch (a.getKind().getStackKind()) {
             case Int:
@@ -647,7 +644,7 @@
     }
 
     @Override
-    public Value emitURem(Value a, Value b, DeoptimizingNode deopting) {
+    public Value emitURem(Value a, Value b, LIRFrameState state) {
         // LIRFrameState state = state(deopting);
         switch (a.getKind().getStackKind()) {
             case Int:
@@ -917,7 +914,7 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,11 +25,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 
 /**
  * This class implements the SPARC specific portion of the LIR generator.
@@ -47,11 +48,6 @@
     }
 
     @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
     public void visitBreakpointNode(BreakpointNode node) {
         JavaType[] sig = new JavaType[node.arguments().size()];
         for (int i = 0; i < sig.length; i++) {
@@ -65,11 +61,12 @@
     @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
         assert v.getKind() == Kind.Object;
-        append(new NullCheckOp(gen.load(operand(v)), gen.state(deopting)));
+        append(new NullCheckOp(gen.load(operand(v)), state(deopting)));
     }
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        throw new InternalError("NYI");
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.test;
 
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
 import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
@@ -33,7 +35,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
@@ -42,15 +43,16 @@
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.phases.verify.*;
 import com.oracle.graal.runtime.*;
+import com.oracle.graal.test.*;
 
 /**
  * Checks that all classes in graal.jar (which must be on the class path) comply with global
  * invariants such as using {@link Object#equals(Object)} to compare certain types instead of
  * identity comparisons.
  */
-public class CheckGraalInvariants {
+public class CheckGraalInvariants extends GraalTest {
 
-    @Test
+    @LongTest
     public void test() {
         RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class);
         Providers providers = rt.getHostBackend().getProviders();
@@ -106,14 +108,7 @@
                         String methodName = className + "." + m.getName();
                         if (matches(filters, methodName)) {
                             StructuredGraph graph = new StructuredGraph(metaAccess.lookupJavaMethod(m));
-                            DebugConfig debugConfig = DebugScope.getConfig();
-                            DebugConfig noInterceptConfig = new DelegatingDebugConfig(debugConfig) {
-                                @Override
-                                public RuntimeException interceptException(Throwable e) {
-                                    return null;
-                                }
-                            };
-                            try (DebugConfigScope s = Debug.setConfig(noInterceptConfig)) {
+                            try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
                                 graphBuilderSuite.apply(graph, context);
                                 checkGraph(context, graph);
                             } catch (VerificationError e) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,7 +29,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.compiler.common.calc.*;
 
 public class ConditionTest {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -59,7 +59,7 @@
         }
     }
 
-    private StructuredGraph parseAndProcess(Class cl, Assumptions assumptions) {
+    private StructuredGraph parseAndProcess(Class<?> cl, Assumptions assumptions) {
         Constructor<?>[] constructors = cl.getConstructors();
         Assert.assertTrue(constructors.length == 1);
         final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaConstructor(constructors[0]);
@@ -73,7 +73,7 @@
         return graph;
     }
 
-    private void checkForRegisterFinalizeNode(Class cl, boolean shouldContainFinalizer, boolean optimistic) {
+    private void checkForRegisterFinalizeNode(Class<?> cl, boolean shouldContainFinalizer, boolean optimistic) {
         Assumptions assumptions = new Assumptions(optimistic);
         StructuredGraph graph = parseAndProcess(cl, assumptions);
         Assert.assertTrue(graph.getNodes().filter(RegisterFinalizerNode.class).count() == (shouldContainFinalizer ? 1 : 0));
@@ -109,7 +109,7 @@
         private static int loaderInstance = 0;
 
         private final String replaceTo;
-        private HashMap<String, Class> cache = new HashMap<>();
+        private HashMap<String, Class<?>> cache = new HashMap<>();
 
         public ClassTemplateLoader() {
             loaderInstance++;
@@ -149,7 +149,7 @@
             }
             dumpStringsInByteArray(classData);
 
-            Class c = defineClass(null, classData, 0, classData.length);
+            Class<?> c = defineClass(null, classData, 0, classData.length);
             cache.put(nameReplaced, c);
             return c;
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,8 +24,8 @@
 
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -38,8 +38,10 @@
 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.replacements.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.baseline.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -168,7 +170,7 @@
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) {
         String expectedString = getCanonicalGraphString(expected, excludeVirtual, checkConstants);
         String actualString = getCanonicalGraphString(graph, excludeVirtual, checkConstants);
-        String mismatchString = "mismatch in graphs:\n========= expected =========\n" + expectedString + "\n\n========= actual =========\n" + actualString;
+        String mismatchString = "mismatch in graphs:\n========= expected (" + expected + ") =========\n" + expectedString + "\n\n========= actual (" + graph + ") =========\n" + actualString;
 
         if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
             Debug.dump(expected, "Node count not matching - expected");
@@ -240,6 +242,10 @@
         return providers;
     }
 
+    protected SnippetReflectionProvider getSnippetReflection() {
+        return Graal.getRequiredCapability(SnippetReflectionProvider.class);
+    }
+
     protected TargetDescription getTarget() {
         return getProviders().getCodeCache().getTarget();
     }
@@ -670,7 +676,7 @@
     }
 
     protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) {
-        return getCodeCache().addMethod(method, compResult, null);
+        return getCodeCache().addMethod(method, compResult, null, null);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.compiler.test;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static org.junit.Assert.*;
 
 import java.util.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import org.junit.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -148,10 +149,10 @@
         Debug.dump(graph, "Graph");
         ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
 
-        Assert.assertTrue(cfg.getLoops().length == 3);
-        Loop rootLoop = cfg.getLoops()[0];
-        Loop nestedLoop = cfg.getLoops()[1];
-        Loop innerMostLoop = cfg.getLoops()[2];
+        Assert.assertTrue(cfg.getLoops().size() == 3);
+        Loop<Block> rootLoop = cfg.getLoops().get(0);
+        Loop<Block> nestedLoop = cfg.getLoops().get(1);
+        Loop<Block> innerMostLoop = cfg.getLoops().get(2);
         Invoke a = getInvoke("a", graph);
         Invoke b = getInvoke("b", graph);
         Invoke c = getInvoke("c", graph);
@@ -168,14 +169,14 @@
         Debug.dump(graph, "Graph");
     }
 
-    private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) {
+    private static boolean contains(Loop<Block> loop, Invoke node, ControlFlowGraph cfg) {
         Block block = cfg.blockFor((Node) node);
         Assert.assertNotNull(block);
         return loop.blocks.contains(block);
     }
 
-    private static boolean containsDirect(Loop loop, Invoke node, ControlFlowGraph cfg) {
-        for (Loop child : loop.children) {
+    private static boolean containsDirect(Loop<Block> loop, Invoke node, ControlFlowGraph cfg) {
+        for (Loop<Block> child : loop.children) {
             if (contains(child, node, cfg)) {
                 return false;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
@@ -71,7 +72,7 @@
             for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) {
                 if (rn.location() instanceof ConstantLocationNode && rn.object().stamp() instanceof ObjectStamp) {
                     long disp = ((ConstantLocationNode) rn.location()).getDisplacement();
-                    ResolvedJavaType receiverType = ObjectStamp.typeOrNull(rn.object());
+                    ResolvedJavaType receiverType = StampTool.typeOrNull(rn.object());
                     ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp);
 
                     assert field != null : "Node " + rn + " tries to access a field which doesn't exists for this type";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class PushThroughIfTest extends GraalCompilerTest {
+
+    public int field1;
+    public int field2;
+
+    public int testSnippet(boolean b) {
+        int i;
+        if (b) {
+            i = field1;
+        } else {
+            i = field1;
+        }
+        return i + field2;
+    }
+
+    @SuppressWarnings("unused")
+    public int referenceSnippet(boolean b) {
+        return field1 + field2;
+    }
+
+    @Test
+    public void test1() {
+        test("testSnippet", "referenceSnippet");
+    }
+
+    private void test(String snippet, String reference) {
+        StructuredGraph graph = parse(snippet);
+        Debug.dump(graph, "Graph");
+        for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) {
+            fs.replaceAtUsages(null);
+            GraphUtil.killWithUnusedFloatingInputs(fs);
+        }
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
+
+        StructuredGraph referenceGraph = parse(reference);
+        for (FrameState fs : referenceGraph.getNodes(FrameState.class).snapshot()) {
+            fs.replaceAtUsages(null);
+            GraphUtil.killWithUnusedFloatingInputs(fs);
+        }
+        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), new Assumptions(false)));
+        assertEquals(referenceGraph, graph);
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -41,9 +41,9 @@
         AbstractEndNode trueEnd = graph.add(new EndNode());
         AbstractEndNode falseEnd = graph.add(new EndNode());
 
-        AbstractBeginNode trueBegin = graph.add(new BeginNode());
+        BeginNode trueBegin = graph.add(new BeginNode());
         trueBegin.setNext(trueEnd);
-        AbstractBeginNode falseBegin = graph.add(new BeginNode());
+        BeginNode falseBegin = graph.add(new BeginNode());
         falseBegin.setNext(falseEnd);
 
         IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,8 +25,8 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.compiler.test.backend;
 
 import static com.oracle.graal.api.code.CodeUtil.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
@@ -33,15 +33,15 @@
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
 
@@ -114,7 +114,7 @@
         SchedulePhase schedule = null;
         try (Scope s = Debug.scope("FrontEnd")) {
             schedule = GraalCompiler.emitFrontEnd(getProviders(), getBackend().getTarget(), graph, assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE,
-                            graph.method().getProfilingInfo(), new SpeculationLog(), getSuites());
+                            graph.method().getProfilingInfo(), null, getSuites());
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -59,8 +59,8 @@
         new DeadCodeEliminationPhase().apply(graph);
 
         for (ConstantNode node : ConstantNode.getConstantNodes(graph)) {
-            if (node.getKind() == Kind.Object && " ".equals(node.getValue().asObject())) {
-                node.replace(graph, ConstantNode.forObject("-", getMetaAccess(), graph));
+            if (node.getKind() == Kind.Object && " ".equals(getSnippetReflection().asObject(node.getValue()))) {
+                node.replace(graph, ConstantNode.forConstant(getSnippetReflection().forObject("-"), getMetaAccess(), graph));
             }
         }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,10 +25,10 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
@@ -62,7 +62,7 @@
 
     @Test
     public void test3() {
-        testEscapeAnalysis("test3Snippet", Constant.forObject(null), false);
+        testEscapeAnalysis("test3Snippet", Constant.NULL_OBJECT, false);
     }
 
     public static Object test3Snippet() {
@@ -257,7 +257,7 @@
 
     @Test
     public void testCheckCast() {
-        testEscapeAnalysis("testCheckCastSnippet", Constant.forObject(TestClassObject.class), false);
+        testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), false);
     }
 
     public Object testCheckCastSnippet() {
@@ -279,7 +279,7 @@
 
     @SuppressWarnings("unused")
     public static void testNewNodeSnippet() {
-        new IntegerAddNode(new IntegerStamp(32, false, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null);
+        new IntegerAddNode(new IntegerStamp(32, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -120,6 +120,7 @@
     }
 
     @Test
+    @Ignore
     public void testCache() {
         testPartialEscapeAnalysis("testCacheSnippet", 0.75, 1);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.compiler.test.nfi;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static java.io.File.*;
 import static java.lang.System.*;
 import static org.junit.Assert.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,7 @@
 
 import static com.oracle.graal.compiler.GraalCompiler.Options.*;
 import static com.oracle.graal.compiler.MethodFilter.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
@@ -34,6 +34,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.alloc.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
@@ -41,6 +42,7 @@
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.util.*;
@@ -127,9 +129,8 @@
      *
      * @param graph the graph to be compiled
      * @param cc the calling convention for calls to the code compiled for {@code graph}
-     * @param installedCodeOwner the method the compiled code will be
-     *            {@linkplain InstalledCode#getMethod() associated} with once installed. This
-     *            argument can be null.
+     * @param installedCodeOwner the method the compiled code will be associated with once
+     *            installed. This argument can be null.
      * @return the result of the compilation
      */
     public static <T extends CompilationResult> T compileGraph(StructuredGraph graph, Object stub, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend,
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,8 +30,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.phases.util.*;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,10 +35,11 @@
 import com.oracle.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.graal.compiler.alloc.Interval.SpillState;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
@@ -46,7 +47,6 @@
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -335,7 +335,7 @@
     }
 
     int numLoops() {
-        return ir.getControlFlowGraph().getLoops().length;
+        return ir.getControlFlowGraph().getLoops().size();
     }
 
     boolean isIntervalInLoop(int interval, int loop) {
@@ -887,6 +887,7 @@
     private static NodeLIRBuilder getNodeLIRGeneratorFromDebugContext() {
         if (Debug.isEnabled()) {
             NodeLIRBuilder lirGen = Debug.contextLookup(NodeLIRBuilder.class);
+            assert lirGen != null;
             return lirGen;
         }
         return null;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed Apr 23 15:48:38 2014 +0200
@@ -34,10 +34,10 @@
 import com.oracle.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.graal.compiler.alloc.Interval.SpillState;
 import com.oracle.graal.compiler.alloc.Interval.State;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.util.*;
 
 /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,13 +28,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.util.*;
 
 /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,9 @@
  */
 package com.oracle.graal.compiler.gen;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.gen.*;
 
 public class BytecodeLIRBuilder {
     protected final LIRGenerator gen;
@@ -53,7 +52,7 @@
         gen.emitIncomingValues(params);
 
         Signature sig = method.getSignature();
-        boolean isStatic = Modifier.isStatic(method.getModifiers());
+        boolean isStatic = method.isStatic();
         for (int i = 0; i < sig.getParameterCount(!isStatic); i++) {
             Value paramValue = params[i];
             assert paramValue.getKind() == sig.getParameterKind(i).getStackKind();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
@@ -128,7 +129,6 @@
         if (state.outerFrameState() != null) {
             caller = computeFrameForState(state.outerFrameState());
         }
-        assert state.bci >= FrameState.BEFORE_BCI : "bci == " + state.bci;
         return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks);
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * 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.compiler.gen;
-
-import com.oracle.graal.lir.*;
-
-public interface LIRGenerationResult {
-    FrameMap getFrameMap();
-
-    LIR getLIR();
-
-    boolean hasForeignCall();
-
-    void setForeignCall(boolean b);
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResultBase.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * 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.compiler.gen;
-
-import com.oracle.graal.lir.*;
-
-public class LIRGenerationResultBase implements LIRGenerationResult {
-    private final LIR lir;
-    private final FrameMap frameMap;
-    /**
-     * Records whether the code being generated makes at least one foreign call.
-     */
-    private boolean hasForeignCall;
-
-    public LIRGenerationResultBase(LIR lir, FrameMap frameMap) {
-        this.lir = lir;
-        this.frameMap = frameMap;
-    }
-
-    public LIR getLIR() {
-        return lir;
-    }
-
-    /**
-     * Determines whether the code being generated makes at least one foreign call.
-     */
-    public boolean hasForeignCall() {
-        return hasForeignCall;
-    }
-
-    public final void setForeignCall(boolean hasForeignCall) {
-        this.hasForeignCall = hasForeignCall;
-    }
-
-    public final FrameMap getFrameMap() {
-        return frameMap;
-    }
-
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,637 +0,0 @@
-/*
- * 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.gen;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.api.meta.Value.*;
-import static com.oracle.graal.lir.LIR.*;
-import static com.oracle.graal.lir.LIRValueUtil.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.BlockEndOp;
-import com.oracle.graal.lir.StandardOp.LabelOp;
-import com.oracle.graal.lir.StandardOp.NoOp;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.options.*;
-import com.oracle.graal.phases.util.*;
-
-/**
- * This class traverses the HIR instructions and generates LIR instructions from them.
- */
-public abstract class LIRGenerator implements ArithmeticLIRGenerator, LIRGeneratorTool, LIRTypeTool {
-
-    public static class Options {
-        // @formatter:off
-        @Option(help = "Print HIR along side LIR as the latter is generated")
-        public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false);
-        @Option(help = "The trace level for the LIR generator")
-        public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0);
-        // @formatter:on
-    }
-
-    private final Providers providers;
-    private final CallingConvention cc;
-
-    private DebugInfoBuilder debugInfoBuilder;
-
-    protected AbstractBlock<?> currentBlock;
-    public final int traceLevel;
-    public final boolean printIRWithLIR;
-
-    /**
-     * Handle for an operation that loads a constant into a variable. The operation starts in the
-     * first block where the constant is used but will eventually be
-     * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the
-     * constant.
-     */
-    public static class LoadConstant implements Comparable<LoadConstant> {
-        /**
-         * The index of {@link #op} within {@link #block}'s instruction list or -1 if {@code op} is
-         * to be moved to a dominator block.
-         */
-        int index;
-
-        /**
-         * The operation that loads the constant.
-         */
-        private final LIRInstruction op;
-
-        /**
-         * The block that does or will contain {@link #op}. This is initially the block where the
-         * first usage of the constant is seen during LIR generation.
-         */
-        Block block;
-
-        /**
-         * The variable into which the constant is loaded.
-         */
-        final Variable variable;
-
-        public LoadConstant(Variable variable, Block block, int index, LIRInstruction op) {
-            this.variable = variable;
-            this.block = block;
-            this.index = index;
-            this.op = op;
-        }
-
-        /**
-         * Sorts {@link LoadConstant} objects according to their enclosing blocks. This is used to
-         * group loads per block in {@link LIRGenerator#insertConstantLoads()}.
-         */
-        public int compareTo(LoadConstant o) {
-            if (block.getId() < o.block.getId()) {
-                return -1;
-            }
-            if (block.getId() > o.block.getId()) {
-                return 1;
-            }
-            return 0;
-        }
-
-        @Override
-        public String toString() {
-            return block + "#" + op;
-        }
-
-        /**
-         * Removes the {@link #op} from its original location if it is still at that location.
-         */
-        public void unpin(LIR lir) {
-            if (index >= 0) {
-                // Replace the move with a filler op so that the operation
-                // list does not need to be adjusted.
-                List<LIRInstruction> instructions = lir.getLIRforBlock(block);
-                instructions.set(index, new NoOp(null, -1));
-                index = -1;
-            }
-        }
-    }
-
-    Map<Constant, LoadConstant> constantLoads;
-
-    private LIRGenerationResult res;
-
-    /**
-     * Set this before using the LIRGenerator.
-     *
-     * TODO this should be removed
-     */
-    void setDebugInfoBuilder(DebugInfoBuilder builder) {
-        debugInfoBuilder = builder;
-    }
-
-    /**
-     * Checks whether the supplied constant can be used without loading it into a register for store
-     * operations, i.e., on the right hand side of a memory access.
-     *
-     * @param c The constant to check.
-     * @return True if the constant can be used directly, false if the constant needs to be in a
-     *         register.
-     */
-    public abstract boolean canStoreConstant(Constant c, boolean isCompressed);
-
-    public LIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult res) {
-        this.res = res;
-        this.providers = providers;
-        this.cc = cc;
-        this.traceLevel = Options.TraceLIRGeneratorLevel.getValue();
-        this.printIRWithLIR = Options.PrintIRWithLIR.getValue();
-    }
-
-    /**
-     * Returns true if the redundant move elimination optimization should be done after register
-     * allocation.
-     */
-    public boolean canEliminateRedundantMoves() {
-        return true;
-    }
-
-    @Override
-    public TargetDescription target() {
-        return getCodeCache().getTarget();
-    }
-
-    public Providers getProviders() {
-        return providers;
-    }
-
-    @Override
-    public MetaAccessProvider getMetaAccess() {
-        return providers.getMetaAccess();
-    }
-
-    @Override
-    public CodeCacheProvider getCodeCache() {
-        return providers.getCodeCache();
-    }
-
-    @Override
-    public ForeignCallsProvider getForeignCalls() {
-        return providers.getForeignCalls();
-    }
-
-    /**
-     * Creates a new {@linkplain Variable variable}.
-     *
-     * @param platformKind The kind of the new variable.
-     * @return a new variable
-     */
-    @Override
-    public Variable newVariable(PlatformKind platformKind) {
-        return new Variable(platformKind, res.getLIR().nextVariable());
-    }
-
-    @Override
-    public RegisterAttributes attributes(Register register) {
-        return res.getFrameMap().registerConfig.getAttributesMap()[register.number];
-    }
-
-    @Override
-    public abstract Variable emitMove(Value input);
-
-    public AllocatableValue asAllocatable(Value value) {
-        if (isAllocatableValue(value)) {
-            return asAllocatableValue(value);
-        } else {
-            return emitMove(value);
-        }
-    }
-
-    public Variable load(Value value) {
-        if (!isVariable(value)) {
-            return emitMove(value);
-        }
-        return (Variable) value;
-    }
-
-    public Value loadNonConst(Value value) {
-        if (isConstant(value) && !canInlineConstant((Constant) value)) {
-            return emitMove(value);
-        }
-        return value;
-    }
-
-    public LabelRef getLIRBlock(FixedNode b) {
-        assert res.getLIR().getControlFlowGraph() instanceof ControlFlowGraph;
-        Block result = ((ControlFlowGraph) res.getLIR().getControlFlowGraph()).blockFor(b);
-        int suxIndex = currentBlock.getSuccessors().indexOf(result);
-        assert suxIndex != -1 : "Block not in successor list of current block";
-
-        assert currentBlock instanceof Block;
-        return LabelRef.forSuccessor(res.getLIR(), currentBlock, suxIndex);
-    }
-
-    /**
-     * Determines if only oop maps are required for the code generated from the LIR.
-     */
-    protected boolean needOnlyOopMaps() {
-        return false;
-    }
-
-    private static FrameState getFrameState(DeoptimizingNode deopt) {
-        if (deopt instanceof DeoptimizingNode.DeoptBefore) {
-            assert !(deopt instanceof DeoptimizingNode.DeoptDuring || deopt instanceof DeoptimizingNode.DeoptAfter);
-            return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore();
-        } else if (deopt instanceof DeoptimizingNode.DeoptDuring) {
-            assert !(deopt instanceof DeoptimizingNode.DeoptAfter);
-            return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring();
-        } else {
-            assert deopt instanceof DeoptimizingNode.DeoptAfter;
-            return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter();
-        }
-    }
-
-    public LIRFrameState state(DeoptimizingNode deopt) {
-        if (!deopt.canDeoptimize()) {
-            return null;
-        }
-        return stateFor(getFrameState(deopt));
-    }
-
-    public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
-        if (!deopt.canDeoptimize()) {
-            return null;
-        }
-        return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge);
-    }
-
-    public LIRFrameState stateFor(FrameState state) {
-        return stateForWithExceptionEdge(state, null);
-    }
-
-    public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) {
-        if (needOnlyOopMaps()) {
-            return new LIRFrameState(null, null, null);
-        }
-        assert state != null;
-        return getDebugInfoBuilder().build(state, exceptionEdge);
-    }
-
-    /**
-     * Gets the ABI specific operand used to return a value of a given kind from a method.
-     *
-     * @param kind the kind of value being returned
-     * @return the operand representing the ABI defined location used return a value of kind
-     *         {@code kind}
-     */
-    public AllocatableValue resultOperandFor(Kind kind) {
-        if (kind == Kind.Void) {
-            return ILLEGAL;
-        }
-        return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind);
-    }
-
-    public void append(LIRInstruction op) {
-        if (printIRWithLIR && !TTY.isSuppressed()) {
-            TTY.println(op.toStringWithIdPrefix());
-            TTY.println();
-        }
-        assert LIRVerifier.verify(op);
-        res.getLIR().getLIRforBlock(currentBlock).add(op);
-    }
-
-    public boolean hasBlockEnd(AbstractBlock<?> block) {
-        List<LIRInstruction> ops = getResult().getLIR().getLIRforBlock(block);
-        if (ops.size() == 0) {
-            return false;
-        }
-        return ops.get(ops.size() - 1) instanceof BlockEndOp;
-    }
-
-    public final void doBlockStart(AbstractBlock<?> block) {
-        if (printIRWithLIR) {
-            TTY.print(block.toString());
-        }
-
-        currentBlock = block;
-
-        // set up the list of LIR instructions
-        assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block";
-        res.getLIR().setLIRforBlock(block, new ArrayList<LIRInstruction>());
-
-        append(new LabelOp(new Label(block.getId()), block.isAligned()));
-
-        if (traceLevel >= 1) {
-            TTY.println("BEGIN Generating LIR for block B" + block.getId());
-        }
-    }
-
-    public final void doBlockEnd(AbstractBlock<?> block) {
-
-        if (traceLevel >= 1) {
-            TTY.println("END Generating LIR for block B" + block.getId());
-        }
-
-        currentBlock = null;
-
-        if (printIRWithLIR) {
-            TTY.println();
-        }
-    }
-
-    public void emitIncomingValues(Value[] params) {
-        ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params);
-    }
-
-    public abstract void emitJump(LabelRef label);
-
-    public abstract void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
-                    double trueDestinationProbability);
-
-    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
-
-    public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
-
-    public abstract Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
-
-    public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
-
-    protected abstract void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info);
-
-    public static AllocatableValue toStackKind(AllocatableValue value) {
-        if (value.getKind().getStackKind() != value.getKind()) {
-            // We only have stack-kinds in the LIR, so convert the operand kind for values from the
-            // calling convention.
-            if (isRegister(value)) {
-                return asRegister(value).asValue(value.getKind().getStackKind());
-            } else if (isStackSlot(value)) {
-                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
-            } else {
-                throw GraalInternalError.shouldNotReachHere();
-            }
-        }
-        return value;
-    }
-
-    @Override
-    public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
-        LIRFrameState state = null;
-        if (linkage.canDeoptimize()) {
-            if (info != null) {
-                state = stateFor(getFrameState(info));
-            } else {
-                assert needOnlyOopMaps();
-                state = new LIRFrameState(null, null, null);
-            }
-        }
-
-        // move the arguments into the correct location
-        CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
-        res.getFrameMap().callsMethod(linkageCc);
-        assert linkageCc.getArgumentCount() == args.length : "argument count mismatch";
-        Value[] argLocations = new Value[args.length];
-        for (int i = 0; i < args.length; i++) {
-            Value arg = args[i];
-            AllocatableValue loc = linkageCc.getArgument(i);
-            emitMove(loc, arg);
-            argLocations[i] = loc;
-        }
-        res.setForeignCall(true);
-        emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state);
-
-        if (isLegal(linkageCc.getReturn())) {
-            return emitMove(linkageCc.getReturn());
-        } else {
-            return null;
-        }
-    }
-
-    protected void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) {
-        int keyCount = keyConstants.length;
-        SwitchStrategy strategy = SwitchStrategy.getBestStrategy(keyProbabilities, keyConstants, keyTargets);
-        long valueRange = keyConstants[keyCount - 1].asLong() - keyConstants[0].asLong() + 1;
-        double tableSwitchDensity = keyCount / (double) valueRange;
-        /*
-         * This heuristic tries to find a compromise between the effort for the best switch strategy
-         * and the density of a tableswitch. If the effort for the strategy is at least 4, then a
-         * tableswitch is preferred if better than a certain value that starts at 0.5 and lowers
-         * gradually with additional effort.
-         */
-        if (strategy.getAverageEffort() < 4 || tableSwitchDensity < (1 / Math.sqrt(strategy.getAverageEffort()))) {
-            emitStrategySwitch(strategy, value, keyTargets, defaultTarget);
-        } else {
-            int minValue = keyConstants[0].asInt();
-            assert valueRange < Integer.MAX_VALUE;
-            LabelRef[] targets = new LabelRef[(int) valueRange];
-            for (int i = 0; i < valueRange; i++) {
-                targets[i] = defaultTarget;
-            }
-            for (int i = 0; i < keyCount; i++) {
-                targets[keyConstants[i].asInt() - minValue] = keyTargets[i];
-            }
-            emitTableSwitch(minValue, defaultTarget, targets, value);
-        }
-    }
-
-    protected abstract void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget);
-
-    protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key);
-
-    public CallingConvention getCallingConvention() {
-        return cc;
-    }
-
-    public DebugInfoBuilder getDebugInfoBuilder() {
-        assert debugInfoBuilder != null;
-        return debugInfoBuilder;
-    }
-
-    @Override
-    public void beforeRegisterAllocation() {
-        insertConstantLoads();
-    }
-
-    /**
-     * Moves deferred {@linkplain LoadConstant loads} of constants into blocks dominating all usages
-     * of the constant. Any operations inserted into a block are guaranteed to be immediately prior
-     * to the first control flow instruction near the end of the block.
-     */
-    private void insertConstantLoads() {
-        if (constantLoads != null) {
-            // Remove loads where all usages are in the same block.
-            for (Iterator<Map.Entry<Constant, LoadConstant>> iter = constantLoads.entrySet().iterator(); iter.hasNext();) {
-                LoadConstant lc = iter.next().getValue();
-
-                // Move loads of constant outside of loops
-                if (OptScheduleOutOfLoops.getValue()) {
-                    Block outOfLoopDominator = lc.block;
-                    while (outOfLoopDominator.getLoop() != null) {
-                        outOfLoopDominator = outOfLoopDominator.getDominator();
-                    }
-                    if (outOfLoopDominator != lc.block) {
-                        lc.unpin(res.getLIR());
-                        lc.block = outOfLoopDominator;
-                    }
-                }
-
-                if (lc.index != -1) {
-                    assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op;
-                    iter.remove();
-                }
-            }
-            if (constantLoads.isEmpty()) {
-                return;
-            }
-
-            // Sorting groups the loads per block.
-            LoadConstant[] groupedByBlock = constantLoads.values().toArray(new LoadConstant[constantLoads.size()]);
-            Arrays.sort(groupedByBlock);
-
-            int groupBegin = 0;
-            while (true) {
-                int groupEnd = groupBegin + 1;
-                Block block = groupedByBlock[groupBegin].block;
-                while (groupEnd < groupedByBlock.length && groupedByBlock[groupEnd].block == block) {
-                    groupEnd++;
-                }
-                int groupSize = groupEnd - groupBegin;
-
-                List<LIRInstruction> ops = res.getLIR().getLIRforBlock(block);
-                int lastIndex = ops.size() - 1;
-                assert ops.get(lastIndex) instanceof BlockEndOp;
-                int insertionIndex = lastIndex;
-                for (int i = Math.max(0, lastIndex - MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END); i < lastIndex; i++) {
-                    if (getExceptionEdge(ops.get(i)) != null) {
-                        insertionIndex = i;
-                        break;
-                    }
-                }
-
-                if (groupSize == 1) {
-                    ops.add(insertionIndex, groupedByBlock[groupBegin].op);
-                } else {
-                    assert groupSize > 1;
-                    List<LIRInstruction> moves = new ArrayList<>(groupSize);
-                    for (int i = groupBegin; i < groupEnd; i++) {
-                        moves.add(groupedByBlock[i].op);
-                    }
-                    ops.addAll(insertionIndex, moves);
-                }
-
-                if (groupEnd == groupedByBlock.length) {
-                    break;
-                }
-                groupBegin = groupEnd;
-            }
-            constantLoads = null;
-        }
-    }
-
-    /**
-     * Gets a garbage value for a given kind.
-     */
-    protected Constant zapValueForKind(PlatformKind kind) {
-        long dead = 0xDEADDEADDEADDEADL;
-        switch ((Kind) kind) {
-            case Boolean:
-                return Constant.FALSE;
-            case Byte:
-                return Constant.forByte((byte) dead);
-            case Char:
-                return Constant.forChar((char) dead);
-            case Short:
-                return Constant.forShort((short) dead);
-            case Int:
-                return Constant.forInt((int) dead);
-            case Double:
-                return Constant.forDouble(Double.longBitsToDouble(dead));
-            case Float:
-                return Constant.forFloat(Float.intBitsToFloat((int) dead));
-            case Long:
-                return Constant.forLong(dead);
-            case Object:
-                return Constant.NULL_OBJECT;
-            default:
-                throw new IllegalArgumentException(kind.toString());
-        }
-    }
-
-    /**
-     * Default implementation: Return the Java stack kind for each stamp.
-     */
-    public PlatformKind getPlatformKind(Stamp stamp) {
-        return stamp.getPlatformKind(this);
-    }
-
-    public PlatformKind getIntegerKind(int bits, boolean unsigned) {
-        if (bits <= 8) {
-            return Kind.Byte;
-        } else if (bits <= 16) {
-            return Kind.Short;
-        } else if (bits <= 32) {
-            return Kind.Int;
-        } else {
-            assert bits <= 64;
-            return Kind.Long;
-        }
-    }
-
-    public PlatformKind getFloatingKind(int bits) {
-        switch (bits) {
-            case 32:
-                return Kind.Float;
-            case 64:
-                return Kind.Double;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    public PlatformKind getObjectKind() {
-        return Kind.Object;
-    }
-
-    public abstract void emitBitCount(Variable result, Value operand);
-
-    public abstract void emitBitScanForward(Variable result, Value operand);
-
-    public abstract void emitBitScanReverse(Variable result, Value operand);
-
-    public abstract void emitByteSwap(Variable result, Value operand);
-
-    public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
-
-    public AbstractBlock<?> getCurrentBlock() {
-        return currentBlock;
-    }
-
-    void setCurrentBlock(AbstractBlock<?> block) {
-        currentBlock = block;
-    }
-
-    public LIRGenerationResult getResult() {
-        return res;
-    }
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,21 +31,24 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.LIRGenerator.LoadConstant;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.type.*;
 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.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
+import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.lir.gen.LIRGenerator.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 
 /**
  * This class traverses the HIR instructions and generates LIR instructions from them.
@@ -64,7 +67,6 @@
         this.gen = gen;
         this.nodeOperands = graph.createNodeMap();
         this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands);
-        gen.setDebugInfoBuilder(debugInfoBuilder);
     }
 
     @SuppressWarnings("hiding")
@@ -110,25 +112,25 @@
                     return setResult(node, value);
                 } else {
                     Variable loadedValue;
-                    if (gen.constantLoads == null) {
-                        gen.constantLoads = new HashMap<>();
+                    if (gen.getConstantLoads() == null) {
+                        gen.setConstantLoads(new HashMap<>());
                     }
-                    LoadConstant load = gen.constantLoads.get(value);
+                    LoadConstant load = gen.getConstantLoads().get(value);
                     assert gen.getCurrentBlock() instanceof Block;
                     if (load == null) {
                         int index = gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size();
                         loadedValue = gen.emitMove(value);
                         LIRInstruction op = gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).get(index);
-                        gen.constantLoads.put(value, new LoadConstant(loadedValue, (Block) gen.getCurrentBlock(), index, op));
+                        gen.getConstantLoads().put(value, new LoadConstant(loadedValue, gen.getCurrentBlock(), index, op));
                     } else {
-                        Block dominator = ControlFlowGraph.commonDominator(load.block, (Block) gen.getCurrentBlock());
-                        loadedValue = load.variable;
-                        if (dominator != load.block) {
+                        AbstractBlock<?> dominator = ControlFlowGraph.commonDominator((Block) load.getBlock(), (Block) gen.getCurrentBlock());
+                        loadedValue = load.getVariable();
+                        if (dominator != load.getBlock()) {
                             load.unpin(gen.getResult().getLIR());
                         } else {
-                            assert load.block != gen.getCurrentBlock() || load.index < gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size();
+                            assert load.getBlock() != gen.getCurrentBlock() || load.getIndex() < gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size();
                         }
-                        load.block = dominator;
+                        load.setBlock(dominator);
                     }
                     return loadedValue;
                 }
@@ -212,9 +214,9 @@
                             try {
                                 doRoot((ValueNode) instr);
                             } catch (GraalInternalError e) {
-                                throw e.addContext(instr);
+                                throw GraalGraphInternalError.transformAndAddContext(e, instr);
                             } catch (Throwable e) {
-                                throw new GraalInternalError(e).addContext(instr);
+                                throw new GraalGraphInternalError(e).addContext(instr);
                             }
                         }
                     }
@@ -412,7 +414,7 @@
         } else if (node instanceof LIRLowerable) {
             ((LIRLowerable) node).generate(this);
         } else if (node instanceof ArithmeticLIRLowerable) {
-            ((ArithmeticLIRLowerable) node).generate(this);
+            ((ArithmeticLIRLowerable) node).generate(this, gen);
         } else {
             throw GraalInternalError.shouldNotReachHere("node is not LIRLowerable: " + node);
         }
@@ -566,7 +568,7 @@
         if (x instanceof InvokeWithExceptionNode) {
             exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge());
         }
-        LIRFrameState callState = gen.stateWithExceptionEdge(x, exceptionEdge);
+        LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge);
 
         Value result = invokeCc.getReturn();
         if (callTarget instanceof DirectCallTargetNode) {
@@ -659,7 +661,46 @@
         return debugInfoBuilder;
     }
 
-    public void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability) {
+    private static FrameState getFrameState(DeoptimizingNode deopt) {
+        if (deopt instanceof DeoptimizingNode.DeoptBefore) {
+            assert !(deopt instanceof DeoptimizingNode.DeoptDuring || deopt instanceof DeoptimizingNode.DeoptAfter);
+            return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore();
+        } else if (deopt instanceof DeoptimizingNode.DeoptDuring) {
+            assert !(deopt instanceof DeoptimizingNode.DeoptAfter);
+            return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring();
+        } else {
+            assert deopt instanceof DeoptimizingNode.DeoptAfter;
+            return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter();
+        }
+    }
+
+    public LIRFrameState state(DeoptimizingNode deopt) {
+        if (!deopt.canDeoptimize()) {
+            return null;
+        }
+        return stateFor(getFrameState(deopt));
+    }
+
+    public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
+        if (!deopt.canDeoptimize()) {
+            return null;
+        }
+        return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge);
+    }
+
+    public LIRFrameState stateFor(FrameState state) {
+        return stateForWithExceptionEdge(state, null);
+    }
+
+    public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) {
+        if (gen.needOnlyOopMaps()) {
+            return new LIRFrameState(null, null, null);
+        }
+        assert state != null;
+        return getDebugInfoBuilder().build(state, exceptionEdge);
+    }
+
+    public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability) {
         gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability);
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,6 +29,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 
 /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.compiler.phases.HighTier.Options.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.compiler.phases;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.options.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.compiler.phases;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.spi.*;
@@ -51,9 +51,7 @@
         }
 
         if (OptFloatingReads.getValue()) {
-            IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer);
-            incCanonicalizer.appendPhase(new FloatingReadPhase());
-            appendPhase(incCanonicalizer);
+            appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase()));
             if (OptReadElimination.getValue()) {
                 appendPhase(new ReadEliminationPhase());
             }
@@ -84,7 +82,7 @@
 
         appendPhase(new LoopSafepointInsertionPhase());
 
-        appendPhase(new GuardLoweringPhase());
+        appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new GuardLoweringPhase()));
 
         appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER));
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,14 @@
 package com.oracle.graal.compiler.target;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.stack.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
@@ -96,12 +98,13 @@
 
     public abstract boolean shouldAllocateRegisters();
 
+    public abstract StackIntrospection getStackIntrospection();
+
     /**
      * Emits the code for a given graph.
      *
-     * @param installedCodeOwner the method the compiled code will be
-     *            {@linkplain InstalledCode#getMethod() associated} with once installed. This
-     *            argument can be null.
+     * @param installedCodeOwner the method the compiled code will be associated with once
+     *            installed. This argument can be null.
      */
     public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.compiler.target;
 
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.debug;
 
 import static com.oracle.graal.debug.Debug.Initialization.*;
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
 import static java.util.FormattableFlags.*;
 
 import java.io.*;
@@ -187,6 +188,19 @@
 
     /**
      * @see #scope(Object)
+     * @param contextObjects an array of object to be appended to the {@linkplain #context()
+     *            current} debug context
+     */
+    public static Scope scope(Object name, Object[] contextObjects) {
+        if (ENABLED) {
+            return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, contextObjects);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see #scope(Object)
      * @param context an object to be appended to the {@linkplain #context() current} debug context
      */
     public static Scope scope(Object name, Object context) {
@@ -259,17 +273,25 @@
     }
 
     public static Scope forceLog() {
-        return Debug.sandbox("forceLog", new DelegatingDebugConfig(DebugScope.getConfig()) {
-            @Override
-            public boolean isLogEnabled() {
-                return true;
-            }
+        return Debug.sandbox("forceLog", new DelegatingDebugConfig().enable(LOG).enable(LOG_METHOD));
+    }
 
-            @Override
-            public boolean isLogEnabledForMethod() {
-                return true;
-            }
-        });
+    /**
+     * Opens a scope in which exception {@linkplain DebugConfig#interceptException(Throwable)
+     * interception} is disabled. It is recommended to use the try-with-resource statement for
+     * managing entering and leaving such scopes:
+     *
+     * <pre>
+     * try (DebugConfigScope s = Debug.disableIntercept()) {
+     *     ...
+     * }
+     * </pre>
+     *
+     * This is particularly useful to suppress extraneous output in JUnit tests that are expected to
+     * throw an exception.
+     */
+    public static DebugConfigScope disableIntercept() {
+        return Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT));
     }
 
     /**
@@ -853,7 +875,7 @@
 
     public static Object convertFormatArg(Object arg) {
         if (arg instanceof Class) {
-            return ((Class) arg).getSimpleName();
+            return ((Class<?>) arg).getSimpleName();
         }
         return arg;
     }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,45 +25,139 @@
 import java.io.*;
 import java.util.*;
 
+import com.oracle.graal.debug.internal.*;
+
 public class DelegatingDebugConfig implements DebugConfig {
 
     protected final DebugConfig delegate;
 
+    /**
+     * The features of a {@link DelegatingDebugConfig} that can be force
+     * {@linkplain DelegatingDebugConfig#enable(Feature) enabled}/
+     * {@linkplain DelegatingDebugConfig#disable(Feature) disabled} or
+     * {@linkplain DelegatingDebugConfig#delegate(Feature) delegated}.
+     */
+    public enum Feature {
+        /**
+         * @see Debug#isLogEnabled()
+         */
+        LOG,
+        /**
+         * @see Debug#isLogEnabledForMethod()
+         */
+        LOG_METHOD,
+        /**
+         * @see Debug#isDumpEnabled()
+         */
+        DUMP,
+        /**
+         * @see Debug#isDumpEnabledForMethod()
+         */
+        DUMP_METHOD,
+        /**
+         * @see Debug#isMeterEnabled()
+         */
+        METER,
+        /**
+         * @see Debug#isTimeEnabled()
+         */
+        TIME,
+        /**
+         * @see DebugConfig#interceptException(Throwable)
+         */
+        INTERCEPT
+    }
+
+    private final Map<Feature, Boolean> featureState = new EnumMap<>(Feature.class);
+
+    /**
+     * Creates a config that delegates to the {@link DebugScope#getConfig() current config}.
+     */
+    public DelegatingDebugConfig() {
+        this(DebugScope.getConfig());
+    }
+
+    /**
+     * Creates a config that delegates to a given config.
+     */
     public DelegatingDebugConfig(DebugConfig delegate) {
         this.delegate = delegate;
     }
 
+    public DelegatingDebugConfig enable(Feature feature) {
+        featureState.put(feature, Boolean.TRUE);
+        return this;
+    }
+
+    public DelegatingDebugConfig disable(Feature feature) {
+        featureState.put(feature, Boolean.FALSE);
+        return this;
+    }
+
+    public DelegatingDebugConfig delegate(Feature feature) {
+        featureState.put(feature, null);
+        return this;
+    }
+
     @Override
     public boolean isLogEnabled() {
-        return delegate.isLogEnabled();
+        Boolean fs = featureState.get(Feature.LOG);
+        if (fs == null) {
+            return delegate.isLogEnabled();
+        }
+        return fs.booleanValue();
     }
 
     public boolean isLogEnabledForMethod() {
-        return delegate.isLogEnabledForMethod();
+        Boolean fs = featureState.get(Feature.LOG_METHOD);
+        if (fs == null) {
+            return delegate.isLogEnabledForMethod();
+        }
+        return fs.booleanValue();
     }
 
     @Override
     public boolean isMeterEnabled() {
-        return delegate.isMeterEnabled();
+        Boolean fs = featureState.get(Feature.METER);
+        if (fs == null) {
+            return delegate.isMeterEnabled();
+        }
+        return fs.booleanValue();
     }
 
     @Override
     public boolean isDumpEnabled() {
-        return delegate.isDumpEnabled();
+        Boolean fs = featureState.get(Feature.DUMP);
+        if (fs == null) {
+            return delegate.isDumpEnabled();
+        }
+        return fs.booleanValue();
     }
 
     public boolean isDumpEnabledForMethod() {
-        return delegate.isDumpEnabledForMethod();
+        Boolean fs = featureState.get(Feature.DUMP_METHOD);
+        if (fs == null) {
+            return delegate.isDumpEnabledForMethod();
+        }
+        return fs.booleanValue();
     }
 
     @Override
     public boolean isTimeEnabled() {
-        return delegate.isTimeEnabled();
+        Boolean fs = featureState.get(Feature.TIME);
+        if (fs == null) {
+            return delegate.isTimeEnabled();
+        }
+        return fs.booleanValue();
     }
 
     @Override
     public RuntimeException interceptException(Throwable e) {
-        return delegate.interceptException(e);
+        Boolean fs = featureState.get(Feature.INTERCEPT);
+        if (fs == null || fs) {
+            return delegate.interceptException(e);
+        }
+        return null;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,425 @@
+/*
+ * 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.graph.test;
+
+import static com.oracle.graal.graph.test.matchers.NodeIterableContains.*;
+import static com.oracle.graal.graph.test.matchers.NodeIterableIsEmpty.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+
+public class NodeUsagesTests {
+
+    private static class Def extends Node {
+
+    }
+
+    private static class Use extends Node {
+        private @Input Def in0;
+        private @Input Def in1;
+        private @Input Def in2;
+
+        public Use(Def in0, Def in1, Def in2) {
+            this.in0 = in0;
+            this.in1 = in1;
+            this.in2 = in2;
+        }
+    }
+
+    @Test
+    public void testReplaceAtUsages() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtUsages(def1);
+
+        assertThat(def0.usages(), isEmpty());
+
+        assertEquals(3, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use1));
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicateAll() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> true);
+
+        assertThat(def0.usages(), isEmpty());
+
+        assertEquals(3, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use1));
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicateNone() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> false);
+
+        assertThat(def1.usages(), isEmpty());
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate1() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u == use1);
+
+        assertEquals(1, def1.usages().count());
+        assertThat(def1.usages(), contains(use1));
+
+        assertThat(def1.usages(), isNotEmpty());
+
+        assertEquals(2, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate2() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u == use2);
+
+        assertEquals(1, def1.usages().count());
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+
+        assertEquals(2, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate0() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u == use0);
+
+        assertEquals(1, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+
+        assertThat(def1.usages(), isNotEmpty());
+
+        assertEquals(2, def0.usages().count());
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate02() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use1);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use1));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(2, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate023() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+        Use use3 = graph.add(new Use(null, null, def0));
+
+        assertEquals(4, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+        assertThat(def0.usages(), contains(use3));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use1);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use1));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(3, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use2));
+        assertThat(def1.usages(), contains(use3));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate013() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+        Use use3 = graph.add(new Use(null, null, def0));
+
+        assertEquals(4, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+        assertThat(def0.usages(), contains(use3));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use2);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(3, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use1));
+        assertThat(def1.usages(), contains(use3));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate2_3() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+        Use use3 = graph.add(new Use(null, null, def0));
+
+        assertEquals(4, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+        assertThat(def0.usages(), contains(use3));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u == use2);
+
+        assertEquals(1, def1.usages().count());
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use3));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate01() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use2);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(2, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use1));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate12() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use0);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(2, def1.usages().count());
+        assertThat(def1.usages(), contains(use1));
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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.graph.test.matchers;
+
+import org.hamcrest.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+
+public class NodeIterableContains<T extends Node> extends TypeSafeDiagnosingMatcher<NodeIterable<T>> {
+    private T node;
+
+    public NodeIterableContains(T node) {
+        this.node = node;
+    }
+
+    public void describeTo(Description description) {
+        description.appendText("is a NodeIterable containing").appendValue(node);
+    }
+
+    public static <T extends Node> NodeIterableContains<T> contains(T node) {
+        return new NodeIterableContains<>(node);
+    }
+
+    public static <T extends Node> NodeIterableContains<T> d(T node) {
+        return new NodeIterableContains<>(node);
+    }
+
+    @Override
+    protected boolean matchesSafely(NodeIterable<T> iterable, Description description) {
+        return iterable.contains(node);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.graph.test.matchers;
+
+import org.hamcrest.*;
+import org.hamcrest.core.*;
+
+import com.oracle.graal.graph.iterators.*;
+
+public class NodeIterableIsEmpty extends BaseMatcher<NodeIterable<?>> {
+
+    private static final NodeIterableIsEmpty INSTANCE = new NodeIterableIsEmpty();
+
+    public boolean matches(Object iterable) {
+        return iterable instanceof NodeIterable<?> && ((NodeIterable<?>) iterable).isEmpty();
+    }
+
+    public void describeTo(Description description) {
+        description.appendText("is an empty NodeIterable");
+    }
+
+    public static Matcher<NodeIterable<?>> isEmpty() {
+        return INSTANCE;
+    }
+
+    public static Matcher<NodeIterable<?>> isNotEmpty() {
+        return IsNot.not(INSTANCE);
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-public abstract class FieldIntrospection extends UnsafeAccess {
-
-    /**
-     * Interface used by {@link #rescanAllFieldOffsets(CalcOffset)} to determine the offset (in
-     * bytes) of a field.
-     */
-    public interface CalcOffset {
-
-        long getOffset(Field field);
-    }
-
-    public static class DefaultCalcOffset implements CalcOffset {
-
-        @Override
-        public long getOffset(Field field) {
-            return unsafe.objectFieldOffset(field);
-        }
-    }
-
-    protected static final ConcurrentHashMap<Class<?>, FieldIntrospection> allClasses = new ConcurrentHashMap<>();
-
-    protected final Class<?> clazz;
-    protected long[] dataOffsets;
-    protected Map<Long, String> fieldNames;
-    protected Map<Long, Class<?>> fieldTypes;
-
-    public FieldIntrospection(Class<?> clazz) {
-        this.clazz = clazz;
-    }
-
-    public static void rescanAllFieldOffsets(CalcOffset calc) {
-        for (FieldIntrospection nodeClass : allClasses.values()) {
-            nodeClass.rescanFieldOffsets(calc);
-        }
-    }
-
-    protected abstract void rescanFieldOffsets(CalcOffset calc);
-
-    public abstract static class BaseFieldScanner {
-
-        private final CalcOffset calc;
-
-        /** The offsets of fields that are not specially handled by subclasses. */
-        public final ArrayList<Long> dataOffsets = new ArrayList<>();
-
-        public final Map<Long, String> fieldNames = new HashMap<>();
-        public final Map<Long, Class<?>> fieldTypes = new HashMap<>();
-
-        protected BaseFieldScanner(CalcOffset calc) {
-            this.calc = calc;
-        }
-
-        protected void scan(Class<?> clazz) {
-            Class<?> currentClazz = clazz;
-            do {
-                for (Field field : currentClazz.getDeclaredFields()) {
-                    if (Modifier.isStatic(field.getModifiers())) {
-                        continue;
-                    }
-                    Class<?> type = field.getType();
-                    long offset = calc.getOffset(field);
-
-                    // scanField() may overwrite the name with a customized name.
-                    fieldNames.put(offset, field.getName());
-                    fieldTypes.put(offset, type);
-
-                    scanField(field, type, offset);
-                }
-                currentClazz = currentClazz.getSuperclass();
-            } while (currentClazz.getSuperclass() != Object.class);
-        }
-
-        protected abstract void scanField(Field field, Class<?> type, long offset);
-    }
-
-    protected static void copyInto(long[] dest, long[] src) {
-        assert dest.length == src.length;
-        for (int i = 0; i < dest.length; i++) {
-            dest[i] = src[i];
-        }
-    }
-
-    protected static <T> void copyInto(T[] dest, T[] src) {
-        assert dest.length == src.length;
-        for (int i = 0; i < dest.length; i++) {
-            dest[i] = src[i];
-        }
-    }
-
-    protected static <T> void copyInto(T[] dest, List<T> src) {
-        assert dest.length == src.size();
-        for (int i = 0; i < dest.length; i++) {
-            dest[i] = src.get(i);
-        }
-    }
-
-    protected static <T> T[] arrayUsingSortedOffsets(Map<Long, T> map, long[] sortedOffsets, T[] result) {
-        for (int i = 0; i < sortedOffsets.length; i++) {
-            result[i] = map.get(sortedOffsets[i]);
-        }
-        return result;
-    }
-
-    protected static long[] sortedLongCopy(ArrayList<Long> list1) {
-        Collections.sort(list1);
-        long[] result = new long[list1.size()];
-        for (int i = 0; i < list1.size(); i++) {
-            result[i] = list1.get(i);
-        }
-        return result;
-    }
-
-    protected static long[] sortedLongCopy(ArrayList<Long> list1, ArrayList<Long> list2) {
-        Collections.sort(list1);
-        Collections.sort(list2);
-        long[] result = new long[list1.size() + list2.size()];
-        for (int i = 0; i < list1.size(); i++) {
-            result[i] = list1.get(i);
-        }
-        for (int i = 0; i < list2.size(); i++) {
-            result[list1.size() + i] = list2.get(i);
-        }
-        return result;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalGraphInternalError.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2011, 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.graph;
+
+import com.oracle.graal.compiler.common.*;
+
+/**
+ * This error is the graph/node aware extension of GraalInternalError.
+ */
+public class GraalGraphInternalError extends GraalInternalError {
+
+    private static final long serialVersionUID = -989290015525497919L;
+    private Node node;
+    private Graph graph;
+
+    /**
+     * This constructor creates a {@link GraalGraphInternalError} with a message assembled via
+     * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to
+     * always generate the same output.
+     *
+     * @param msg the message that will be associated with the error, in String.format syntax
+     * @param args parameters to String.format - parameters that implement {@link Iterable} will be
+     *            expanded into a [x, x, ...] representation.
+     */
+    public GraalGraphInternalError(String msg, Object... args) {
+        super(msg, args);
+    }
+
+    /**
+     * This constructor creates a {@link GraalGraphInternalError} for a given causing Throwable
+     * instance.
+     *
+     * @param cause the original exception that contains additional information on this error
+     */
+    public GraalGraphInternalError(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * This constructor creates a {@link GraalGraphInternalError} from a given GraalInternalError
+     * instance.
+     *
+     * @param e the original GraalInternalError
+     */
+    protected GraalGraphInternalError(GraalInternalError e) {
+        super(e);
+        if (e instanceof GraalGraphInternalError) {
+            node = ((GraalGraphInternalError) e).node;
+            graph = ((GraalGraphInternalError) e).graph;
+        }
+    }
+
+    /**
+     * Adds a graph to the context of this VerificationError. The first graph added via this method
+     * will be returned by {@link #graph()}.
+     *
+     * @param newGraph the graph which is in a incorrect state, if the verification error was not
+     *            caused by a specific node
+     */
+    GraalGraphInternalError addContext(Graph newGraph) {
+        if (newGraph != this.graph) {
+            addContext("graph", newGraph);
+            if (this.graph == null) {
+                this.graph = newGraph;
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Adds a node to the context of this VerificationError. The first node added via this method
+     * will be returned by {@link #node()}.
+     *
+     * @param newNode the node which is in a incorrect state, if the verification error was caused
+     *            by a node
+     */
+    public GraalGraphInternalError addContext(Node newNode) {
+        if (newNode != this.node) {
+            addContext("node", newNode);
+            if (this.node == null) {
+                this.node = newNode;
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Transform a GraalInternalError into a GraalGraphInternalError and add a graph to the context.
+     *
+     * @param e the previous error
+     * @param newGraph the graph which is in a incorrect state, if the verification error was not
+     *            caused by a specific node
+     */
+    public static GraalGraphInternalError transformAndAddContext(GraalInternalError e, Graph newGraph) {
+        GraalGraphInternalError graphError;
+        if (e instanceof GraalGraphInternalError) {
+            graphError = (GraalGraphInternalError) e;
+        } else {
+            graphError = new GraalGraphInternalError(e);
+        }
+        return graphError.addContext(newGraph);
+    }
+
+    /**
+     * Transform a GraalInternalError into a GraalGraphInternalError and add a node to the context.
+     *
+     * @param e the previous error
+     * @param newNode the node which is in a incorrect state, if the verification error was caused
+     *            by a node
+     */
+    public static GraalGraphInternalError transformAndAddContext(GraalInternalError e, Node newNode) {
+        GraalGraphInternalError graphError;
+        if (e instanceof GraalGraphInternalError) {
+            graphError = (GraalGraphInternalError) e;
+        } else {
+            graphError = new GraalGraphInternalError(e);
+        }
+        return graphError.addContext(newNode);
+    }
+
+    public Node node() {
+        return node;
+    }
+
+    public Graph graph() {
+        return graph;
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph;
-
-import java.util.*;
-
-/**
- * This error represents a conditions that should never occur during normal operation.
- */
-public class GraalInternalError extends Error {
-
-    private static final long serialVersionUID = 8776065085829593278L;
-    private Node node;
-    private Graph graph;
-    private final ArrayList<String> context = new ArrayList<>();
-
-    public static RuntimeException unimplemented() {
-        throw new GraalInternalError("unimplemented");
-    }
-
-    public static RuntimeException unimplemented(String msg) {
-        throw new GraalInternalError("unimplemented: %s", msg);
-    }
-
-    public static RuntimeException shouldNotReachHere() {
-        throw new GraalInternalError("should not reach here");
-    }
-
-    public static RuntimeException shouldNotReachHere(String msg) {
-        throw new GraalInternalError("should not reach here: %s", msg);
-    }
-
-    /**
-     * Checks a given condition and throws a {@link GraalInternalError} if it is false. Guarantees
-     * are stronger than assertions in that they are always checked. Error messages for guarantee
-     * violations should clearly indicate the nature of the problem as well as a suggested solution
-     * if possible.
-     * 
-     * @param condition the condition to check
-     * @param msg the message that will be associated with the error, in
-     *            {@link String#format(String, Object...)} syntax
-     * @param args arguments to the format string
-     */
-    public static void guarantee(boolean condition, String msg, Object... args) {
-        if (!condition) {
-            throw new GraalInternalError("failed guarantee: " + msg, args);
-        }
-    }
-
-    /**
-     * This constructor creates a {@link GraalInternalError} with a message assembled via
-     * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to
-     * always generate the same output.
-     * 
-     * @param msg the message that will be associated with the error, in String.format syntax
-     * @param args parameters to String.format - parameters that implement {@link Iterable} will be
-     *            expanded into a [x, x, ...] representation.
-     */
-    public GraalInternalError(String msg, Object... args) {
-        super(format(msg, args));
-    }
-
-    /**
-     * This constructor creates a {@link GraalInternalError} for a given causing Throwable instance.
-     * 
-     * @param cause the original exception that contains additional information on this error
-     */
-    public GraalInternalError(Throwable cause) {
-        super(cause);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder str = new StringBuilder();
-        str.append(super.toString());
-        for (String s : context) {
-            str.append("\n\tat ").append(s);
-        }
-        return str.toString();
-    }
-
-    private static String format(String msg, Object... args) {
-        if (args != null) {
-            // expand Iterable parameters into a list representation
-            for (int i = 0; i < args.length; i++) {
-                if (args[i] instanceof Iterable<?>) {
-                    ArrayList<Object> list = new ArrayList<>();
-                    for (Object o : (Iterable<?>) args[i]) {
-                        list.add(o);
-                    }
-                    args[i] = list.toString();
-                }
-            }
-        }
-        return String.format(Locale.ENGLISH, msg, args);
-    }
-
-    public GraalInternalError addContext(String newContext) {
-        this.context.add(newContext);
-        return this;
-    }
-
-    public GraalInternalError addContext(String name, Object obj) {
-        return addContext(format("%s: %s", name, obj));
-    }
-
-    /**
-     * Adds a graph to the context of this VerificationError. The first graph added via this method
-     * will be returned by {@link #graph()}.
-     * 
-     * @param newGraph the graph which is in a incorrect state, if the verification error was not
-     *            caused by a specific node
-     */
-    public GraalInternalError addContext(Graph newGraph) {
-        if (newGraph != this.graph) {
-            addContext("graph", newGraph);
-            if (this.graph == null) {
-                this.graph = newGraph;
-            }
-        }
-        return this;
-    }
-
-    /**
-     * Adds a node to the context of this VerificationError. The first node added via this method
-     * will be returned by {@link #node()}.
-     * 
-     * @param newNode the node which is in a incorrect state, if the verification error was caused
-     *            by a node
-     */
-    public GraalInternalError addContext(Node newNode) {
-        if (newNode != this.node) {
-            addContext("node", newNode);
-            if (this.node == null) {
-                this.node = newNode;
-            }
-        }
-        return this;
-    }
-
-    public Node node() {
-        return node;
-    }
-
-    public Graph graph() {
-        return graph;
-    }
-}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.GraphEvent.NodeEvent;
 import com.oracle.graal.graph.Node.ValueNumberable;
@@ -525,7 +526,7 @@
      */
     public NodeIterable<Node> getNewNodes(Mark mark) {
         final int index = mark.getValue();
-        return new AbstractNodeIterable<Node>() {
+        return new NodeIterable<Node>() {
 
             @Override
             public Iterator<Node> iterator() {
@@ -540,7 +541,7 @@
      * @return an {@link Iterable} providing all the live nodes.
      */
     public NodeIterable<Node> getNodes() {
-        return new AbstractNodeIterable<Node>() {
+        return new NodeIterable<Node>() {
 
             @Override
             public Iterator<Node> iterator() {
@@ -714,7 +715,7 @@
      */
     public <T extends Node & IterableNodeType> NodeIterable<T> getNodes(final Class<T> type) {
         final NodeClass nodeClass = NodeClass.get(type);
-        return new AbstractNodeIterable<T>() {
+        return new NodeIterable<T>() {
 
             @Override
             public Iterator<T> iterator() {
@@ -839,7 +840,7 @@
                     throw new GraalInternalError(t);
                 }
             } catch (GraalInternalError e) {
-                throw e.addContext(node).addContext(this);
+                throw GraalGraphInternalError.transformAndAddContext(e, node).addContext(this);
             }
         }
         return true;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputType.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputType.java	Wed Apr 23 15:48:38 2014 +0200
@@ -53,6 +53,10 @@
      */
     Association,
     /**
+     * Inputs that connect tightly coupled nodes, e.g., an InvokeNode and its CallTargetNode.
+     */
+    Extension,
+    /**
      * Inputs of this type are temporarily exempt from type checking. This should only be used in
      * exceptional cases and should never survive to later stages of compilation.
      */
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Wed Apr 23 15:48:38 2014 +0200
@@ -111,7 +111,7 @@
          * method. If not specified, then the class in which the annotated method is declared is
          * used (and is assumed to be a {@link Node} subclass).
          */
-        Class value() default NodeIntrinsic.class;
+        Class<?> value() default NodeIntrinsic.class;
 
         /**
          * Determines if the stamp of the instantiated intrinsic node has its stamp set from the
@@ -189,7 +189,6 @@
         Node current;
 
         private void advance() {
-            assert index == -1 || current != null;
             current = null;
             index++;
             if (index == 0) {
@@ -228,10 +227,35 @@
         }
     }
 
-    class NodeUsageIterable extends AbstractNodeIterable<Node> {
+    class NodeUsageWithModCountIterator extends NodeUsageIterator {
+
+        private final int expectedModCount = usageModCount();
+
+        @Override
+        public boolean hasNext() {
+            if (expectedModCount != usageModCount()) {
+                throw new ConcurrentModificationException();
+            }
+            return super.hasNext();
+        }
+
+        @Override
+        public Node next() {
+            if (expectedModCount != usageModCount()) {
+                throw new ConcurrentModificationException();
+            }
+            return super.next();
+        }
+    }
+
+    class NodeUsageIterable implements NodeIterable<Node> {
 
         public NodeUsageIterator iterator() {
-            return new NodeUsageIterator();
+            if (MODIFICATION_COUNTS_ENABLED) {
+                return new NodeUsageWithModCountIterator();
+            } else {
+                return new NodeUsageIterator();
+            }
         }
 
         @Override
@@ -246,13 +270,7 @@
 
         @Override
         public int count() {
-            if (usage0 == null) {
-                return 0;
-            }
-            if (usage1 == null) {
-                return 1;
-            }
-            return 2 + indexOfLastNonNull(extraUsages) + 1;
+            return usageCount();
         }
     }
 
@@ -349,6 +367,81 @@
         }
     }
 
+    private int usageCount() {
+        if (usage0 == null) {
+            return 0;
+        }
+        if (usage1 == null) {
+            return 1;
+        }
+        return 2 + indexOfLastNonNull(extraUsages) + 1;
+    }
+
+    /**
+     * Remove all usages between {@code fromIndex} and {@code toIndex} (exclusive), also, if
+     * {@code toIndex} is a valid usage, it is moved to {@code fromIndex}.
+     *
+     * <p>
+     * Visually,
+     *
+     * <pre>
+     * {@code
+     * [1, 2, 3, 4, 5, 6, 7].removeUsagesAndShiftFirst(1, 2) == [1, 4, 6, 7, 5, null, null]}
+     * </pre>
+     *
+     *
+     * @param fromIndex the index of the first element to be removed
+     * @param toIndex the index after the last element to be removed
+     */
+    private void removeUsagesAndShiftFirst(int fromIndex, int toIndex) {
+        assert fromIndex < toIndex;
+        int firstNullIndex = usageCount();
+        assert toIndex <= firstNullIndex;
+        int i = fromIndex;
+        int limit = toIndex;
+        if (toIndex < firstNullIndex) {
+            // move usage at toIndex to fromIndex(!)
+            movUsageTo(toIndex, fromIndex);
+            limit++;
+            i++;
+        }
+        while (i < limit && firstNullIndex > limit) {
+            movUsageTo(firstNullIndex - 1, i);
+            firstNullIndex--;
+            i++;
+        }
+        while (i < limit) {
+            if (i == 0) {
+                usage0 = null;
+            } else if (i == 1) {
+                usage1 = null;
+            } else {
+                extraUsages[i - INLINE_USAGE_COUNT] = null;
+            }
+            i++;
+        }
+
+    }
+
+    private void movUsageTo(int usageIndex, int toIndex) {
+        assert usageIndex > toIndex;
+        if (toIndex == 0) {
+            if (usageIndex == 1) {
+                usage0 = usage1;
+                usage1 = null;
+            } else {
+                usage0 = extraUsages[usageIndex - INLINE_USAGE_COUNT];
+                extraUsages[usageIndex - INLINE_USAGE_COUNT] = null;
+            }
+        } else if (toIndex == 1) {
+            usage1 = extraUsages[usageIndex - INLINE_USAGE_COUNT];
+            extraUsages[usageIndex - INLINE_USAGE_COUNT] = null;
+        } else {
+            extraUsages[toIndex - INLINE_USAGE_COUNT] = extraUsages[usageIndex - INLINE_USAGE_COUNT];
+            extraUsages[usageIndex - INLINE_USAGE_COUNT] = null;
+        }
+    }
+
     /**
      * Removes a given node from this node's {@linkplain #usages() usages}.
      *
@@ -357,6 +450,7 @@
      */
     private boolean removeUsage(Node node) {
         assert recordsUsages();
+        assert node != null;
         // It is critical that this method maintains the invariant that
         // the usage list has no null element preceding a non-null element
         incUsageModCount();
@@ -388,20 +482,19 @@
             }
             return true;
         }
-        int lastNonNull = indexOfLastNonNull(extraUsages);
-        if (lastNonNull >= 0) {
-            for (int i = 0; i <= lastNonNull; ++i) {
-                Node n = extraUsages[i];
-                if (n == node) {
-                    if (i < lastNonNull) {
-                        extraUsages[i] = extraUsages[lastNonNull];
-                        extraUsages[lastNonNull] = null;
-                    } else {
-                        extraUsages[i] = null;
-                    }
-                    return true;
-                }
+        int matchIndex = -1;
+        int i = 0;
+        Node n;
+        while (i < extraUsages.length && (n = extraUsages[i]) != null) {
+            if (n == node) {
+                matchIndex = i;
             }
+            i++;
+        }
+        if (matchIndex >= 0) {
+            extraUsages[matchIndex] = extraUsages[i - 1];
+            extraUsages[i - 1] = null;
+            return true;
         }
         return false;
     }
@@ -543,6 +636,40 @@
         clearUsages();
     }
 
+    public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) {
+        assert checkReplaceWith(other);
+        NodeUsageIterator it = (NodeUsageIterator) usages().iterator();
+        int removeStart = -1;
+        while (it.hasNext()) {
+            Node usage = it.next();
+            if (usagePredicate.apply(usage)) {
+                if (removeStart < 0) {
+                    removeStart = it.index - 1;
+                }
+                boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
+                assert assertTrue(result, "not found in inputs, usage: %s", usage);
+                if (other != null) {
+                    maybeNotifyChanged(usage);
+                    if (other.recordsUsages()) {
+                        other.addUsage(usage);
+                    }
+                }
+            } else {
+                if (removeStart >= 0) {
+                    int removeEndIndex = it.index - 1;
+                    removeUsagesAndShiftFirst(removeStart, removeEndIndex);
+                    it.index = removeStart;
+                    it.advance();
+                    removeStart = -1;
+                }
+            }
+        }
+        if (removeStart >= 0) {
+            int removeEndIndex = it.index;
+            removeUsagesAndShiftFirst(removeStart, removeEndIndex);
+        }
+    }
+
     public void replaceAtUsages(InputType type, Node other) {
         assert checkReplaceWith(other);
         for (Node usage : usages().snapshot()) {
@@ -707,7 +834,7 @@
         try {
             newNode = (Node) this.clone();
         } catch (CloneNotSupportedException e) {
-            throw new GraalInternalError(e).addContext(this);
+            throw new GraalGraphInternalError(e).addContext(this);
         }
         if (clearInputsAndSuccessors) {
             nodeClass.clearInputs(newNode);
@@ -907,7 +1034,8 @@
         if ((flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE) {
             formatter.format("%s", toString(Verbosity.Id));
         } else if ((flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE) {
-            formatter.format("%s", toString(Verbosity.Long));
+            // Use All here since Long is only slightly longer than Short.
+            formatter.format("%s", toString(Verbosity.All));
         } else {
             formatter.format("%s", toString(Verbosity.Short));
         }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.graph.iterators.*;
 
-public final class NodeBitMap extends AbstractNodeIterable<Node> {
+public final class NodeBitMap implements NodeIterable<Node> {
 
     private final boolean autoGrow;
     private final BitSet bitMap;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,8 +26,8 @@
 
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.concurrent.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.Node.Input;
@@ -36,7 +36,7 @@
 import com.oracle.graal.graph.spi.*;
 
 /**
- * Lazily associated metadata for every {@link Node} type. The metadata includes:
+ * Metadata for every {@link Node} type. The metadata includes:
  * <ul>
  * <li>The offsets of fields annotated with {@link Input} and {@link Successor} as well as methods
  * for iterating over such fields.</li>
@@ -45,72 +45,7 @@
  */
 public final class NodeClass extends FieldIntrospection {
 
-    /**
-     * Maps {@link Class} values (for {@link Node} types) to {@link NodeClass} values.
-     *
-     * Only a single Registry instance can be created. If a runtime creates a specialized registry,
-     * it must do so before the class initializer of {@link NodeClass} is executed.
-     */
-    public static class Registry {
-
-        private static Registry instance;
-
-        /**
-         * Gets the singleton {@link Registry} instance, creating it first if necessary.
-         */
-        static synchronized Registry instance() {
-            if (instance == null) {
-                return new Registry();
-            }
-            return instance;
-        }
-
-        protected Registry() {
-            assert instance == null : "exactly one registry can be created";
-            instance = this;
-        }
-
-        /**
-         * @return the {@link NodeClass} value for {@code key} or {@code null} if no such mapping
-         *         exists
-         */
-        protected NodeClass get(Class<? extends Node> key) {
-            return (NodeClass) allClasses.get(key);
-        }
-
-        /**
-         * Same as {@link #get(Class)} except that a {@link NodeClass} is created if no such mapping
-         * exists. The creation of a {@link NodeClass} must be serialized as
-         * {@link NodeClass#NodeClass(Class)} accesses both {@link FieldIntrospection#allClasses}
-         * and {@link NodeClass#nextIterableId}.
-         * <p>
-         * The fact that {@link ConcurrentHashMap#put} {@link ConcurrentHashMap#get} are used should
-         * make the double-checked locking idiom work in the way {@link NodeClass#get(Class)} uses
-         * this method and {@link #get(Class)}.
-         */
-        final synchronized NodeClass make(Class<? extends Node> key) {
-            NodeClass value = (NodeClass) allClasses.get(key);
-            if (value == null) {
-                value = new NodeClass(key);
-                Object old = allClasses.putIfAbsent(key, value);
-                assert old == null;
-                registered(key, value);
-            }
-            return value;
-        }
-
-        /**
-         * Hook for a subclass to be notified of a new mapping added to the registry.
-         *
-         * @param key
-         * @param value
-         */
-        protected void registered(Class<? extends Node> key, NodeClass value) {
-
-        }
-    }
-
-    private static final Registry registry = Registry.instance();
+    private static final Object GetNodeClassLock = new Object();
 
     /**
      * Gets the {@link NodeClass} associated with a given {@link Class}.
@@ -118,11 +53,22 @@
     @SuppressWarnings("unchecked")
     public static NodeClass get(Class<?> c) {
         Class<? extends Node> key = (Class<? extends Node>) c;
-        NodeClass value = registry.get(key);
-        if (value != null) {
-            return value;
+        NodeClass value = (NodeClass) allClasses.get(key);
+        // The fact that {@link ConcurrentHashMap#put} and {@link ConcurrentHashMap#get}
+        // are used makes the double-checked locking idiom work.
+        if (value == null) {
+            // The creation of a NodeClass must be serialized as the NodeClass constructor accesses
+            // both FieldIntrospection.allClasses and NodeClass.nextIterableId.
+            synchronized (GetNodeClassLock) {
+                value = (NodeClass) allClasses.get(key);
+                if (value == null) {
+                    value = new NodeClass(key);
+                    Object old = allClasses.putIfAbsent(key, value);
+                    assert old == null : old + "   " + key;
+                }
+            }
         }
-        return registry.make(key);
+        return value;
     }
 
     public static final int NOT_ITERABLE = -1;
@@ -137,10 +83,8 @@
     private final int directInputCount;
     private final long[] inputOffsets;
     private final InputType[] inputTypes;
-    private final String[] inputNames;
     private final int directSuccessorCount;
     private final long[] successorOffsets;
-    private final String[] successorNames;
     private final Class<?>[] dataTypes;
     private final boolean canGVN;
     private final boolean isLeafNode;
@@ -180,20 +124,12 @@
         directInputCount = scanner.inputOffsets.size();
         inputOffsets = sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets);
         inputTypes = new InputType[inputOffsets.length];
-        inputNames = new String[inputOffsets.length];
         for (int i = 0; i < inputOffsets.length; i++) {
             inputTypes[i] = scanner.types.get(inputOffsets[i]);
-            inputNames[i] = scanner.names.get(inputOffsets[i]);
             assert inputTypes[i] != null;
-            assert inputNames[i] != null;
         }
         directSuccessorCount = scanner.successorOffsets.size();
         successorOffsets = sortedLongCopy(scanner.successorOffsets, scanner.successorListOffsets);
-        successorNames = new String[successorOffsets.length];
-        for (int i = 0; i < successorOffsets.length; i++) {
-            successorNames[i] = scanner.names.get(successorOffsets[i]);
-            assert successorNames[i] != null;
-        }
 
         dataOffsets = sortedLongCopy(scanner.dataOffsets);
         dataTypes = new Class[dataOffsets.length];
@@ -243,10 +179,10 @@
             this.iterableId = nextIterableId++;
             List<NodeClass> existingClasses = new LinkedList<>();
             for (FieldIntrospection nodeClass : allClasses.values()) {
-                if (clazz.isAssignableFrom(nodeClass.clazz)) {
+                if (clazz.isAssignableFrom(nodeClass.getClazz())) {
                     existingClasses.add((NodeClass) nodeClass);
                 }
-                if (nodeClass.clazz.isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) {
+                if (nodeClass.getClazz().isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.getClazz())) {
                     NodeClass superNodeClass = (NodeClass) nodeClass;
                     superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1);
                     superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId;
@@ -271,7 +207,7 @@
     @Override
     protected void rescanFieldOffsets(CalcOffset calc) {
         FieldScanner scanner = new FieldScanner(calc);
-        scanner.scan(clazz);
+        scanner.scan(getClazz());
         assert directInputCount == scanner.inputOffsets.size();
         copyInto(inputOffsets, sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets));
         assert directSuccessorCount == scanner.successorOffsets.size();
@@ -388,7 +324,7 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append("NodeClass ").append(clazz.getSimpleName()).append(" [");
+        str.append("NodeClass ").append(getClazz().getSimpleName()).append(" [");
         for (int i = 0; i < inputOffsets.length; i++) {
             str.append(i == 0 ? "" : ", ").append(inputOffsets[i]);
         }
@@ -412,9 +348,9 @@
      */
     public static final class Position {
 
-        public final boolean input;
-        public final int index;
-        public final int subIndex;
+        private final boolean input;
+        private final int index;
+        private final int subIndex;
 
         public Position(boolean input, int index, int subIndex) {
             this.input = input;
@@ -436,7 +372,7 @@
         }
 
         public String getInputName(Node node) {
-            return node.getNodeClass().getEdgeName(this);
+            return node.getNodeClass().getName(this);
         }
 
         public void set(Node node, Node value) {
@@ -480,6 +416,18 @@
             }
             return true;
         }
+
+        public int getSubIndex() {
+            return subIndex;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public boolean isInput() {
+            return input;
+        }
     }
 
     private static Node getNode(Node node, long offset) {
@@ -495,7 +443,7 @@
         unsafe.putObject(node, offset, value);
     }
 
-    private static void putNodeList(Node node, long offset, NodeList value) {
+    private static void putNodeList(Node node, long offset, NodeList<?> value) {
         unsafe.putObject(node, offset, value);
     }
 
@@ -871,7 +819,7 @@
     }
 
     public boolean valueEqual(Node a, Node b) {
-        if (!canGVN || a.getClass() != b.getClass()) {
+        if (a.getClass() != b.getClass()) {
             return a == b;
         }
         for (int i = 0; i < dataOffsets.length; ++i) {
@@ -949,43 +897,39 @@
         if (this == from) {
             return true;
         }
-        long[] offsets = pos.input ? inputOffsets : successorOffsets;
-        if (pos.index >= offsets.length) {
+        long[] offsets = pos.isInput() ? inputOffsets : successorOffsets;
+        if (pos.getIndex() >= offsets.length) {
             return false;
         }
-        long[] fromOffsets = pos.input ? from.inputOffsets : from.successorOffsets;
-        if (pos.index >= fromOffsets.length) {
+        long[] fromOffsets = pos.isInput() ? from.inputOffsets : from.successorOffsets;
+        if (pos.getIndex() >= fromOffsets.length) {
             return false;
         }
-        return offsets[pos.index] == fromOffsets[pos.index];
+        return offsets[pos.getIndex()] == fromOffsets[pos.getIndex()];
     }
 
     public Node get(Node node, Position pos) {
-        long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index];
-        if (pos.subIndex == NOT_ITERABLE) {
+        long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
+        if (pos.getSubIndex() == NOT_ITERABLE) {
             return getNode(node, offset);
         } else {
-            return getNodeList(node, offset).get(pos.subIndex);
+            return getNodeList(node, offset).get(pos.getSubIndex());
         }
     }
 
     public InputType getInputType(Position pos) {
-        assert pos.input;
-        return inputTypes[pos.index];
-    }
-
-    public String getEdgeName(Position pos) {
-        return pos.input ? inputNames[pos.index] : successorNames[pos.index];
+        assert pos.isInput();
+        return inputTypes[pos.getIndex()];
     }
 
     public NodeList<?> getNodeList(Node node, Position pos) {
-        long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index];
-        assert pos.subIndex == NODE_LIST;
+        long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
+        assert pos.getSubIndex() == NODE_LIST;
         return getNodeList(node, offset);
     }
 
     public String getName(Position pos) {
-        return fieldNames.get(pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]);
+        return fieldNames.get(pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]);
     }
 
     void updateInputSuccInPlace(Node node, InplaceUpdateClosure duplicationReplacement) {
@@ -1028,7 +972,7 @@
         int index = startIndex;
         while (index < inputOffsets.length) {
             NodeList<Node> list = getNodeList(node, inputOffsets[index]);
-            assert list != null : clazz;
+            assert list != null : getClazz();
             putNodeList(node, inputOffsets[index], updateInputListCopy(list, node, duplicationReplacement));
             index++;
         }
@@ -1038,7 +982,7 @@
         int index = startIndex;
         while (index < successorOffsets.length) {
             NodeList<Node> list = getNodeList(node, successorOffsets[index]);
-            assert list != null : clazz;
+            assert list != null : getClazz();
             putNodeList(node, successorOffsets[index], updateSuccListCopy(list, node, duplicationReplacement));
             index++;
         }
@@ -1071,22 +1015,22 @@
     }
 
     public void set(Node node, Position pos, Node x) {
-        long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index];
-        if (pos.subIndex == NOT_ITERABLE) {
+        long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
+        if (pos.getSubIndex() == NOT_ITERABLE) {
             Node old = getNode(node, offset);
-            assert x == null || fieldTypes.get((pos.input ? inputOffsets : successorOffsets)[pos.index]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")";
+            assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")";
             putNode(node, offset, x);
-            if (pos.input) {
+            if (pos.isInput()) {
                 node.updateUsages(old, x);
             } else {
                 node.updatePredecessor(old, x);
             }
         } else {
             NodeList<Node> list = getNodeList(node, offset);
-            if (pos.subIndex < list.size()) {
-                list.set(pos.subIndex, x);
+            if (pos.getSubIndex() < list.size()) {
+                list.set(pos.getSubIndex(), x);
             } else {
-                while (pos.subIndex < list.size() - 1) {
+                while (pos.getSubIndex() < list.size() - 1) {
                     list.add(null);
                 }
                 list.add(x);
@@ -1095,7 +1039,7 @@
     }
 
     public NodeClassIterable getInputIterable(final Node node) {
-        assert clazz.isInstance(node);
+        assert getClazz().isInstance(node);
         return new NodeClassIterable() {
 
             @Override
@@ -1115,7 +1059,7 @@
     }
 
     public NodeClassIterable getSuccessorIterable(final Node node) {
-        assert clazz.isInstance(node);
+        assert getClazz().isInstance(node);
         return new NodeClassIterable() {
 
             @Override
@@ -1148,7 +1092,7 @@
         }
         while (index < inputOffsets.length) {
             NodeList<Node> list = getNodeList(node, inputOffsets[index]);
-            assert list != null : clazz;
+            assert list != null : getClazz();
             if (list.replaceFirst(old, other)) {
                 return true;
             }
@@ -1171,7 +1115,7 @@
         }
         while (index < successorOffsets.length) {
             NodeList<Node> list = getNodeList(node, successorOffsets[index]);
-            assert list != null : clazz + " " + successorOffsets[index] + " " + node;
+            assert list != null : getClazz() + " " + successorOffsets[index] + " " + node;
             if (list.replaceFirst(old, other)) {
                 return true;
             }
@@ -1228,7 +1172,7 @@
      * @param newNode the node to which the inputs should be copied.
      */
     public void copyInputs(Node node, Node newNode) {
-        assert node.getClass() == clazz && newNode.getClass() == clazz;
+        assert node.getClass() == getClazz() && newNode.getClass() == getClazz();
 
         int index = 0;
         while (index < directInputCount) {
@@ -1250,7 +1194,7 @@
      * @param newNode the node to which the successors should be copied.
      */
     public void copySuccessors(Node node, Node newNode) {
-        assert node.getClass() == clazz && newNode.getClass() == clazz;
+        assert node.getClass() == getClazz() && newNode.getClass() == getClazz();
 
         int index = 0;
         while (index < directSuccessorCount) {
@@ -1269,7 +1213,7 @@
     }
 
     public boolean inputsEqual(Node node, Node other) {
-        assert node.getClass() == clazz && other.getClass() == clazz;
+        assert node.getClass() == getClazz() && other.getClass() == getClazz();
         int index = 0;
         while (index < directInputCount) {
             if (getNode(other, inputOffsets[index]) != getNode(node, inputOffsets[index])) {
@@ -1288,7 +1232,7 @@
     }
 
     public boolean successorsEqual(Node node, Node other) {
-        assert node.getClass() == clazz && other.getClass() == clazz;
+        assert node.getClass() == getClazz() && other.getClass() == getClazz();
         int index = 0;
         while (index < directSuccessorCount) {
             if (getNode(other, successorOffsets[index]) != getNode(node, successorOffsets[index])) {
@@ -1307,7 +1251,7 @@
     }
 
     public boolean inputContains(Node node, Node other) {
-        assert node.getClass() == clazz;
+        assert node.getClass() == getClazz();
 
         int index = 0;
         while (index < directInputCount) {
@@ -1327,7 +1271,7 @@
     }
 
     public boolean successorContains(Node node, Node other) {
-        assert node.getClass() == clazz;
+        assert node.getClass() == getClazz();
 
         int index = 0;
         while (index < directSuccessorCount) {
@@ -1409,7 +1353,7 @@
     }
 
     public Class<?> getJavaClass() {
-        return clazz;
+        return getClazz();
     }
 
     /**
@@ -1509,7 +1453,7 @@
                     replacement = replacements.replacement(input);
                 }
                 if (replacement != input) {
-                    assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.index]), replacement);
+                    assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.getIndex()]), replacement);
                     target = replacement;
                 } else if (input.graph() == graph) { // patch to the outer world
                     target = input;
@@ -1528,7 +1472,7 @@
             if (target == null) {
                 Node replacement = replacements.replacement(succ);
                 if (replacement != succ) {
-                    assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.index]), replacement);
+                    assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.getIndex()]), replacement);
                     target = replacement;
                 }
             }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,7 +30,7 @@
  * The iterator returned by this iterable can be used to access {@link Position Positions} during
  * iteration using {@link NodeClassIterator#nextPosition()}.
  */
-public abstract class NodeClassIterable extends AbstractNodeIterable<Node> {
+public interface NodeClassIterable extends NodeIterable<Node> {
 
     @Override
     public abstract NodeClassIterator iterator();
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Apr 23 15:48:38 2014 +0200
@@ -257,7 +257,7 @@
     }
 
     @Override
-    public void snapshotTo(Collection<T> to) {
+    public void snapshotTo(Collection<? super T> to) {
         for (int i = 0; i < size; i++) {
             to.add(get(i));
         }
@@ -348,42 +348,6 @@
     }
 
     @Override
-    public NodeIterable<T> until(final T u) {
-        return new FilteredNodeIterable<>(this).until(u);
-    }
-
-    @Override
-    public NodeIterable<T> until(final Class<? extends T> clazz) {
-        return new FilteredNodeIterable<>(this).until(clazz);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <F extends T> NodeIterable<F> filter(Class<F> clazz) {
-        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
-    }
-
-    @Override
-    public NodeIterable<T> filterInterface(Class<?> iface) {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
-    }
-
-    @Override
-    public FilteredNodeIterable<T> filter(NodePredicate predicate) {
-        return new FilteredNodeIterable<>(this).and(predicate);
-    }
-
-    @Override
-    public FilteredNodeIterable<T> nonNull() {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
-    }
-
-    @Override
-    public NodeIterable<T> distinct() {
-        return new FilteredNodeIterable<>(this).distinct();
-    }
-
-    @Override
     public T first() {
         if (size() > 0) {
             return get(0);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph;
-
-import java.lang.reflect.*;
-
-import sun.misc.*;
-
-public class UnsafeAccess {
-
-    /**
-     * An instance of {@link Unsafe} for use within Graal.
-     */
-    public static final Unsafe unsafe = getUnsafe();
-
-    private static Unsafe getUnsafe() {
-        try {
-            // this will fail if Graal is not part of the boot class path
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-            // nothing to do
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            // currently we rely on being able to use Unsafe...
-            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));
-    }
-
-    /**
-     * Reads a {@code '\0'} terminated C string from native memory and converts it to a
-     * {@link String}.
-     * 
-     * @return a Java string
-     */
-    public static String readCString(long address) {
-        if (address == 0) {
-            return null;
-        }
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0;; i++) {
-            char c = (char) unsafe.getByte(address + i);
-            if (c == 0) {
-                break;
-            }
-            sb.append(c);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * 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.graph/src/com/oracle/graal/graph/VerificationError.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
  * This error represents a failed verification of a node . It must only be used for conditions that
  * should never occur during normal operation.
  */
-public class VerificationError extends GraalInternalError {
+public class VerificationError extends GraalGraphInternalError {
 
     private static final long serialVersionUID = 8459607567446819822L;
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph.iterators;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-
-public abstract class AbstractNodeIterable<T extends Node> implements NodeIterable<T> {
-
-    @Override
-    public NodeIterable<T> until(final T u) {
-        return new FilteredNodeIterable<>(this).until(u);
-    }
-
-    @Override
-    public NodeIterable<T> until(final Class<? extends T> clazz) {
-        return new FilteredNodeIterable<>(this).until(clazz);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <F extends T> NodeIterable<F> filter(Class<F> clazz) {
-        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
-    }
-
-    @Override
-    public NodeIterable<T> filterInterface(Class<?> iface) {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
-    }
-
-    @Override
-    public FilteredNodeIterable<T> filter(NodePredicate predicate) {
-        return new FilteredNodeIterable<>(this).and(predicate);
-    }
-
-    @Override
-    public FilteredNodeIterable<T> nonNull() {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
-    }
-
-    @Override
-    public NodeIterable<T> distinct() {
-        return new FilteredNodeIterable<>(this).distinct();
-    }
-
-    @Override
-    public List<T> snapshot() {
-        ArrayList<T> list = new ArrayList<>();
-        for (T n : this) {
-            list.add(n);
-        }
-        return list;
-    }
-
-    @Override
-    public void snapshotTo(Collection<T> to) {
-        for (T n : this) {
-            to.add(n);
-        }
-    }
-
-    @Override
-    public T first() {
-        Iterator<T> iterator = iterator();
-        if (iterator.hasNext()) {
-            return iterator.next();
-        }
-        return null;
-    }
-
-    @Override
-    public int count() {
-        int count = 0;
-        Iterator<T> iterator = iterator();
-        while (iterator.hasNext()) {
-            iterator.next();
-            count++;
-        }
-        return count;
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return !iterator().hasNext();
-    }
-
-    @Override
-    public boolean isNotEmpty() {
-        return iterator().hasNext();
-    }
-
-    @Override
-    public boolean contains(T node) {
-        return this.filter(NodePredicates.equals(node)).isNotEmpty();
-    }
-}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctFilteredNodeIterable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctFilteredNodeIterable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -39,6 +39,6 @@
 
     @Override
     public Iterator<T> iterator() {
-        return new DistinctPredicatedProxyNodeIterator<>(until, nodeIterable.iterator(), predicate);
+        return new DistinctPredicatedProxyNodeIterator<>(nodeIterable.iterator(), predicate);
     }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,8 +30,8 @@
 
     private NodeBitMap visited;
 
-    public DistinctPredicatedProxyNodeIterator(NodePredicate until, Iterator<T> iterator, NodePredicate predicate) {
-        super(until, iterator, predicate);
+    public DistinctPredicatedProxyNodeIterator(Iterator<T> iterator, NodePredicate predicate) {
+        super(iterator, predicate);
     }
 
     @Override
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,11 +26,10 @@
 
 import com.oracle.graal.graph.*;
 
-public class FilteredNodeIterable<T extends Node> extends AbstractNodeIterable<T> {
+public class FilteredNodeIterable<T extends Node> implements NodeIterable<T> {
 
     protected final NodeIterable<T> nodeIterable;
     protected NodePredicate predicate = NodePredicates.alwaysTrue();
-    protected NodePredicate until = NodePredicates.isNull();
 
     public FilteredNodeIterable(NodeIterable<T> nodeIterable) {
         this.nodeIterable = nodeIterable;
@@ -47,18 +46,6 @@
     }
 
     @Override
-    public NodeIterable<T> until(final T u) {
-        until = until.or(NodePredicates.equals(u));
-        return this;
-    }
-
-    @Override
-    public NodeIterable<T> until(final Class<? extends T> clazz) {
-        until = until.or(NodePredicates.isA(clazz));
-        return this;
-    }
-
-    @Override
     public FilteredNodeIterable<T> nonNull() {
         this.predicate = this.predicate.and(NodePredicates.isNotNull());
         return this;
@@ -68,13 +55,12 @@
     public DistinctFilteredNodeIterable<T> distinct() {
         DistinctFilteredNodeIterable<T> distinct = new DistinctFilteredNodeIterable<>(nodeIterable);
         distinct.predicate = predicate;
-        distinct.until = until;
         return distinct;
     }
 
     @Override
     public Iterator<T> iterator() {
-        return new PredicatedProxyNodeIterator<>(until, nodeIterable.iterator(), predicate);
+        return new PredicatedProxyNodeIterator<>(nodeIterable.iterator(), predicate);
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,32 +28,66 @@
 
 public interface NodeIterable<T extends Node> extends Iterable<T> {
 
-    NodeIterable<T> until(T u);
+    @SuppressWarnings("unchecked")
+    default <F extends T> NodeIterable<F> filter(Class<F> clazz) {
+        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
+    }
 
-    NodeIterable<T> until(Class<? extends T> clazz);
+    default NodeIterable<T> filterInterface(Class<?> iface) {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
+    }
 
-    <F extends T> NodeIterable<F> filter(Class<F> clazz);
+    default FilteredNodeIterable<T> filter(NodePredicate predicate) {
+        return new FilteredNodeIterable<>(this).and(predicate);
+    }
 
-    NodeIterable<T> filterInterface(Class<?> iface);
-
-    FilteredNodeIterable<T> filter(NodePredicate predicate);
+    default FilteredNodeIterable<T> nonNull() {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
+    }
 
-    FilteredNodeIterable<T> nonNull();
+    default NodeIterable<T> distinct() {
+        return new FilteredNodeIterable<>(this).distinct();
+    }
 
-    NodeIterable<T> distinct();
+    default List<T> snapshot() {
+        ArrayList<T> list = new ArrayList<>();
+        snapshotTo(list);
+        return list;
+    }
 
-    List<T> snapshot();
-
-    void snapshotTo(Collection<T> to);
+    default void snapshotTo(Collection<? super T> to) {
+        for (T n : this) {
+            to.add(n);
+        }
+    }
 
-    T first();
-
-    int count();
+    default T first() {
+        Iterator<T> iterator = iterator();
+        if (iterator.hasNext()) {
+            return iterator.next();
+        }
+        return null;
+    }
 
-    boolean isEmpty();
-
-    boolean isNotEmpty();
+    default int count() {
+        int count = 0;
+        Iterator<T> iterator = iterator();
+        while (iterator.hasNext()) {
+            iterator.next();
+            count++;
+        }
+        return count;
+    }
 
-    boolean contains(T node);
+    default boolean isEmpty() {
+        return !iterator().hasNext();
+    }
 
+    default boolean isNotEmpty() {
+        return iterator().hasNext();
+    }
+
+    default boolean contains(T node) {
+        return this.filter(NodePredicates.equals(node)).isNotEmpty();
+    }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicate.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicate.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,20 +23,21 @@
 package com.oracle.graal.graph.iterators;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.NodePredicates.*;
 
-public abstract class NodePredicate {
+public interface NodePredicate {
 
-    public abstract boolean apply(Node n);
+    boolean apply(Node n);
 
-    public NodePredicate and(NodePredicate np) {
-        return NodePredicates.and(this, np);
+    default NodePredicate and(NodePredicate np) {
+        return new AndPredicate(this, np);
     }
 
-    public NodePredicate or(NodePredicate np) {
-        return NodePredicates.or(this, np);
+    default NodePredicate or(NodePredicate np) {
+        return new OrPredicate(this, np);
     }
 
-    public NodePredicate negate() {
-        return NodePredicates.not(this);
+    default NodePredicate negate() {
+        return new NotPredicate(this);
     }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicates.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicates.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 public abstract class NodePredicates {
 
     private static final TautologyPredicate TAUTOLOGY = new TautologyPredicate();
-    private static final FalsePredicate FALSE = new FalsePredicate();
+    private static final ContradictionPredicate CONTRADICTION = new ContradictionPredicate();
     private static final IsNullPredicate IS_NULL = new IsNullPredicate();
     private static final IsNotNullPredicate IS_NOT_NULL = new IsNotNullPredicate();
 
@@ -36,7 +36,7 @@
     }
 
     public static NodePredicate alwaysFalse() {
-        return FALSE;
+        return CONTRADICTION;
     }
 
     public static NodePredicate isNull() {
@@ -52,60 +52,7 @@
     }
 
     public static NodePredicate not(NodePredicate a) {
-        if (a == TAUTOLOGY) {
-            return FALSE;
-        }
-        if (a == FALSE) {
-            return TAUTOLOGY;
-        }
-        if (a == IS_NULL) {
-            return IS_NOT_NULL;
-        }
-        if (a == IS_NOT_NULL) {
-            return IS_NULL;
-        }
-        if (a instanceof NotPredicate) {
-            return ((NotPredicate) a).a;
-        }
-        if (a instanceof PositiveTypePredicate) {
-            return new NegativeTypePredicate((PositiveTypePredicate) a);
-        }
-        if (a instanceof NegativeTypePredicate) {
-            return new PositiveTypePredicate((NegativeTypePredicate) a);
-        }
-        if (a instanceof EqualsPredicate) {
-            return new NotEqualsPredicate(((EqualsPredicate) a).u);
-        }
-        if (a instanceof NotEqualsPredicate) {
-            return new EqualsPredicate(((NotEqualsPredicate) a).u);
-        }
-        return new NotPredicate(a);
-    }
-
-    public static NodePredicate and(NodePredicate a, NodePredicate b) {
-        if (a == TAUTOLOGY) {
-            return b;
-        }
-        if (b == TAUTOLOGY) {
-            return a;
-        }
-        if (a == FALSE || b == FALSE) {
-            return FALSE;
-        }
-        return new AndPredicate(a, b);
-    }
-
-    public static NodePredicate or(NodePredicate a, NodePredicate b) {
-        if (a == FALSE) {
-            return b;
-        }
-        if (b == FALSE) {
-            return a;
-        }
-        if (a == TAUTOLOGY || b == TAUTOLOGY) {
-            return TAUTOLOGY;
-        }
-        return new OrPredicate(a, b);
+        return a.negate();
     }
 
     public static NegativeTypePredicate isNotA(Class<? extends Node> clazz) {
@@ -126,28 +73,52 @@
         return new NegativeTypePredicate(iface);
     }
 
-    private static final class TautologyPredicate extends NodePredicate {
+    static final class TautologyPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
             return true;
         }
+
+        public NodePredicate and(NodePredicate np) {
+            return np;
+        }
+
+        public NodePredicate negate() {
+            return CONTRADICTION;
+        }
+
+        public NodePredicate or(NodePredicate np) {
+            return this;
+        }
     }
 
-    private static final class FalsePredicate extends NodePredicate {
+    static final class ContradictionPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
             return false;
         }
+
+        public NodePredicate and(NodePredicate np) {
+            return this;
+        }
+
+        public NodePredicate negate() {
+            return TAUTOLOGY;
+        }
+
+        public NodePredicate or(NodePredicate np) {
+            return np;
+        }
     }
 
-    private static final class AndPredicate extends NodePredicate {
+    static final class AndPredicate implements NodePredicate {
 
         private final NodePredicate a;
         private final NodePredicate b;
 
-        private AndPredicate(NodePredicate a, NodePredicate b) {
+        AndPredicate(NodePredicate a, NodePredicate b) {
             this.a = a;
             this.b = b;
         }
@@ -158,11 +129,11 @@
         }
     }
 
-    private static final class NotPredicate extends NodePredicate {
+    static final class NotPredicate implements NodePredicate {
 
         private final NodePredicate a;
 
-        private NotPredicate(NodePredicate n) {
+        NotPredicate(NodePredicate n) {
             this.a = n;
         }
 
@@ -170,14 +141,18 @@
         public boolean apply(Node n) {
             return !a.apply(n);
         }
+
+        public NodePredicate negate() {
+            return a;
+        }
     }
 
-    private static final class OrPredicate extends NodePredicate {
+    static final class OrPredicate implements NodePredicate {
 
         private final NodePredicate a;
         private final NodePredicate b;
 
-        private OrPredicate(NodePredicate a, NodePredicate b) {
+        OrPredicate(NodePredicate a, NodePredicate b) {
             this.a = a;
             this.b = b;
         }
@@ -188,27 +163,35 @@
         }
     }
 
-    private static final class IsNullPredicate extends NodePredicate {
+    static final class IsNullPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
             return n == null;
         }
+
+        public NodePredicate negate() {
+            return IS_NOT_NULL;
+        }
     }
 
-    private static final class IsNotNullPredicate extends NodePredicate {
+    static final class IsNotNullPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
             return n != null;
         }
+
+        public NodePredicate negate() {
+            return IS_NULL;
+        }
     }
 
-    private static final class EqualsPredicate extends NodePredicate {
+    static final class EqualsPredicate implements NodePredicate {
 
         private final Node u;
 
-        public EqualsPredicate(Node u) {
+        EqualsPredicate(Node u) {
             this.u = u;
         }
 
@@ -216,13 +199,17 @@
         public boolean apply(Node n) {
             return u == n;
         }
+
+        public NodePredicate negate() {
+            return new NotEqualsPredicate(u);
+        }
     }
 
-    private static final class NotEqualsPredicate extends NodePredicate {
+    static final class NotEqualsPredicate implements NodePredicate {
 
         private final Node u;
 
-        public NotEqualsPredicate(Node u) {
+        NotEqualsPredicate(Node u) {
             this.u = u;
         }
 
@@ -230,14 +217,18 @@
         public boolean apply(Node n) {
             return u != n;
         }
+
+        public NodePredicate negate() {
+            return new EqualsPredicate(u);
+        }
     }
 
-    public static final class PositiveTypePredicate extends NodePredicate {
+    public static final class PositiveTypePredicate implements NodePredicate {
 
         private final Class<?> type;
         private PositiveTypePredicate or;
 
-        public PositiveTypePredicate(Class<?> type) {
+        PositiveTypePredicate(Class<?> type) {
             this.type = type;
         }
 
@@ -261,14 +252,18 @@
             }
             return this;
         }
+
+        public NodePredicate negate() {
+            return new NegativeTypePredicate(this);
+        }
     }
 
-    public static final class NegativeTypePredicate extends NodePredicate {
+    public static final class NegativeTypePredicate implements NodePredicate {
 
         private final Class<?> type;
         private NegativeTypePredicate nor;
 
-        public NegativeTypePredicate(Class<?> type) {
+        NegativeTypePredicate(Class<?> type) {
             this.type = type;
         }
 
@@ -292,5 +287,9 @@
             }
             return this;
         }
+
+        public NodePredicate negate() {
+            return new PositiveTypePredicate(this);
+        }
     }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/PredicatedProxyNodeIterator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/PredicatedProxyNodeIterator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,10 +30,8 @@
 
     private final Iterator<T> iterator;
     private final NodePredicate predicate;
-    private final NodePredicate until;
 
-    public PredicatedProxyNodeIterator(NodePredicate until, Iterator<T> iterator, NodePredicate predicate) {
-        this.until = until;
+    public PredicatedProxyNodeIterator(Iterator<T> iterator, NodePredicate predicate) {
         this.iterator = iterator;
         this.predicate = predicate;
     }
@@ -43,7 +41,7 @@
         while ((current == null || !current.isAlive() || !predicate.apply(current)) && iterator.hasNext()) {
             current = iterator.next();
         }
-        if (current != null && (!current.isAlive() || !predicate.apply(current) || until.apply(current))) {
+        if (current != null && (!current.isAlive() || !predicate.apply(current))) {
             current = null;
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizationStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * 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 static com.oracle.graal.amd64.AMD64.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.*;
+
+final class AMD64DeoptimizationStub extends DeoptimizationStub {
+
+    private RegisterConfig registerConfig;
+
+    public AMD64DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
+        super(providers, target, linkage);
+        registerConfig = new AMD64HotSpotRegisterConfig(target.arch, HotSpotGraalRuntime.runtime().getConfig(), new Register[]{rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14});
+    }
+
+    @Override
+    public RegisterConfig getRegisterConfig() {
+        return registerConfig;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -41,6 +41,6 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-        AMD64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP), null, false, info);
+        AMD64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, false, info);
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,9 +25,7 @@
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-import static java.lang.reflect.Modifier.*;
-
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import java.util.*;
 
 import sun.misc.*;
@@ -48,6 +46,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -225,7 +224,7 @@
         Assembler masm = createAssembler(frameMap);
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame);
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
-        crb.setFrameSize(frameMap.frameSize());
+        crb.setTotalFrameSize(frameMap.totalFrameSize());
         StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
         if (deoptimizationRescueSlot != null && stub == null) {
             crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
@@ -264,7 +263,7 @@
      */
     public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedEntry) {
         HotSpotProviders providers = getProviders();
-        if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) {
+        if (installedCodeOwner != null && !installedCodeOwner.isStatic()) {
             MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY);
             CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false);
             Register inlineCacheKlass = rax; // see definition of IC_Klass in
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -108,10 +109,11 @@
         // to be valid for the entire run of the VM.
         Assumptions assumptions = new Assumptions(false);
         Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null);
-        Replacements replacements = createReplacements(runtime, assumptions, p);
+        HotSpotSnippetReflectionProvider snippetReflection = createSnippetReflection();
+        Replacements replacements = createReplacements(runtime, assumptions, p, snippetReflection);
         HotSpotDisassemblerProvider disassembler = createDisassembler(runtime);
         HotSpotSuitesProvider suites = createSuites(runtime);
-        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
+        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection);
 
         return createBackend(runtime, providers);
     }
@@ -128,8 +130,8 @@
         return new HotSpotDisassemblerProvider(runtime);
     }
 
-    protected Replacements createReplacements(HotSpotGraalRuntime runtime, Assumptions assumptions, Providers p) {
-        return new HotSpotReplacementsImpl(p, runtime.getConfig(), assumptions, p.getCodeCache().getTarget());
+    protected Replacements createReplacements(HotSpotGraalRuntime runtime, Assumptions assumptions, Providers p, SnippetReflectionProvider snippetReflection) {
+        return new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), assumptions, p.getCodeCache().getTarget());
     }
 
     protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache,
@@ -153,6 +155,10 @@
         return new HotSpotSuitesProvider(runtime);
     }
 
+    protected HotSpotSnippetReflectionProvider createSnippetReflection() {
+        return new HotSpotSnippetReflectionProvider();
+    }
+
     protected AMD64HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) {
         return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers);
     }
@@ -183,15 +189,15 @@
         } else {
             /*
              * System V Application Binary Interface, AMD64 Architecture Processor Supplement
-             * 
+             *
              * Draft Version 0.96
-             * 
+             *
              * http://www.uclibc.org/docs/psABI-x86_64.pdf
-             * 
+             *
              * 3.2.1
-             * 
+             *
              * ...
-             * 
+             *
              * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12
              * through %r15 "belong" to the calling function and the called function is required to
              * preserve their values. In other words, a called function must preserve these
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,13 +24,12 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.SaveRbp;
 import com.oracle.graal.lir.StandardOp.NoOp;
+import com.oracle.graal.lir.gen.*;
 
 public class AMD64HotSpotBytecodeLIRBuilder extends BytecodeLIRBuilder {
 
@@ -72,7 +71,7 @@
         gen.append(getSaveRbp().placeholder);
 
         Signature sig = method.getSignature();
-        boolean isStatic = Modifier.isStatic(method.getModifiers());
+        boolean isStatic = method.isStatic();
         for (int i = 0; i < sig.getParameterCount(!isStatic); i++) {
             Value paramValue = params[i];
             assert paramValue.getKind() == sig.getParameterKind(i).getStackKind();
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -33,11 +34,11 @@
  * Removes the current frame and tail calls the uncommon trap routine.
  */
 @Opcode("DEOPT_CALLER")
-final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp {
+final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp implements BlockEndOp {
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
         leaveFrameAndRestoreRbp(crb, masm);
-        AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP));
+        AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER));
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Emits code that enters a stack frame which is tailored to call the C++ method
+ * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}.
+ */
+@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME")
+final class AMD64HotSpotEnterUnpackFramesStackFrameOp extends AMD64LIRInstruction {
+
+    private final Register thread;
+    private final int threadLastJavaSpOffset;
+    private final int threadLastJavaPcOffset;
+    private final int threadLastJavaFpOffset;
+    @Alive(REG) AllocatableValue framePc;
+    @Alive(REG) AllocatableValue senderSp;
+    @Alive(REG) AllocatableValue senderFp;
+
+    AMD64HotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc, AllocatableValue senderSp,
+                    AllocatableValue senderFp) {
+        this.thread = thread;
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.threadLastJavaPcOffset = threadLastJavaPcOffset;
+        this.threadLastJavaFpOffset = threadLastJavaFpOffset;
+        this.framePc = framePc;
+        this.senderSp = senderSp;
+        this.senderFp = senderFp;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        final int totalFrameSize = crb.frameMap.totalFrameSize();
+        masm.push(asRegister(framePc));
+        masm.push(asRegister(senderFp));
+        masm.movq(rbp, rsp);
+
+        /*
+         * Allocate a full sized frame. Since return address and base pointer are already in place
+         * (see above) we allocate two words less.
+         */
+        masm.decrementq(rsp, totalFrameSize - 2 * crb.target.wordSize);
+
+        // Set up last Java values.
+        masm.movq(new AMD64Address(thread, threadLastJavaSpOffset), rsp);
+
+        /*
+         * Save the PC since it cannot easily be retrieved using the last Java SP after we aligned
+         * SP. Don't need the precise return PC here, just precise enough to point into this code
+         * blob.
+         */
+        masm.leaq(rax, new AMD64Address(rip, 0));
+        masm.movq(new AMD64Address(thread, threadLastJavaPcOffset), rax);
+
+        // Use BP because the frames look interpreted now.
+        masm.movq(new AMD64Address(thread, threadLastJavaFpOffset), rbp);
+
+        // Align the stack for the following unpackFrames call.
+        masm.andq(rsp, -(crb.target.stackAlignment));
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
@@ -37,7 +36,7 @@
 /**
  * Superclass for operations that use the value of RBP saved in a method's prologue.
  */
-abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction implements BlockEndOp {
+abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction {
 
     /**
      * The type of location (i.e., stack or register) in which RBP is saved is not known until
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -36,7 +36,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -51,7 +51,8 @@
 
     @Override
     public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
-        Kind word = providers.getCodeCache().getTarget().wordKind;
+        TargetDescription target = providers.getCodeCache().getTarget();
+        Kind word = target.wordKind;
 
         // The calling convention for the exception handler stub is (only?) defined in
         // TemplateInterpreterGenerator::generate_throw_exception()
@@ -62,6 +63,8 @@
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, null, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, ANY_LOCATION));
 
+        link(new AMD64DeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
+
         // When the java.ext.dirs property is modified then the crypto classes might not be found.
         // If that's the case we ignore the ClassNotFoundException and continue since we cannot
         // replace a non-existing method anyway.
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -31,6 +31,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
@@ -38,7 +39,7 @@
  * and jumps to the handler.
  */
 @Opcode("JUMP_TO_EXCEPTION_HANDLER_IN_CALLER")
-final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpilogueOp {
+final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpilogueOp implements BlockEndOp {
 
     @Use(REG) AllocatableValue handlerInCallerPc;
     @Use(REG) AllocatableValue exception;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,10 +25,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.gen.*;
 
 public class AMD64HotSpotLIRGenerationResult extends LIRGenerationResultBase {
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*;
 
 import java.util.*;
 
@@ -32,27 +33,26 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.amd64.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
-import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.LoadCompressedPointer;
-import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedConstantOp;
-import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedPointer;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.NoOp;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.lir.gen.*;
 
 /**
  * LIR generator specialized for AMD64 HotSpot.
@@ -60,6 +60,7 @@
 public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator {
 
     final HotSpotVMConfig config;
+    private HotSpotLockStack lockStack;
 
     protected AMD64HotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
         super(providers, cc, lirGenRes);
@@ -126,7 +127,17 @@
 
     @Override
     public StackSlot getLockSlot(int lockDepth) {
-        return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth);
+        return getLockStack().makeLockSlot(lockDepth);
+    }
+
+    private HotSpotLockStack getLockStack() {
+        assert lockStack != null;
+        return lockStack;
+    }
+
+    protected void setLockStack(HotSpotLockStack lockStack) {
+        assert this.lockStack == null;
+        this.lockStack = lockStack;
     }
 
     private Register findPollOnReturnScratchRegister() {
@@ -155,7 +166,7 @@
     }
 
     @Override
-    protected boolean needOnlyOopMaps() {
+    public boolean needOnlyOopMaps() {
         // Stubs only need oop maps
         return ((AMD64HotSpotLIRGenerationResult) getResult()).getStub() != null;
     }
@@ -173,12 +184,65 @@
         super.emitForeignCall(linkage, result, arguments, temps, info);
     }
 
-    protected AMD64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations) {
-        AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations, true);
+    public void emitLeaveCurrentStackFrame() {
+        append(new AMD64HotSpotLeaveCurrentStackFrameOp());
+    }
+
+    public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
+        Variable frameSizeVariable = load(frameSize);
+        Variable initialInfoVariable = load(initialInfo);
+        append(new AMD64HotSpotLeaveDeoptimizedStackFrameOp(frameSizeVariable, initialInfoVariable));
+    }
+
+    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        Variable framePcVariable = load(framePc);
+        Variable senderSpVariable = load(senderSp);
+        Variable senderFpVariable = load(senderFp);
+        append(new AMD64HotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), framePcVariable,
+                        senderSpVariable, senderFpVariable));
+    }
+
+    public void emitLeaveUnpackFramesStackFrame() {
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset()));
+    }
+
+    /**
+     * @param savedRegisters the registers saved by this operation which may be subject to pruning
+     * @param savedRegisterLocations the slots to which the registers are saved
+     * @param supportsRemove determines if registers can be pruned
+     */
+    protected AMD64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations, boolean supportsRemove) {
+        AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove);
         append(save);
         return save;
     }
 
+    /**
+     * Adds a node to the graph that saves all allocatable registers to the stack.
+     *
+     * @param supportsRemove determines if registers can be pruned
+     * @return the register save node
+     */
+    private AMD64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) {
+        StackSlot[] savedRegisterLocations = new StackSlot[savedRegisters.length];
+        for (int i = 0; i < savedRegisters.length; i++) {
+            PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory());
+            assert kind != Kind.Illegal;
+            StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind);
+            savedRegisterLocations[i] = spillSlot;
+        }
+        return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove);
+    }
+
+    @Override
+    public SaveRegistersOp emitSaveAllRegisters() {
+        // We are saving all registers.
+        // TODO Save upper half of YMM registers.
+        return emitSaveAllRegisters(cpuxmmRegisters, false);
+    }
+
     protected void emitRestoreRegisters(AMD64SaveRegistersOp save) {
         append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save));
     }
@@ -188,32 +252,25 @@
     }
 
     @Override
-    public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
+    public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) {
         HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
         boolean destroysRegisters = hotspotLinkage.destroysRegisters();
 
         AMD64SaveRegistersOp save = null;
-        StackSlot[] savedRegisterLocations = null;
         if (destroysRegisters) {
             if (getStub() != null) {
                 if (getStub().preservesRegisters()) {
                     Register[] savedRegisters = getResult().getFrameMap().registerConfig.getAllocatableRegisters();
-                    savedRegisterLocations = new StackSlot[savedRegisters.length];
-                    for (int i = 0; i < savedRegisters.length; i++) {
-                        PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory());
-                        assert kind != Kind.Illegal;
-                        StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind);
-                        savedRegisterLocations[i] = spillSlot;
-                    }
-                    save = emitSaveRegisters(savedRegisters, savedRegisterLocations);
+                    save = emitSaveAllRegisters(savedRegisters, true);
                 }
             }
         }
 
         Variable result;
-        DeoptimizingNode deoptInfo = null;
+        // TODO (je) check if we can remove this
+        LIRFrameState deoptInfo = null;
         if (hotspotLinkage.canDeoptimize()) {
-            deoptInfo = info;
+            deoptInfo = state;
             assert deoptInfo != null || getStub() != null;
             assert hotspotLinkage.needsJavaFrameAnchor();
         }
@@ -230,9 +287,9 @@
         if (destroysRegisters) {
             if (getStub() != null) {
                 if (getStub().preservesRegisters()) {
-                    assert !((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo().containsKey(currentRuntimeCallInfo);
-                    ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo().put(currentRuntimeCallInfo, save);
-
+                    AMD64HotSpotLIRGenerationResult generationResult = (AMD64HotSpotLIRGenerationResult) getResult();
+                    assert !generationResult.getCalleeSaveInfo().containsKey(currentRuntimeCallInfo);
+                    generationResult.getCalleeSaveInfo().put(currentRuntimeCallInfo, save);
                     emitRestoreRegisters(save);
                 } else {
                     assert zapRegisters();
@@ -243,6 +300,21 @@
         return result;
     }
 
+    public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
+        ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP);
+
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread));
+        Variable result = super.emitForeignCall(linkage, null, thread.asValue(Kind.Long), trapRequest);
+        append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread));
+
+        Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo();
+        assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo);
+        calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp);
+
+        return result;
+    }
+
     protected AMD64ZapRegistersOp emitZapRegisters(Register[] zappedRegisters, Constant[] zapValues) {
         AMD64ZapRegistersOp zap = new AMD64ZapRegistersOp(zappedRegisters, zapValues);
         append(zap);
@@ -307,9 +379,9 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) {
         moveDeoptValuesToThread(actionAndReason, speculation);
-        append(new AMD64DeoptimizeOp(state(deopting)));
+        append(new AMD64DeoptimizeOp(state));
     }
 
     @Override
@@ -333,18 +405,16 @@
     }
 
     /**
-     * Returns whether or not the input access should be (de)compressed.
-     */
-    private boolean isCompressedOperation(PlatformKind kind, Access access) {
-        return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops));
-    }
-
-    /**
      * @return a compressed version of the incoming constant
      */
     protected static Constant compress(Constant c, CompressEncoding encoding) {
         if (c.getKind() == Kind.Long) {
-            return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
+            int compressedValue = (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL);
+            if (c instanceof HotSpotMetaspaceConstant) {
+                return HotSpotMetaspaceConstant.forMetaspaceObject(Kind.Int, compressedValue, HotSpotMetaspaceConstant.getMetaspaceObject(c));
+            } else {
+                return Constant.forIntegerKind(Kind.Int, compressedValue);
+            }
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -366,100 +436,72 @@
         }
     }
 
+    public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
+        Variable frameSizeVariable = load(frameSize);
+        Variable framePcVariable = load(framePc);
+        Variable senderSpVariable = load(senderSp);
+        Variable initialInfoVariable = load(initialInfo);
+        append(new AMD64HotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable));
+    }
+
     @Override
-    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) {
         AMD64AddressValue loadAddress = asAddressValue(address);
         Variable result = newVariable(toStackKind(kind));
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
-        /**
-         * Currently, the (de)compression of pointers applies conditionally to some objects (oops,
-         * kind==Object) and some addresses (klass pointers, kind==Long). Initially, the input
-         * operation is checked to discover if it has been tagged as a potential "compression"
-         * candidate. Consequently, depending on the appropriate kind, the specific (de)compression
-         * functions are being called.
-         */
-        if (isCompressedOperation(kind, access)) {
-            if (kind == Kind.Object) {
-                append(new LoadCompressedPointer(Kind.Object, result, getProviders().getRegisters().getHeapBaseRegister().asValue(), loadAddress, state, config.getOopEncoding()));
-            } else if (kind == Kind.Long) {
-                Variable scratch = config.getKlassEncoding().base != 0 ? newVariable(Kind.Long) : null;
-                append(new LoadCompressedPointer(Kind.Long, result, scratch, loadAddress, state, config.getKlassEncoding()));
-            } else {
-                throw GraalInternalError.shouldNotReachHere("can't handle: " + access);
-            }
-        } else {
-            append(new LoadOp(getMemoryKind(kind), result, loadAddress, state));
-        }
+        append(new LoadOp(getMemoryKind(kind), result, loadAddress, state));
         return result;
     }
 
     @Override
-    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) {
         AMD64AddressValue storeAddress = asAddressValue(address);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
-        boolean isCompressed = isCompressedOperation(kind, access);
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
-            if (canStoreConstant(c, isCompressed)) {
-                if (isCompressed) {
-                    if (c.getKind() == Kind.Object) {
-                        append(new StoreCompressedConstantOp(Kind.Object, storeAddress, c, state));
-                    } else if (c.getKind() == Kind.Long) {
-                        // It's always a good idea to directly store compressed constants since they
-                        // have to be materialized as 64 bits encoded otherwise.
-                        Constant value = compress(c, config.getKlassEncoding());
-                        append(new StoreCompressedConstantOp(Kind.Long, storeAddress, value, state));
-                    } else {
-                        throw GraalInternalError.shouldNotReachHere("can't handle: " + access);
-                    }
-                    return;
-                } else {
-                    append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state));
-                    return;
-                }
+            if (canStoreConstant(c, false)) {
+                append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state));
+                return;
             }
         }
         Variable input = load(inputVal);
-        if (isCompressed) {
-            if (kind == Kind.Object) {
-                if (input.getKind() == Kind.Object) {
-                    Variable scratch = newVariable(Kind.Long);
-                    Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister();
-                    append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, config.getOopEncoding(), heapBaseReg));
-                } else {
-                    // the input oop is already compressed
-                    append(new StoreOp(input.getKind(), storeAddress, input, state));
-                }
-            } else if (kind == Kind.Long) {
-                Variable scratch = newVariable(Kind.Long);
-                Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister();
-                append(new StoreCompressedPointer(Kind.Long, storeAddress, input, scratch, state, config.getKlassEncoding(), heapBaseReg));
-            } else {
-                append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
+        append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
+    }
+
+    @Override
+    public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
+        if (pointer.getPlatformKind() == Kind.Object) {
+            Variable result = newVariable(NarrowOopStamp.NarrowOop);
+            append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
+            return result;
+        } else {
+            assert pointer.getPlatformKind() == Kind.Long;
+            Variable result = newVariable(Kind.Int);
+            AllocatableValue base = Value.ILLEGAL;
+            if (encoding.base != 0) {
+                base = newVariable(Kind.Long);
+                append(new AMD64Move.MoveToRegOp(Kind.Long, base, Constant.forLong(encoding.base)));
             }
-        } else {
-            append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
+            append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull));
+            return result;
         }
     }
 
     @Override
-    public Value emitCompress(Value pointer, CompressEncoding encoding) {
-        Variable result = newVariable(NarrowOopStamp.NarrowOop);
-        append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding));
-        return result;
-    }
-
-    @Override
-    public Value emitUncompress(Value pointer, CompressEncoding encoding) {
-        Variable result = newVariable(Kind.Object);
-        append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding));
-        return result;
+    public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
+        if (pointer.getPlatformKind() == NarrowOopStamp.NarrowOop) {
+            Variable result = newVariable(Kind.Object);
+            append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
+            return result;
+        } else {
+            assert pointer.getPlatformKind() == Kind.Int;
+            Variable result = newVariable(Kind.Long);
+            AllocatableValue base = Value.ILLEGAL;
+            if (encoding.base != 0) {
+                base = newVariable(Kind.Long);
+                append(new AMD64Move.MoveToRegOp(Kind.Long, base, Constant.forLong(encoding.base)));
+            }
+            append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull));
+            return result;
+        }
     }
 
     @Override
@@ -475,4 +517,38 @@
         }
     }
 
+    public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        PlatformKind kind = newValue.getPlatformKind();
+        assert kind == expectedValue.getPlatformKind();
+        Kind memKind = getMemoryKind(kind);
+
+        AMD64AddressValue addressValue = asAddressValue(address);
+        RegisterValue raxRes = AMD64.rax.asValue(kind);
+        emitMove(raxRes, expectedValue);
+        append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue)));
+
+        assert trueValue.getPlatformKind() == falseValue.getPlatformKind();
+        Variable result = newVariable(trueValue.getPlatformKind());
+        append(new CondMoveOp(result, Condition.EQ, asAllocatable(trueValue), falseValue));
+        return result;
+    }
+
+    public Value emitAtomicReadAndAdd(Value address, Value delta) {
+        PlatformKind kind = delta.getPlatformKind();
+        Kind memKind = getMemoryKind(kind);
+        Variable result = newVariable(kind);
+        AMD64AddressValue addressValue = asAddressValue(address);
+        append(new AMD64Move.AtomicReadAndAddOp(memKind, result, addressValue, asAllocatable(delta)));
+        return result;
+    }
+
+    public Value emitAtomicReadAndWrite(Value address, Value newValue) {
+        PlatformKind kind = newValue.getPlatformKind();
+        Kind memKind = getMemoryKind(kind);
+        Variable result = newVariable(kind);
+        AMD64AddressValue addressValue = asAddressValue(address);
+        append(new AMD64Move.AtomicReadAndWriteOp(memKind, result, addressValue, asAllocatable(newValue)));
+        return result;
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Pops the current frame off the stack including the return address.
+ */
+@Opcode("LEAVE_CURRENT_STACK_FRAME")
+final class AMD64HotSpotLeaveCurrentStackFrameOp extends AMD64HotSpotEpilogueOp {
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        leaveFrameAndRestoreRbp(crb, masm);
+        masm.addq(rsp, crb.target.arch.getReturnAddressSize());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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.hotspot.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Pops the current frame off the stack including the return address.
+ */
+@Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME")
+final class AMD64HotSpotLeaveDeoptimizedStackFrameOp extends AMD64HotSpotEpilogueOp {
+
+    @Use(REG) AllocatableValue frameSize;
+    @Use(REG) AllocatableValue framePointer;
+
+    public AMD64HotSpotLeaveDeoptimizedStackFrameOp(AllocatableValue frameSize, AllocatableValue initialInfo) {
+        this.frameSize = frameSize;
+        this.framePointer = initialInfo;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        masm.addq(rsp, asRegister(frameSize));
+        // Restore the frame pointer before stack bang because if a stack overflow is thrown it
+        // needs to be pushed (and preserved).
+        masm.movq(rbp, asRegister(framePointer));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Emits code that leaves a stack frame which is tailored to call the C++ method
+ * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}.
+ */
+@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME")
+final class AMD64HotSpotLeaveUnpackFramesStackFrameOp extends AMD64LIRInstruction {
+
+    private final Register thread;
+    private final int threadLastJavaSpOffset;
+    private final int threadLastJavaPcOffset;
+    private final int threadLastJavaFpOffset;
+
+    AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset) {
+        this.thread = thread;
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.threadLastJavaPcOffset = threadLastJavaPcOffset;
+        this.threadLastJavaFpOffset = threadLastJavaFpOffset;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        // Restore stack pointer.
+        masm.movq(rsp, new AMD64Address(thread, threadLastJavaSpOffset));
+
+        // Clear last Java frame values.
+        masm.movslq(new AMD64Address(thread, threadLastJavaSpOffset), 0);
+        masm.movslq(new AMD64Address(thread, threadLastJavaPcOffset), 0);
+        masm.movslq(new AMD64Address(thread, threadLastJavaFpOffset), 0);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -41,7 +41,7 @@
 
     @Override
     public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
-        convertSnippets = new AMD64ConvertSnippets.Templates(providers, providers.getCodeCache().getTarget());
+        convertSnippets = new AMD64ConvertSnippets.Templates(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
         super.initialize(providers, config);
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,15 +28,17 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.compiler.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.data.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 
 /**
@@ -63,9 +65,9 @@
                 masm.cmpl(x.toAddress(), 0);
             } else {
                 if (y.getKind() == Kind.Object) {
-                    crb.recordInlineDataInCode(new OopData(0, constant.asObject(), true));
+                    crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(constant), true));
                 } else if (y.getKind() == Kind.Long) {
-                    crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), constant.getPrimitiveAnnotation(), true));
+                    crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), true));
                 } else {
                     throw GraalInternalError.shouldNotReachHere();
                 }
@@ -82,11 +84,21 @@
     }
 
     @Override
+    protected Kind getMemoryKind(Access access) {
+        PlatformKind kind = gen.getLIRGenerator().getPlatformKind(access.asNode().stamp());
+        if (kind == NarrowOopStamp.NarrowOop) {
+            return Kind.Int;
+        } else {
+            return (Kind) kind;
+        }
+    }
+
+    @Override
     protected boolean emitCompareBranchMemory(ValueNode left, ValueNode right, Access access, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel,
                     double trueLabelProbability) {
         if (HotSpotGraalRuntime.runtime().getConfig().useCompressedOops) {
             ValueNode other = selectOtherInput(left, right, access);
-            Kind kind = access.accessLocation().getValueKind();
+            Kind kind = getMemoryKind(access);
 
             if (other.isConstant() && kind == Kind.Object && access.isCompressible()) {
                 ensureEvaluated(other);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,10 +31,10 @@
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.data.*;
-import com.oracle.graal.hotspot.nodes.type.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
@@ -53,8 +53,8 @@
         public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
             if (kind == Kind.Long) {
                 if (NumUtil.isInt(input.asLong())) {
-                    if (input.getPrimitiveAnnotation() != null) {
-                        crb.recordInlineDataInCode(new MetaspaceData(0, input.asLong(), input.getPrimitiveAnnotation(), true));
+                    if (input instanceof HotSpotMetaspaceConstant) {
+                        crb.recordInlineDataInCode(new MetaspaceData(0, input.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(input), true));
                     }
                     masm.movl(address.toAddress(), (int) input.asLong());
                 } else {
@@ -64,7 +64,7 @@
                 if (input.isNull()) {
                     masm.movl(address.toAddress(), 0);
                 } else if (crb.target.inlineObjects) {
-                    crb.recordInlineDataInCode(new OopData(0, input.asObject(), true));
+                    crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(input), true));
                     masm.movl(address.toAddress(), 0xDEADDEAD);
                 } else {
                     throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
@@ -78,25 +78,36 @@
     public static class CompressPointer extends AMD64LIRInstruction {
 
         private final CompressEncoding encoding;
+        private final boolean nonNull;
 
         @Def({REG, HINT}) protected AllocatableValue result;
         @Use({REG}) protected AllocatableValue input;
-        @Temp({REG, ILLEGAL}) protected AllocatableValue baseRegister;
+        @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
 
-        public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding) {
+        public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
             this.result = result;
             this.input = input;
             this.baseRegister = baseRegister;
             this.encoding = encoding;
+            this.nonNull = nonNull;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            if (result.getPlatformKind() == NarrowOopStamp.NarrowOop) {
-                AMD64Move.move(Kind.Long, crb, masm, result, input);
-                encodePointer(masm, asRegister(result), asRegister(baseRegister), encoding);
-            } else {
-                throw GraalInternalError.unimplemented();
+            AMD64Move.move(Kind.Long, crb, masm, result, input);
+
+            Register resReg = asRegister(result);
+            if (encoding.base != 0) {
+                Register baseReg = asRegister(baseRegister);
+                if (!nonNull) {
+                    masm.testq(resReg, resReg);
+                    masm.cmovq(ConditionFlag.Equal, resReg, baseReg);
+                }
+                masm.subq(resReg, baseReg);
+            }
+
+            if (encoding.shift != 0) {
+                masm.shrq(resReg, encoding.shift);
             }
         }
     }
@@ -104,25 +115,43 @@
     public static class UncompressPointer extends AMD64LIRInstruction {
 
         private final CompressEncoding encoding;
+        private final boolean nonNull;
 
         @Def({REG, HINT}) protected AllocatableValue result;
         @Use({REG}) protected AllocatableValue input;
-        @Temp({REG, ILLEGAL}) protected AllocatableValue baseRegister;
+        @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
 
-        public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding) {
+        public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
             this.result = result;
             this.input = input;
             this.baseRegister = baseRegister;
             this.encoding = encoding;
+            this.nonNull = nonNull;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            if (result.getKind() == Kind.Object) {
-                AMD64Move.move(Kind.Int, crb, masm, result, input);
-                decodePointer(masm, asRegister(result), asRegister(baseRegister), encoding);
-            } else {
-                throw GraalInternalError.unimplemented();
+            AMD64Move.move(Kind.Int, crb, masm, result, input);
+
+            Register resReg = asRegister(result);
+            if (encoding.shift != 0) {
+                masm.shlq(resReg, encoding.shift);
+            }
+
+            if (encoding.base != 0) {
+                if (nonNull) {
+                    masm.addq(resReg, asRegister(baseRegister));
+                } else {
+                    if (encoding.shift == 0) {
+                        // if encoding.shift != 0, the flags are already set by the shlq
+                        masm.testq(resReg, resReg);
+                    }
+
+                    Label done = new Label();
+                    masm.jccb(ConditionFlag.Equal, done);
+                    masm.addq(resReg, asRegister(baseRegister));
+                    masm.bind(done);
+                }
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,8 +26,6 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -39,17 +37,14 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.SaveRbp;
-import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
@@ -60,6 +55,9 @@
     public AMD64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) {
         super(graph, gen);
         memoryPeephole = new AMD64HotSpotMemoryPeephole(this);
+        assert gen instanceof AMD64HotSpotLIRGenerator;
+        assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder;
+        ((AMD64HotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
     }
 
     private AMD64HotSpotLIRGenerator getGen() {
@@ -111,7 +109,7 @@
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
-        LIRFrameState info = gen.state(i);
+        LIRFrameState info = state(i);
         append(new AMD64HotSpotSafepointOp(info, getGen().config, this));
     }
 
@@ -123,9 +121,8 @@
         } else {
             assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
             HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
-            assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method.";
-            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
-            append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
+            assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method.";
+            append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
         }
     }
 
@@ -165,7 +162,7 @@
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) {
+        if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) {
             Debug.log("Ignoring InfopointNode for AFTER_BCI");
         } else {
             super.visitInfopointNode(i);
@@ -198,32 +195,10 @@
 
         RegisterValue raxLocal = AMD64.rax.asValue(kind);
         gen.emitMove(raxLocal, expected);
-        append(new CompareAndSwapOp(raxLocal, address, raxLocal, newVal));
+        append(new CompareAndSwapOp(kind, raxLocal, address, raxLocal, newVal));
 
         Variable result = newVariable(x.getKind());
         gen.emitMove(result, raxLocal);
         setResult(x, result);
     }
-
-    @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        Kind kind = node.getNewValue().getKind();
-        assert kind == node.getExpectedValue().getKind();
-        Value expected = gen.loadNonConst(operand(node.getExpectedValue()));
-        Variable newValue = gen.load(operand(node.getNewValue()));
-        AMD64AddressValue addressValue = getGen().asAddressValue(address);
-        RegisterValue raxRes = AMD64.rax.asValue(kind);
-        gen.emitMove(raxRes, expected);
-        if (getGen().config.useCompressedOops && node.isCompressible()) {
-            Variable scratch = newVariable(Kind.Long);
-            Register heapBaseReg = getGen().getProviders().getRegisters().getHeapBaseRegister();
-            append(new CompareAndSwapCompressedOp(raxRes, addressValue, raxRes, newValue, scratch, getGen().config.getOopEncoding(), heapBaseReg));
-        } else {
-            append(new CompareAndSwapOp(raxRes, addressValue, raxRes, newValue));
-        }
-        Variable result = newVariable(node.getKind());
-        append(new CondMoveOp(result, Condition.EQ, gen.load(Constant.TRUE), Constant.FALSE));
-        setResult(node, result);
-    }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,81 @@
+/*
+ * 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.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Pushes an interpreter frame to the stack.
+ */
+@Opcode("PUSH_INTERPRETER_FRAME")
+final class AMD64HotSpotPushInterpreterFrameOp extends AMD64LIRInstruction {
+
+    @Alive(REG) AllocatableValue frameSize;
+    @Alive(REG) AllocatableValue framePc;
+    @Alive(REG) AllocatableValue senderSp;
+    @Alive(REG) AllocatableValue initialInfo;
+
+    AMD64HotSpotPushInterpreterFrameOp(AllocatableValue frameSize, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue initialInfo) {
+        this.frameSize = frameSize;
+        this.framePc = framePc;
+        this.senderSp = senderSp;
+        this.initialInfo = initialInfo;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        final Register frameSizeRegister = asRegister(frameSize);
+        final Register framePcRegister = asRegister(framePc);
+        final Register senderSpRegister = asRegister(senderSp);
+        final Register initialInfoRegister = asRegister(initialInfo);
+        final HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig();
+        final int wordSize = HotSpotGraalRuntime.runtime().getTarget().wordSize;
+
+        // We'll push PC and BP by hand.
+        masm.subq(frameSizeRegister, 2 * wordSize);
+
+        // Push return address.
+        masm.push(framePcRegister);
+
+        // Prolog
+        masm.push(initialInfoRegister);
+        masm.movq(initialInfoRegister, rsp);
+        masm.subq(rsp, frameSizeRegister);
+
+        // This value is corrected by layout_activation_impl.
+        masm.movptr(new AMD64Address(initialInfoRegister, config.frameInterpreterFrameLastSpOffset * wordSize), 0);
+
+        // Make the frame walkable.
+        masm.movq(new AMD64Address(initialInfoRegister, config.frameInterpreterFrameSenderSpOffset * wordSize), senderSpRegister);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.amd64.AMD64.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
@@ -31,10 +31,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.type.*;
-import com.oracle.graal.phases.*;
 
 public class AMD64HotSpotRegisterConfig implements RegisterConfig {
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -29,13 +29,14 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
  * Returns from a function.
  */
 @Opcode("RETURN")
-final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp {
+final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp implements BlockEndOp {
 
     @Use({REG, ILLEGAL}) protected Value value;
     private final boolean isStub;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,7 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.asm.NumUtil.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -77,7 +77,7 @@
         if (ImmutableCode.getValue()) {
             Kind hostWordKind = HotSpotGraalRuntime.getHostWordKind();
             int alignment = hostWordKind.getBitCount() / Byte.SIZE;
-            Constant pollingPageAddress = Constant.forIntegerKind(hostWordKind, config.safepointPollingAddress, null);
+            Constant pollingPageAddress = Constant.forIntegerKind(hostWordKind, config.safepointPollingAddress);
             // This move will be patched to load the safepoint page from a data segment
             // co-located with the immutable code.
             asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment));
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -31,6 +31,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -38,7 +39,7 @@
  * Removes the current frame and jumps to the {@link UnwindExceptionToCallerStub}.
  */
 @Opcode("UNWIND")
-final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp {
+final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp implements BlockEndOp {
 
     @Use({REG}) protected RegisterValue exception;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,42 +22,32 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
-import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
-import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
- * A direct call that complies with the conventions for such calls in HotSpot. In particular, for
- * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call.
+ * A direct call that complies with the conventions for such calls in HotSpot. It doesn't use an
+ * inline cache so it's just a patchable call site.
  */
 @Opcode("CALL_DIRECT")
 final class AMD64HotspotDirectStaticCallOp extends DirectCallOp {
 
-    private final Constant metaspaceMethod;
     private final InvokeKind invokeKind;
 
-    AMD64HotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, Constant metaspaceMethod) {
+    AMD64HotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) {
         super(target, result, parameters, temps, state);
         assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
-        this.metaspaceMethod = metaspaceMethod;
         this.invokeKind = invokeKind;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-        // The mark for an invocation that uses an inline cache must be placed at the
-        // instruction that loads the Klass from the inline cache.
-        AMD64Move.move(crb, masm, AMD64.rbx.asValue(Kind.Long), metaspaceMethod);
         MarkId.recordMark(crb, invokeKind == InvokeKind.Static ? MarkId.INVOKESTATIC : MarkId.INVOKESPECIAL);
-        // This must be emitted exactly like this to ensure it's patchable
-        masm.movq(AMD64.rax, HotSpotGraalRuntime.runtime().getConfig().nonOopBits);
         super.emitCode(crb, masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,11 +26,11 @@
 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.common.type.*;
 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 {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/DonorThreadPool.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.hsail;
+
+import static com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options.*;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options;
+
+/**
+ * Thread pool for HSAIL allocation support.
+ */
+public class DonorThreadPool {
+
+    private final Thread[] threads;
+
+    void waitAt(CyclicBarrier barrier) {
+        try {
+            barrier.await();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Creates a pool of threads whose size is given by {@link Options#HsailDonorThreads}.
+     */
+    DonorThreadPool() {
+        int size = HsailDonorThreads.getValue();
+        this.threads = new Thread[size];
+        CyclicBarrier barrier = new CyclicBarrier(size + 1);
+
+        // fill in threads
+        for (int i = 0; i < size; i++) {
+            threads[i] = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    while (true) {
+                        waitAt(barrier);
+                    }
+                }
+            }, "HsailDonorThread-" + i);
+            threads[i].setDaemon(true);
+            threads[i].start();
+        }
+        // creating thread waits at barrier to make sure others have started
+        waitAt(barrier);
+    }
+
+    public Thread[] getThreads() {
+        return threads;
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Wed Apr 23 15:48:38 2014 +0200
@@ -62,7 +62,7 @@
      * @param intConsumerClass a class implementing {@code java.util.function.IntConsumer}
      * @return a {@link HotSpotNmethod} handle to the compiled and installed kernel
      */
-    private static HotSpotNmethod getCompiledLambda(Class intConsumerClass) {
+    private static HotSpotNmethod getCompiledLambda(Class<?> intConsumerClass) {
         Method acceptMethod = null;
         for (Method m : intConsumerClass.getMethods()) {
             if (m.getName().equals("accept")) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotAssembler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.hotspot.hsail;
+
+import java.lang.reflect.*;
+
+import com.amd.okra.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.hsail.*;
+import com.oracle.graal.hotspot.meta.*;
+
+/**
+ * This class contains routines to emit HSAIL assembly code.
+ */
+public class HSAILHotSpotAssembler extends HSAILAssembler {
+
+    public HSAILHotSpotAssembler(TargetDescription target) {
+        super(target);
+    }
+
+    @Override
+    public final void mov(Register a, Constant src) {
+        String regName = "$d" + a.encoding();
+        // For a null object simply move 0x0 into the destination register.
+        if (src.isNull()) {
+            emitString("mov_b64 " + regName + ", 0x0;  // null object");
+        } else {
+            Object obj = HotSpotObjectConstant.asObject(src);
+            // Get a JNI reference handle to the object.
+            long refHandle = OkraUtil.getRefHandle(obj);
+            // Get the clasname of the object for emitting a comment.
+            Class<?> clazz = obj.getClass();
+            String className = clazz.getName();
+            String comment = "// handle for object of type " + className;
+            // If the object is an array note the array length in the comment.
+            if (className.startsWith("[")) {
+                comment += ", length " + Array.getLength(obj);
+            }
+            // First move the reference handle into a register.
+            emitString("mov_b64 " + regName + ", 0x" + Long.toHexString(refHandle) + ";    " + comment);
+            // Next load the Object addressed by this reference handle into the destination reg.
+            emitString("ld_global_u64 " + regName + ", [" + regName + "];");
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,8 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options.*;
+import static com.oracle.graal.hotspot.hsail.replacements.HSAILNewObjectSnippets.Options.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -44,11 +46,13 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.hsail.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.gpu.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
 import com.oracle.graal.hotspot.meta.*;
@@ -57,14 +61,16 @@
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.hsail.*;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp;
+import com.oracle.graal.lir.hsail.HSAILMove.AtomicReadAndAddOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -73,6 +79,14 @@
  */
 public class HSAILHotSpotBackend extends HotSpotBackend {
 
+    public static class Options {
+
+        // @formatter:off
+        @Option(help = "Number of donor threads for HSAIL kernel dispatch")
+        static public final OptionValue<Integer> HsailDonorThreads = new OptionValue<>(4);
+        // @formatter:on
+    }
+
     private Map<String, String> paramTypeMap = new HashMap<>();
     private final boolean deviceInitialized;
     // TODO: get maximum Concurrency from okra
@@ -103,18 +117,6 @@
     private static native boolean initialize();
 
     /**
-     * Control how many threads run on simulator (used only from junit tests).
-     */
-    public void setSimulatorSingleThreaded() {
-        String simThrEnv = System.getenv("SIMTHREADS");
-        if (simThrEnv == null || !simThrEnv.equals("1")) {
-            setSimulatorSingleThreaded0();
-        }
-    }
-
-    private static native void setSimulatorSingleThreaded0();
-
-    /**
      * Determines if the GPU device (or simulator) is available and initialized.
      */
     public boolean isDeviceInitialized() {
@@ -257,7 +259,7 @@
                 Debug.log("Param count: %d", parameterTypes.length);
                 for (int i = 0; i < parameterTypes.length; i++) {
                     ParameterNode parameter = hostGraph.getParameter(i);
-                    Debug.log("Param [%d]=%d", i, parameter);
+                    Debug.log("Param [%d]=%s", i, parameter);
                     parameterTypes[i] = parameter.stamp().javaType(hostBackend.getProviders().getMetaAccess());
                     Debug.log(" %s", parameterTypes[i]);
                 }
@@ -293,7 +295,7 @@
         assert hsailCode.getDataReferences().isEmpty();
 
         // from host code
-        result.setFrameSize(hostCode.getFrameSize());
+        result.setTotalFrameSize(hostCode.getTotalFrameSize());
         result.setCustomStackAreaOffset(hostCode.getCustomStackAreaOffset());
         result.setRegisterRestoreEpilogueOffset(hostCode.getRegisterRestoreEpilogueOffset());
         result.setTargetCode(hostCode.getTargetCode(), hostCode.getTargetCodeSize());
@@ -347,15 +349,23 @@
         return result;
     }
 
+    private static final ThreadLocal<DonorThreadPool> donorThreadPool = new ThreadLocal<DonorThreadPool>() {
+        @Override
+        protected DonorThreadPool initialValue() {
+            return new DonorThreadPool();
+        }
+    };
+
     public boolean executeKernel(HotSpotInstalledCode kernel, int jobSize, Object[] args) throws InvalidInstalledCodeException {
         if (!deviceInitialized) {
             throw new GraalInternalError("Cannot execute GPU kernel if device is not initialized");
         }
         Object[] oopsSaveArea = new Object[maxDeoptIndex * 16];
-        return executeKernel0(kernel, jobSize, args, oopsSaveArea);
+        return executeKernel0(kernel, jobSize, args, oopsSaveArea, donorThreadPool.get().getThreads(), HsailAllocBytesPerWorkitem.getValue());
     }
 
-    private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave) throws InvalidInstalledCodeException;
+    private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave, Thread[] donorThreads, int allocBytesPerWorkitem)
+                    throws InvalidInstalledCodeException;
 
     /**
      * Use the HSAIL register set when the compilation target is HSAIL.
@@ -412,7 +422,7 @@
 
     @Override
     protected Assembler createAssembler(FrameMap frameMap) {
-        return new HSAILAssembler(getTarget());
+        return new HSAILHotSpotAssembler(getTarget());
     }
 
     @Override
@@ -423,15 +433,32 @@
         // save lirGen for later use by setHostGraph
         CompilationResultBuilder crb = new HSAILCompilationResultBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult,
                         (HSAILHotSpotLIRGenerationResult) lirGenRes);
-        crb.setFrameSize(frameMap.frameSize());
+        crb.setTotalFrameSize(frameMap.totalFrameSize());
         return crb;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod method) {
         assert method != null : lir + " is not associated with a method";
+        Kind wordKind = getProviders().getCodeCache().getTarget().wordKind;
 
-        boolean useHSAILDeoptimization = getRuntime().getConfig().useHSAILDeoptimization;
+        HotSpotVMConfig config = getRuntime().getConfig();
+        boolean useHSAILDeoptimization = config.useHSAILDeoptimization;
+        boolean useHSAILSafepoints = config.useHSAILSafepoints;
+
+        // see what graph nodes we have to see if we are using the thread register
+        // if not, we don't have to emit the code that sets that up
+        // maybe there is a better way to do this?
+        boolean usesThreadRegister = false;
+        search: for (AbstractBlock<?> b : lir.linearScanOrder()) {
+            for (LIRInstruction op : lir.getLIRforBlock(b)) {
+                if (op instanceof AtomicReadAndAddOp) {
+                    usesThreadRegister = true;
+                    assert useHSAILDeoptimization : "cannot use thread register if HSAIL deopt support is disabled";
+                    break search;
+                }
+            }
+        }
 
         // Emit the prologue.
         HSAILAssembler asm = (HSAILAssembler) crb.asm;
@@ -442,7 +469,7 @@
         // We're subtracting 1 because we're not making the final gid as a parameter.
 
         int nonConstantParamCount = sigParamCount - 1;
-        boolean isStatic = (Modifier.isStatic(method.getModifiers()));
+        boolean isStatic = (method.isStatic());
         // Determine if this is an object lambda.
         boolean isObjectLambda = true;
 
@@ -542,18 +569,51 @@
         String workItemReg = "$s" + Integer.toString(asRegister(cc.getArgument(nonConstantParamCount)).encoding());
         asm.emitString("workitemabsid_u32 " + workItemReg + ", 0;");
 
-        final int offsetToDeopt = getRuntime().getConfig().hsailDeoptOffset;
         final String deoptInProgressLabel = "@LHandleDeoptInProgress";
 
         if (useHSAILDeoptimization) {
-            AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object);
-            AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int);
-            HSAILAddress deoptInfoAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeopt).toAddress();
-            asm.emitLoadKernelArg(scratch64, asm.getDeoptInfoName(), "u64");
-            asm.emitComment("// Check if a deopt has occurred and abort if true before doing any work");
-            asm.emitLoadAcquire(scratch32, deoptInfoAddr);
-            asm.emitCompare(scratch32, Constant.forInt(0), "ne", false, false);
+            // Aliases for d16
+            RegisterValue d16_deoptInfo = HSAIL.d16.asValue(wordKind);
+            RegisterValue d16_donorThreads = d16_deoptInfo;
+
+            // Aliases for d17
+            RegisterValue d17_donorThreadIndex = HSAIL.d17.asValue(wordKind);
+            RegisterValue d17_safepointFlagAddrIndex = d17_donorThreadIndex;
+
+            // Aliases for s34
+            RegisterValue s34_deoptOccurred = HSAIL.s34.asValue(Kind.Int);
+            RegisterValue s34_donorThreadIndex = s34_deoptOccurred;
+
+            asm.emitLoadKernelArg(d16_deoptInfo, asm.getDeoptInfoName(), "u64");
+            asm.emitComment("// Check if a deopt or safepoint has occurred and abort if true before doing any work");
+
+            if (useHSAILSafepoints) {
+                // Load address of _notice_safepoints field
+                asm.emitLoad(wordKind, d17_safepointFlagAddrIndex, new HSAILAddressValue(wordKind, d16_deoptInfo, config.hsailNoticeSafepointsOffset).toAddress());
+                // Load int value from that field
+                asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(Kind.Int, d17_safepointFlagAddrIndex, 0).toAddress());
+                asm.emitCompare(Kind.Int, s34_deoptOccurred, Constant.forInt(0), "ne", false, false);
+                asm.cbr(deoptInProgressLabel);
+            }
+            asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(Kind.Int, d16_deoptInfo, config.hsailDeoptOccurredOffset).toAddress());
+            asm.emitCompare(Kind.Int, s34_deoptOccurred, Constant.forInt(0), "ne", false, false);
             asm.cbr(deoptInProgressLabel);
+            // load thread register if needed
+            if (usesThreadRegister) {
+                assert HsailDonorThreads.getValue() > 0;
+                asm.emitLoad(wordKind, d16_donorThreads, new HSAILAddressValue(wordKind, d16_deoptInfo, config.hsailDonorThreadsOffset).toAddress());
+                if (HsailDonorThreads.getValue() != 1) {
+                    asm.emitComment("// map workitem to a donor thread");
+                    asm.emitString(String.format("rem_u32  $%s, %s, %d;", s34_donorThreadIndex.getRegister(), workItemReg, HsailDonorThreads.getValue()));
+                    asm.emitConvert(d17_donorThreadIndex, s34_donorThreadIndex, wordKind, Kind.Int);
+                    asm.emit("mad", d16_donorThreads, d17_donorThreadIndex, Constant.forInt(8), d16_donorThreads);
+                } else {
+                    // workitem is already mapped to solitary donor thread
+                }
+                AllocatableValue threadRegValue = getProviders().getRegisters().getThreadRegister().asValue(wordKind);
+                asm.emitComment("// $" + getProviders().getRegisters().getThreadRegister() + " will point to a donor thread for this workitem");
+                asm.emitLoad(wordKind, threadRegValue, new HSAILAddressValue(wordKind, d16_donorThreads).toAddress());
+            }
         }
 
         /*
@@ -566,8 +626,8 @@
         asm.emitString(spillsegTemplate);
         // Emit object array load prologue here.
         if (isObjectLambda) {
-            boolean useCompressedOops = getRuntime().getConfig().useCompressedOops;
-            final int arrayElementsOffset = HotSpotGraalRuntime.getArrayBaseOffset(Kind.Object);
+            boolean useCompressedOops = config.useCompressedOops;
+            final int arrayElementsOffset = HotSpotGraalRuntime.getArrayBaseOffset(wordKind);
             String iterationObjArgReg = HSAIL.mapRegister(cc.getArgument(nonConstantParamCount - 1));
             // iterationObjArgReg will be the highest $d register in use (it is the last parameter)
             // so tempReg can be the next higher $d register
@@ -586,8 +646,8 @@
                 // Load u32 into the d 64 reg since it will become an object address
                 asm.emitString("ld_global_u32 " + tmpReg + ", " + "[" + tmpReg + "]" + "; // Load compressed ptr from array");
 
-                long narrowOopBase = getRuntime().getConfig().narrowOopBase;
-                long narrowOopShift = getRuntime().getConfig().narrowOopShift;
+                long narrowOopBase = config.narrowOopBase;
+                long narrowOopShift = config.narrowOopShift;
 
                 if (narrowOopBase == 0 && narrowOopShift == 0) {
                     // No more calculation to do, mov to target register
@@ -629,36 +689,36 @@
 
         // TODO: keep track of whether we need it
         if (useHSAILDeoptimization) {
-            final int offsetToDeoptSaveStates = getRuntime().getConfig().hsailSaveStatesOffset0;
-            final int sizeofKernelDeopt = getRuntime().getConfig().hsailSaveStatesOffset1 - getRuntime().getConfig().hsailSaveStatesOffset0;
-            final int offsetToNeverRanArray = getRuntime().getConfig().hsailNeverRanArrayOffset;
-            final int offsetToDeoptNextIndex = getRuntime().getConfig().hsailDeoptNextIndexOffset;
-            final int offsetToDeoptimizationWorkItem = getRuntime().getConfig().hsailDeoptimizationWorkItem;
-            final int offsetToDeoptimizationReason = getRuntime().getConfig().hsailDeoptimizationReason;
-            final int offsetToDeoptimizationFrame = getRuntime().getConfig().hsailDeoptimizationFrame;
-            final int offsetToFramePc = getRuntime().getConfig().hsailFramePcOffset;
-            final int offsetToNumSaves = getRuntime().getConfig().hsailFrameNumSRegOffset;
-            final int offsetToSaveArea = getRuntime().getConfig().hsailFrameSaveAreaOffset;
+            final int offsetToDeoptSaveStates = config.hsailSaveStatesOffset0;
+            final int sizeofKernelDeopt = config.hsailSaveStatesOffset1 - config.hsailSaveStatesOffset0;
+            final int offsetToNeverRanArray = config.hsailNeverRanArrayOffset;
+            final int offsetToDeoptNextIndex = config.hsailDeoptNextIndexOffset;
+            final int offsetToDeoptimizationWorkItem = config.hsailDeoptimizationWorkItem;
+            final int offsetToDeoptimizationReason = config.hsailDeoptimizationReason;
+            final int offsetToDeoptimizationFrame = config.hsailDeoptimizationFrame;
+            final int offsetToFramePc = config.hsailFramePcOffset;
+            final int offsetToNumSaves = config.hsailFrameNumSRegOffset;
+            final int offsetToSaveArea = config.hsailFrameSaveAreaOffset;
 
-            AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object);
-            AllocatableValue cuSaveAreaPtr = HSAIL.d17.asValue(Kind.Object);
-            AllocatableValue waveMathScratch1 = HSAIL.d18.asValue(Kind.Object);
-            AllocatableValue waveMathScratch2 = HSAIL.d19.asValue(Kind.Object);
+            AllocatableValue scratch64 = HSAIL.d16.asValue(wordKind);
+            AllocatableValue cuSaveAreaPtr = HSAIL.d17.asValue(wordKind);
+            AllocatableValue waveMathScratch1 = HSAIL.d18.asValue(wordKind);
+            AllocatableValue waveMathScratch2 = HSAIL.d19.asValue(wordKind);
 
-            AllocatableValue actionAndReasonReg = HSAIL.s32.asValue(Kind.Int);
-            AllocatableValue codeBufferOffsetReg = HSAIL.s33.asValue(Kind.Int);
+            AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
+            AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
             AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int);
             AllocatableValue workidreg = HSAIL.s35.asValue(Kind.Int);
-            AllocatableValue dregOopMapReg = HSAIL.s39.asValue(Kind.Int);
+            AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int);
 
             HSAILAddress deoptNextIndexAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeoptNextIndex).toAddress();
             HSAILAddress neverRanArrayAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToNeverRanArray).toAddress();
 
             // The just-started lanes that see the deopt flag will jump here
             asm.emitString0(deoptInProgressLabel + ":\n");
-            asm.emitLoad(Kind.Object, waveMathScratch1, neverRanArrayAddr);
+            asm.emitLoad(wordKind, waveMathScratch1, neverRanArrayAddr);
             asm.emitWorkItemAbsId(workidreg);
-            asm.emitConvert(waveMathScratch2, workidreg, Kind.Object, Kind.Int);
+            asm.emitConvert(waveMathScratch2, workidreg, wordKind, Kind.Int);
             asm.emit("add", waveMathScratch1, waveMathScratch1, waveMathScratch2);
             HSAILAddress neverRanStoreAddr = new HSAILAddressValue(Kind.Byte, waveMathScratch1, 0).toAddress();
             asm.emitStore(Kind.Byte, Constant.forInt(1), neverRanStoreAddr);
@@ -668,7 +728,7 @@
             asm.emitString0(asm.getDeoptLabelName() + ":\n");
             String labelExit = asm.getDeoptLabelName() + "_Exit";
 
-            HSAILAddress deoptInfoAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeopt).toAddress();
+            HSAILAddress deoptInfoAddr = new HSAILAddressValue(Kind.Int, scratch64, config.hsailDeoptOccurredOffset).toAddress();
             asm.emitLoadKernelArg(scratch64, asm.getDeoptInfoName(), "u64");
 
             // Set deopt occurred flag
@@ -680,7 +740,7 @@
             // scratch32 now holds next index to use
             // set error condition if no room in save area
             asm.emitComment("// assert room to save deopt");
-            asm.emitCompare(scratch32, Constant.forInt(maxDeoptIndex), "lt", false, false);
+            asm.emitCompare(Kind.Int, scratch32, Constant.forInt(maxDeoptIndex), "lt", false, false);
             asm.cbr("@L_StoreDeopt");
             // if assert fails, store a guaranteed negative workitemid in top level deopt occurred
             // flag
@@ -694,7 +754,7 @@
             // Store deopt for this workitem into its slot in the HSAILComputeUnitSaveStates array
 
             asm.emitComment("// Convert id's for ptr math");
-            asm.emitConvert(cuSaveAreaPtr, scratch32, Kind.Object, Kind.Int);
+            asm.emitConvert(cuSaveAreaPtr, scratch32, wordKind, Kind.Int);
             asm.emitComment("// multiply by sizeof KernelDeoptArea");
             asm.emit("mul", cuSaveAreaPtr, cuSaveAreaPtr, Constant.forInt(sizeofKernelDeopt));
             asm.emitComment("// Add computed offset to deoptInfoPtr base");
@@ -725,9 +785,7 @@
             asm.emitStore(Kind.Short, dregOopMapReg, dregOopMapAddr);
 
             // get the union of registers needed to be saved at the infopoints
-            // usedRegs array assumes d15 has the highest register number we wish to save
-            // and initially has all registers as false
-            boolean[] infoUsedRegs = new boolean[HSAIL.d15.number + 1];
+            boolean[] infoUsedRegs = new boolean[HSAIL.threadRegister.number + 1];
             List<Infopoint> infoList = crb.compilationResult.getInfopoints();
             for (Infopoint info : infoList) {
                 BytecodeFrame frame = info.debugInfo.frame();
@@ -784,10 +842,10 @@
 
         ExternalCompilationResult compilationResult = (ExternalCompilationResult) crb.compilationResult;
         HSAILHotSpotLIRGenerationResult lirGenRes = ((HSAILCompilationResultBuilder) crb).lirGenRes;
-        compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), getRuntime().getConfig()));
+        compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), config));
     }
 
-    private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List<DeoptimizeOp> deopts, HotSpotProviders providers, HotSpotVMConfig config) {
+    private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List<DeoptimizingOp> deopts, HotSpotProviders providers, HotSpotVMConfig config) {
         if (deopts.isEmpty()) {
             return null;
         }
@@ -796,17 +854,17 @@
         ParameterNode hsailFrame = hostGraph.unique(new ParameterNode(1, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind)));
         ParameterNode reasonAndAction = hostGraph.unique(new ParameterNode(2, StampFactory.intValue()));
         ParameterNode speculation = hostGraph.unique(new ParameterNode(3, StampFactory.object()));
-        AbstractBeginNode[] branches = new AbstractBeginNode[deopts.size() + 1];
+        BeginNode[] branches = new BeginNode[deopts.size() + 1];
         int[] keys = new int[deopts.size()];
         int[] keySuccessors = new int[deopts.size() + 1];
         double[] keyProbabilities = new double[deopts.size() + 1];
         int i = 0;
-        Collections.sort(deopts, new Comparator<DeoptimizeOp>() {
-            public int compare(DeoptimizeOp o1, DeoptimizeOp o2) {
+        Collections.sort(deopts, new Comparator<DeoptimizingOp>() {
+            public int compare(DeoptimizingOp o1, DeoptimizingOp o2) {
                 return o1.getCodeBufferPos() - o2.getCodeBufferPos();
             }
         });
-        for (DeoptimizeOp deopt : deopts) {
+        for (DeoptimizingOp deopt : deopts) {
             keySuccessors[i] = i;
             keyProbabilities[i] = 1.0 / deopts.size();
             keys[i] = deopt.getCodeBufferPos();
@@ -828,15 +886,14 @@
         return hostGraph;
     }
 
-    private static AbstractBeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) {
+    private static BeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) {
         VMErrorNode vmError = hostGraph.add(new VMErrorNode("Error in HSAIL deopt. DeoptId=%d", deoptId));
         // ConvertNode.convert(hostGraph, Kind.Long, deoptId)));
         vmError.setNext(hostGraph.add(new ReturnNode(ConstantNode.defaultForKind(hostGraph.method().getSignature().getReturnKind(), hostGraph))));
         return BeginNode.begin(vmError);
     }
 
-    private static AbstractBeginNode createHostDeoptBranch(DeoptimizeOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers,
-                    HotSpotVMConfig config) {
+    private static BeginNode createHostDeoptBranch(DeoptimizingOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers, HotSpotVMConfig config) {
         BeginNode branch = hsailFrame.graph().add(new BeginNode());
         DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(new DynamicDeoptimizeNode(reasonAndAction, speculation));
         deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config));
@@ -868,7 +925,7 @@
         return frameState;
     }
 
-    @SuppressWarnings({"unused"})
+    @SuppressWarnings("unused")
     private static MonitorIdNode getMonitorIdForHotSpotMonitorValueFromFrame(HotSpotMonitorValue lockValue, ParameterNode hsailFrame, StructuredGraph hsailGraph) {
         if (lockValue.isEliminated()) {
             return null;
@@ -910,7 +967,7 @@
             int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long);
             long offset = config.hsailFrameSaveAreaOffset + longSize * (regNumber - HSAIL.d0.number);
             LocationNode numSRegsLocation = ConstantLocationNode.create(FINAL_LOCATION, Kind.Byte, config.hsailFrameNumSRegOffset, hostGraph);
-            ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8, false)));
+            ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8)));
             numSRegs = SignExtendNode.convert(numSRegs, StampFactory.forKind(Kind.Byte));
             location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4);
         } else {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,10 +28,10 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hsail.*;
-import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
+import com.oracle.graal.hotspot.hsail.replacements.*;
 
 @ServiceProvider(HotSpotBackendFactory.class)
 public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory {
@@ -40,7 +40,7 @@
     public HSAILHotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend hostBackend) {
         HotSpotProviders host = hostBackend.getProviders();
 
-        HotSpotRegisters registers = new HotSpotRegisters(Register.None, Register.None, Register.None);
+        HotSpotRegisters registers = new HotSpotRegisters(HSAIL.threadRegister, Register.None, Register.None);
         HotSpotMetaAccessProvider metaAccess = host.getMetaAccess();
         HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, createTarget());
         ConstantReflectionProvider constantReflection = host.getConstantReflection();
@@ -50,10 +50,13 @@
         // to be valid for the entire run of the VM.
         Assumptions assumptions = new Assumptions(false);
         Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null);
-        Replacements replacements = new HSAILHotSpotReplacementsImpl(p, assumptions, codeCache.getTarget(), host.getReplacements());
+        Replacements replacements = new HSAILHotSpotReplacementsImpl(p, host.getSnippetReflection(), assumptions, codeCache.getTarget(), host.getReplacements());
         HotSpotDisassemblerProvider disassembler = host.getDisassembler();
-        SuitesProvider suites = new DefaultSuitesProvider();
-        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
+        SuitesProvider suites = new HotSpotSuitesProvider(runtime);
+        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection());
+
+        // pass registers info down to ReplacementsUtil (maybe a better way to do this?)
+        HSAILHotSpotReplacementsUtil.initialize(providers.getRegisters());
 
         return new HSAILHotSpotBackend(runtime, providers);
     }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,23 +24,23 @@
 
 import java.util.*;
 
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
+import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp;
 
 public class HSAILHotSpotLIRGenerationResult extends LIRGenerationResultBase {
 
-    private List<DeoptimizeOp> deopts = new ArrayList<>();
+    private List<DeoptimizingOp> deopts = new ArrayList<>();
 
     public HSAILHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap) {
         super(lir, frameMap);
     }
 
-    public List<DeoptimizeOp> getDeopts() {
+    public List<DeoptimizingOp> getDeopts() {
         return deopts;
     }
 
-    public void addDeopt(DeoptimizeOp deopt) {
+    public void addDeopt(DeoptimizingOp deopt) {
         deopts.add(deopt);
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -27,28 +27,28 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.hsail.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall1ArgOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall2ArgOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp;
-import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer;
+import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp;
 import com.oracle.graal.lir.hsail.HSAILMove.LoadOp;
 import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp;
 import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp;
-import com.oracle.graal.lir.hsail.HSAILMove.StoreCompressedPointer;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreOp;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -92,22 +92,11 @@
         return config.narrowKlassBase;
     }
 
-    private static boolean isCompressCandidate(Access access) {
-        return access != null && access.isCompressible();
-    }
-
     @Override
     public boolean canStoreConstant(Constant c, boolean isCompressed) {
         return true;
     }
 
-    /**
-     * Returns whether or not the input access should be (de)compressed.
-     */
-    private boolean isCompressedOperation(PlatformKind kind, Access access) {
-        return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops));
-    }
-
     private static Kind getMemoryKind(PlatformKind kind) {
         if (kind == NarrowOopStamp.NarrowOop) {
             return Kind.Int;
@@ -117,20 +106,10 @@
     }
 
     @Override
-    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) {
         HSAILAddressValue loadAddress = asAddressValue(address);
         Variable result = newVariable(kind);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
-        if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) {
-            Variable scratch = newVariable(Kind.Long);
-            append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
-        } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) {
-            Variable scratch = newVariable(Kind.Long);
-            append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment()));
-        } else if (kind == NarrowOopStamp.NarrowOop) {
+        if (kind == NarrowOopStamp.NarrowOop) {
             append(new LoadOp(Kind.Int, result, loadAddress, state));
         } else {
             append(new LoadOp(getMemoryKind(kind), result, loadAddress, state));
@@ -139,49 +118,51 @@
     }
 
     @Override
-    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) {
         HSAILAddressValue storeAddress = asAddressValue(address);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
-        boolean isCompressed = isCompressedOperation(kind, access);
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
-            if (canStoreConstant(c, isCompressed)) {
-                if (isCompressed) {
-                    if ((c.getKind() == Kind.Object) && c.isNull()) {
-                        append(new StoreConstantOp(Kind.Int, storeAddress, Constant.forInt(0), state));
-                    } else if (c.getKind() == Kind.Long) {
-                        Constant value = compress(c, config.getKlassEncoding());
-                        append(new StoreConstantOp(Kind.Int, storeAddress, value, state));
-                    } else {
-                        throw GraalInternalError.shouldNotReachHere("can't handle: " + access);
-                    }
-                    return;
-                } else {
-                    append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state));
-                    return;
-                }
+            if (canStoreConstant(c, false)) {
+                append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state));
+                return;
             }
         }
         Variable input = load(inputVal);
-        if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) {
-            Variable scratch = newVariable(Kind.Long);
-            append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
-        } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) {
-            Variable scratch = newVariable(Kind.Long);
-            append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment()));
-        } else if (kind == NarrowOopStamp.NarrowOop) {
+        if (kind == NarrowOopStamp.NarrowOop) {
             append(new StoreOp(Kind.Int, storeAddress, input, state));
         } else {
             append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
         }
     }
 
+    public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        PlatformKind kind = newValue.getPlatformKind();
+        assert kind == expectedValue.getPlatformKind();
+        Kind memKind = getMemoryKind(kind);
+
+        HSAILAddressValue addressValue = asAddressValue(address);
+        Variable expected = emitMove(expectedValue);
+        Variable casResult = newVariable(kind);
+        append(new CompareAndSwapOp(memKind, casResult, addressValue, expected, asAllocatable(newValue)));
+
+        assert trueValue.getPlatformKind() == falseValue.getPlatformKind();
+        Variable nodeResult = newVariable(trueValue.getPlatformKind());
+        append(new CondMoveOp(HSAILLIRGenerator.mapKindToCompareOp(memKind), casResult, expected, nodeResult, Condition.EQ, trueValue, falseValue));
+        return nodeResult;
+    }
+
+    public Value emitAtomicReadAndAdd(Value address, Value delta) {
+        PlatformKind kind = delta.getPlatformKind();
+        Kind memKind = getMemoryKind(kind);
+        Variable result = newVariable(kind);
+        HSAILAddressValue addressValue = asAddressValue(address);
+        append(new HSAILMove.AtomicReadAndAddOp(memKind, result, addressValue, asAllocatable(delta)));
+        return result;
+    }
+
     @Override
-    public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting) {
-        emitDeoptimizeInner(actionAndReason, state(deopting), "emitDeoptimize");
+    public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state) {
+        emitDeoptimizeInner(actionAndReason, state, "emitDeoptimize");
     }
 
     /***
@@ -199,7 +180,7 @@
      * emitting a comment as to what Foreign call they would have made.
      */
     @Override
-    public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
+    public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) {
         Variable result = newVariable(Kind.Object);  // linkage.getDescriptor().getResultType());
 
         // to make the LIRVerifier happy, we move any constants into registers
@@ -252,33 +233,68 @@
      */
     protected static Constant compress(Constant c, CompressEncoding encoding) {
         if (c.getKind() == Kind.Long) {
-            return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
+            int compressedValue = (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL);
+            if (c instanceof HotSpotMetaspaceConstant) {
+                return HotSpotMetaspaceConstant.forMetaspaceObject(Kind.Int, compressedValue, HotSpotMetaspaceConstant.getMetaspaceObject(c));
+            } else {
+                return Constant.forIntegerKind(Kind.Int, compressedValue);
+            }
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     public void emitTailcall(Value[] args, Value address) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     public StackSlot getLockSlot(int lockDepth) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
-    public Value emitCompress(Value pointer, CompressEncoding encoding) {
+    @Override
+    public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
         Variable result = newVariable(NarrowOopStamp.NarrowOop);
-        append(new HSAILMove.CompressPointer(result, newVariable(pointer.getPlatformKind()), asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment));
+        append(new HSAILMove.CompressPointer(result, newVariable(pointer.getPlatformKind()), asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment, nonNull));
+        return result;
+    }
+
+    @Override
+    public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
+        Variable result = newVariable(Kind.Object);
+        append(new HSAILMove.UncompressPointer(result, asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment, nonNull));
         return result;
     }
 
-    public Value emitUncompress(Value pointer, CompressEncoding encoding) {
-        Variable result = newVariable(Kind.Object);
-        append(new HSAILMove.UncompressPointer(result, asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment));
-        return result;
+    public void emitLeaveCurrentStackFrame() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitLeaveUnpackFramesStackFrame() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public SaveRegistersOp emitSaveAllRegisters() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
+        throw GraalInternalError.unimplemented();
     }
 }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,41 +22,59 @@
  */
 package com.oracle.graal.hotspot.hsail;
 
-import java.util.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.hotspot.hsail.replacements.*;
+
+import java.util.HashMap;
 
 public class HSAILHotSpotLoweringProvider extends HotSpotLoweringProvider {
 
-    abstract static class LoweringStrategy {
+    private HSAILNewObjectSnippets.Templates hsailNewObjectSnippets;
+
+    abstract class LoweringStrategy {
         abstract void lower(Node n, LoweringTool tool);
     }
 
-    static LoweringStrategy PassThruStrategy = new LoweringStrategy() {
+    LoweringStrategy PassThruStrategy = new LoweringStrategy() {
         @Override
         void lower(Node n, LoweringTool tool) {
             return;
         }
     };
 
-    static LoweringStrategy RejectStrategy = new LoweringStrategy() {
+    LoweringStrategy RejectStrategy = new LoweringStrategy() {
         @Override
         void lower(Node n, LoweringTool tool) {
             throw new GraalInternalError("Node implementing Lowerable not handled in HSAIL Backend: " + n);
         }
     };
 
+    LoweringStrategy NewObjectStrategy = new LoweringStrategy() {
+        @Override
+        void lower(Node n, LoweringTool tool) {
+            StructuredGraph graph = (StructuredGraph) n.graph();
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
+                if (n instanceof NewInstanceNode) {
+                    hsailNewObjectSnippets.lower((NewInstanceNode) n, tool);
+                } else if (n instanceof NewArrayNode) {
+                    hsailNewObjectSnippets.lower((NewArrayNode) n, tool);
+                }
+            }
+        }
+    };
+
     // strategy to replace an UnwindNode with a DeoptNode
-    static LoweringStrategy UnwindNodeStrategy = new LoweringStrategy() {
+    LoweringStrategy UnwindNodeStrategy = new LoweringStrategy() {
         @Override
         void lower(Node n, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) n.graph();
@@ -85,12 +103,13 @@
         }
     };
 
-    private static HashMap<Class<?>, LoweringStrategy> strategyMap = new HashMap<>();
-    static {
+    private HashMap<Class<?>, LoweringStrategy> strategyMap = new HashMap<>();
+
+    void initStrategyMap() {
         strategyMap.put(ConvertNode.class, PassThruStrategy);
         strategyMap.put(FloatConvertNode.class, PassThruStrategy);
-        strategyMap.put(NewInstanceNode.class, RejectStrategy);
-        strategyMap.put(NewArrayNode.class, RejectStrategy);
+        strategyMap.put(NewInstanceNode.class, NewObjectStrategy);
+        strategyMap.put(NewArrayNode.class, NewObjectStrategy);
         strategyMap.put(NewMultiArrayNode.class, RejectStrategy);
         strategyMap.put(DynamicNewArrayNode.class, RejectStrategy);
         strategyMap.put(MonitorEnterNode.class, RejectStrategy);
@@ -98,12 +117,20 @@
         strategyMap.put(UnwindNode.class, UnwindNodeStrategy);
     }
 
-    private static LoweringStrategy getStrategy(Node n) {
+    private LoweringStrategy getStrategy(Node n) {
         return strategyMap.get(n.getClass());
     }
 
     public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) {
         super(runtime, metaAccess, foreignCalls, registers);
+        initStrategyMap();
+    }
+
+    @Override
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+        super.initialize(providers, config);
+        TargetDescription target = providers.getCodeCache().getTarget();
+        hsailNewObjectSnippets = new HSAILNewObjectSnippets.Templates(providers, target);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,71 +23,31 @@
 
 package com.oracle.graal.hotspot.hsail;
 
-import sun.misc.*;
-
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.hsail.*;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
-import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapCompressedOp;
 import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
 
 /**
  * The HotSpot specific portion of the HSAIL LIR generator.
  */
-public class HSAILHotSpotNodeLIRBuilder extends HSAILNodeLIRBuilder {
+public class HSAILHotSpotNodeLIRBuilder extends HSAILNodeLIRBuilder implements HotSpotNodeLIRBuilder {
 
     public HSAILHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) {
         super(graph, lirGen);
     }
 
-    private HSAILHotSpotLIRGenerator getGen() {
-        return (HSAILHotSpotLIRGenerator) gen;
-    }
-
-    /**
-     * Appends either a {@link CompareAndSwapOp} or a {@link CompareAndSwapCompressedOp} depending
-     * on whether the memory location of a given {@link LoweredCompareAndSwapNode} contains a
-     * compressed oop. For the {@link CompareAndSwapCompressedOp} case, allocates a number of
-     * scratch registers. The result {@link #operand(ValueNode) operand} for {@code node} complies
-     * with the API for {@link Unsafe#compareAndSwapInt(Object, long, int, int)}.
-     *
-     * @param address the memory location targeted by the operation
-     */
-    @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        Kind kind = node.getNewValue().getKind();
-        assert kind == node.getExpectedValue().getKind();
-        Variable expected = gen.load(operand(node.getExpectedValue()));
-        Variable newValue = gen.load(operand(node.getNewValue()));
-        HSAILAddressValue addressValue = getGen().asAddressValue(address);
-        Variable casResult = newVariable(kind);
-        if (getGen().config.useCompressedOops && node.isCompressible()) {
-            // make 64-bit scratch variables for expected and new
-            Variable scratchExpected64 = newVariable(Kind.Long);
-            Variable scratchNewValue64 = newVariable(Kind.Long);
-            // make 32-bit scratch variables for expected and new and result
-            Variable scratchExpected32 = newVariable(Kind.Int);
-            Variable scratchNewValue32 = newVariable(Kind.Int);
-            Variable scratchCasResult32 = newVariable(Kind.Int);
-            append(new CompareAndSwapCompressedOp(casResult, addressValue, expected, newValue, scratchExpected64, scratchNewValue64, scratchExpected32, scratchNewValue32, scratchCasResult32,
-                            getGen().getNarrowOopBase(), getGen().getNarrowOopShift(), getGen().getLogMinObjectAlignment()));
-        } else {
-            append(new CompareAndSwapOp(casResult, addressValue, expected, newValue));
-        }
-        Variable nodeResult = newVariable(node.getKind());
-        append(new CondMoveOp(HSAILLIRGenerator.mapKindToCompareOp(kind), casResult, expected, nodeResult, Condition.EQ, Constant.INT_1, Constant.INT_0));
-        setResult(node, nodeResult);
-    }
-
     @Override
     protected void emitNode(ValueNode node) {
         if (node instanceof CurrentJavaThreadNode) {
@@ -97,14 +57,75 @@
         }
     }
 
+    private HSAILHotSpotLIRGenerator getGen() {
+        return (HSAILHotSpotLIRGenerator) gen;
+    }
+
     /**
      * @return a compressed version of the incoming constant lifted from AMD64HotSpotLIRGenerator
      */
     protected static Constant compress(Constant c, CompressEncoding encoding) {
         if (c.getKind() == Kind.Long) {
-            return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
+            int compressedValue = (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL);
+            if (c instanceof HotSpotMetaspaceConstant) {
+                return HotSpotMetaspaceConstant.forMetaspaceObject(Kind.Int, compressedValue, HotSpotMetaspaceConstant.getMetaspaceObject(c));
+            } else {
+                return Constant.forIntegerKind(Kind.Int, compressedValue);
+            }
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
     }
+
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        Kind kind = x.newValue().getKind();
+        assert kind == x.expectedValue().getKind();
+
+        Variable expected = getGen().load(operand(x.expectedValue()));
+        Variable newVal = getGen().load(operand(x.newValue()));
+
+        int disp = 0;
+        HSAILAddressValue address;
+        Value index = operand(x.offset());
+        if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) {
+            assert !getGen().getCodeCache().needsDataPatch(ValueUtil.asConstant(index));
+            disp += (int) ValueUtil.asConstant(index).asLong();
+            address = new HSAILAddressValue(kind, getGen().load(operand(x.object())), disp);
+        } else {
+            throw GraalInternalError.shouldNotReachHere("NYI");
+        }
+
+        Variable casResult = newVariable(kind);
+        append(new CompareAndSwapOp(kind, casResult, address, expected, newVal));
+
+        setResult(x, casResult);
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        HotSpotVMConfig config = getGen().config;
+        if (config.useHSAILSafepoints == true) {
+            LIRFrameState info = state(i);
+            HSAILHotSpotSafepointOp safepoint = new HSAILHotSpotSafepointOp(info, config, this);
+            ((HSAILHotSpotLIRGenerationResult) getGen().getResult()).addDeopt(safepoint);
+            append(safepoint);
+        } else {
+            Debug.log("HSAIL safepoints turned off");
+        }
+    }
+
+    @Override
+    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
+        // nop
+    }
+
+    @Override
+    public void emitPatchReturnAddress(ValueNode address) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
+        throw GraalInternalError.unimplemented();
+    }
 }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,7 +28,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hsail.*;
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
@@ -41,8 +42,8 @@
     private final Replacements host;
     private HashSet<ResolvedJavaMethod> ignoredResolvedMethods = new HashSet<>();
 
-    public HSAILHotSpotReplacementsImpl(Providers providers, Assumptions assumptions, TargetDescription target, Replacements host) {
-        super(providers, assumptions, target);
+    public HSAILHotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, Assumptions assumptions, TargetDescription target, Replacements host) {
+        super(providers, snippetReflection, assumptions, target);
         this.host = host;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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.hotspot.hsail;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.hsail.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hsail.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Emits a safepoint deoptimization from HSA back to CPU.
+ */
+@Opcode("SAFEPOINT")
+public class HSAILHotSpotSafepointOp extends HSAILLIRInstruction implements HSAILControlFlow.DeoptimizingOp {
+    private Constant actionAndReason;
+    @State protected LIRFrameState frameState;
+    protected int codeBufferPos = -1;
+    protected int dregOopMap = 0;
+    final int offsetToNoticeSafepoints;
+
+    public HSAILHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRBuilderTool tool) {
+        actionAndReason = tool.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(DeoptimizationAction.None, DeoptimizationReason.None, 0);
+        frameState = state;
+        offsetToNoticeSafepoints = config.hsailNoticeSafepointsOffset;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+
+        // get a unique codeBuffer position
+        // when we save our state, we will save this as well (it can be used as a key to get the
+        // debugInfo)
+        codeBufferPos = masm.position();
+
+        masm.emitComment(" /* HSAIL safepoint bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */");
+        String afterSafepointLabel = "@LAfterSafepoint_at_pos_" + codeBufferPos;
+
+        AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object);
+        AllocatableValue spAddrReg = HSAIL.d17.asValue(Kind.Object);
+        AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int);
+        masm.emitLoadKernelArg(scratch64, masm.getDeoptInfoName(), "u64");
+
+        // Build address of noticeSafepoints field
+        HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(Kind.Object, scratch64, offsetToNoticeSafepoints).toAddress();
+        masm.emitLoad(Kind.Object, spAddrReg, noticeSafepointsAddr);
+
+        // Load int value from that field
+        HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(Kind.Int, spAddrReg, 0).toAddress();
+        masm.emitLoadAcquire(scratch32, noticeSafepointsIntAddr);
+        masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false);
+        masm.cbr(afterSafepointLabel);
+
+        BytecodeFrame frame = frameState.debugInfo().frame();
+        for (int i = 0; i < frame.numLocals + frame.numStack; i++) {
+            Value val = frame.values[i];
+            if (isLegal(val) && isRegister(val)) {
+                Register reg = asRegister(val);
+                if (val.getKind() == Kind.Object) {
+                    dregOopMap |= 1 << (reg.encoding());
+                }
+            }
+        }
+
+        AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
+        AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
+        AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int);
+        masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason);
+        masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
+        masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap));
+        masm.emitJumpToLabelName(masm.getDeoptLabelName());
+
+        masm.emitString0(afterSafepointLabel + ":\n");
+
+        // now record the debuginfo
+        crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.SAFEPOINT);
+    }
+
+    public LIRFrameState getFrameState() {
+        return frameState;
+    }
+
+    public int getCodeBufferPos() {
+        return codeBufferPos;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 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.hsail.replacements;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.replacements.Snippet.Fold;
+import com.oracle.graal.word.*;
+import com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil;
+import com.oracle.graal.hotspot.meta.*;
+
+//JaCoCo Exclude
+
+/**
+ * A collection of methods used in HSAIL-specific snippets and substitutions.
+ */
+public class HSAILHotSpotReplacementsUtil extends HotSpotReplacementsUtil {
+
+    private static HotSpotRegistersProvider hsailRegisters;
+
+    public static void initialize(HotSpotRegistersProvider registers) {
+        hsailRegisters = registers;
+    }
+
+    /**
+     * Gets the value of the thread register as a Word.
+     */
+    public static Word thread() {
+        return registerAsWord(threadRegister(), true, false);
+    }
+
+    @Fold
+    public static Register threadRegister() {
+        return hsailRegisters.getThreadRegister();
+    }
+
+    public static Word atomicGetAndAddTlabTop(Word thread, int size) {
+        return Word.unsigned(AtomicReadAndAddNode.getAndAddLong(null, thread.rawValue() + threadTlabTopOffset(), size, TLAB_TOP_LOCATION));
+    }
+
+    public static final LocationIdentity TLAB_PFTOP_LOCATION = new NamedLocationIdentity("TlabPfTop");
+
+    @Fold
+    public static int threadTlabPfTopOffset() {
+        return config().threadTlabPfTopOffset();
+    }
+
+    public static void writeTlabPfTop(Word thread, Word val) {
+        thread.writeWord(threadTlabPfTopOffset(), val, TLAB_PFTOP_LOCATION);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.hsail.replacements;
+
+import static com.oracle.graal.api.code.UnsignedMath.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.hotspot.hsail.replacements.HSAILHotSpotReplacementsUtil.*;
+import static com.oracle.graal.hotspot.hsail.replacements.HSAILNewObjectSnippets.Options.*;
+import static com.oracle.graal.nodes.PiArrayNode.*;
+import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
+import static com.oracle.graal.replacements.SnippetTemplate.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.options.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.word.*;
+
+/**
+ * HSAIL-specific Snippets used for implementing NEW and NEWARRAY.
+ */
+public class HSAILNewObjectSnippets extends NewObjectSnippets {
+
+    static public class Options {
+
+        // @formatter:off
+        @Option(help = "In HSAIL allocation, allow allocation from eden as fallback if TLAB is full")
+        static final OptionValue<Boolean> HsailUseEdenAllocate = new OptionValue<>(false);
+
+        @Option(help = "Estimate of number of bytes allocated by each HSAIL workitem, used to size TLABs")
+        static public final OptionValue<Integer> HsailAllocBytesPerWorkitem = new OptionValue<>(64);
+
+        // @formatter:on
+    }
+
+    private static final boolean hsailUseEdenAllocate = HsailUseEdenAllocate.getValue();
+
+    @Snippet
+    public static Object allocateInstanceAtomic(@ConstantParameter int size, Word hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, @ConstantParameter String typeContext) {
+        Word thread = thread();
+        boolean haveResult = false;
+        if (useTLAB()) {
+            Word top = atomicGetAndAddTlabTop(thread, size);
+            Word end = readTlabEnd(thread);
+            Word newTop = top.add(size);
+            if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
+                // writeTlabTop(thread, newTop) was done by the atomicGetAndAdd
+                Object result = formatObject(hub, size, top, prototypeMarkWord, fillContents, true, false, true);
+                profileAllocation("instance", size, typeContext);
+                return piCast(verifyOop(result), StampFactory.forNodeIntrinsic());
+            } else {
+                // only one overflower will be the first overflower, detectable because
+                // oldtop was still below end
+                if (top.belowOrEqual(end)) {
+                    // hack alert: store the last good top before overflow into pf_top
+                    // we will move it back into top later when back in the VM
+                    writeTlabPfTop(thread, top);
+                }
+                // useless logic but see notes on deopt path below
+                haveResult = newTop.belowOrEqual(end);
+            }
+        }
+        if (hsailUseEdenAllocate) {
+            // originally:
+            // result = NewInstanceStubCall.call(hub);
+
+            // we could not allocate from tlab, try allocating directly from eden
+            // false for no logging
+            Word memory = NewInstanceStub.edenAllocate(Word.unsigned(size), false);
+            if (memory.notEqual(0)) {
+                new_eden.inc();
+                Object result = formatObject(hub, size, memory, prototypeMarkWord, fillContents, true, false, true);
+                profileAllocation("instance", size, typeContext);
+                return piCast(verifyOop(result), StampFactory.forNodeIntrinsic());
+            }
+        }
+        // haveResult test here helps avoid dropping earlier stores were seen to be dropped without
+        // this.
+        if (!haveResult) {
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        // will never get here but this keeps the compiler happy
+        return Word.zero().toObject();
+    }
+
+    @Snippet
+    public static Object allocateArrayAtomic(Word hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
+                    @ConstantParameter boolean fillContents, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) {
+        if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
+            // This handles both negative array sizes and very large array sizes
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        return allocateArrayAtomicImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, maybeUnroll, typeContext);
+    }
+
+    private static Object allocateArrayAtomicImpl(Word hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, boolean maybeUnroll, String typeContext) {
+        int alignment = wordSize();
+        int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize);
+        Word thread = thread();
+        boolean haveResult = false;
+        if (useTLAB()) {
+            Word top = atomicGetAndAddTlabTop(thread, allocationSize);
+            Word end = readTlabEnd(thread);
+            Word newTop = top.add(allocationSize);
+            if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
+                // writeTlabTop(thread, newTop) was done by the atomicGetAndAdd
+                newarray_loopInit.inc();
+                // we are not in a stub so we can set useSnippetCounters to true
+                Object result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, true);
+                profileAllocation("array", allocationSize, typeContext);
+                return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
+            } else {
+                // only one overflower will be the first overflower, detectable because
+                // oldtop was still below end
+                if (top.belowOrEqual(end)) {
+                    // hack alert: store the last good top before overflow into pf_top
+                    // we will move it back into top later when back in the VM
+                    writeTlabPfTop(thread, top);
+                }
+                // useless logic but see notes on deopt path below
+                haveResult = newTop.belowOrEqual(end);
+            }
+        }
+        // we could not allocate from tlab, try allocating directly from eden
+        if (hsailUseEdenAllocate) {
+            // false for no logging
+            Word memory = NewInstanceStub.edenAllocate(Word.unsigned(allocationSize), false);
+            if (memory.notEqual(0)) {
+                newarray_eden.inc();
+                // we are not in a stub so we can set useSnippetCounters to true
+                Object result = formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents, maybeUnroll, true);
+                profileAllocation("array", allocationSize, typeContext);
+                return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
+            }
+        }
+        if (!haveResult) {
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        // will never get here but this keeps the compiler happy
+        return Word.zero().toObject();
+    }
+
+    public static class Templates extends AbstractTemplates {
+
+        private final SnippetInfo allocateInstance = snippet(HSAILNewObjectSnippets.class, "allocateInstanceAtomic");
+        private final SnippetInfo allocateArray = snippet(HSAILNewObjectSnippets.class, "allocateArrayAtomic");
+
+        // private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class,
+        // "allocateArrayDynamic");
+        // private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class,
+        // "newmultiarray");
+
+        public Templates(HotSpotProviders providers, TargetDescription target) {
+            super(providers, providers.getSnippetReflection(), target);
+        }
+
+        /**
+         * Lowers a {@link NewInstanceNode}.
+         */
+        public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) {
+            StructuredGraph graph = newInstanceNode.graph();
+            HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newInstanceNode.instanceClass();
+            assert !type.isArray();
+            ConstantNode hub = ConstantNode.forConstant(type.klass(), providers.getMetaAccess(), graph);
+            int size = instanceSize(type);
+
+            Arguments args = new Arguments(allocateInstance, graph.getGuardsStage(), tool.getLoweringStage());
+            args.addConst("size", size);
+            args.add("hub", hub);
+            args.add("prototypeMarkWord", type.prototypeMarkWord());
+            args.addConst("fillContents", newInstanceNode.fillContents());
+            args.addConst("typeContext", MetaUtil.toJavaName(type, false));
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args);
+            template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args);
+        }
+
+        /**
+         * Lowers a {@link NewArrayNode}.
+         */
+        public void lower(NewArrayNode newArrayNode, LoweringTool tool) {
+            StructuredGraph graph = newArrayNode.graph();
+            ResolvedJavaType elementType = newArrayNode.elementType();
+            HotSpotResolvedObjectType arrayType = (HotSpotResolvedObjectType) elementType.getArrayClass();
+            Kind elementKind = elementType.getKind();
+            ConstantNode hub = ConstantNode.forConstant(arrayType.klass(), providers.getMetaAccess(), graph);
+            final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind);
+            // lowerer extends HotSpotLoweringProvider so we can just use that
+            HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
+            int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind));
+
+            Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage());
+            args.add("hub", hub);
+            args.add("length", newArrayNode.length());
+            args.add("prototypeMarkWord", arrayType.prototypeMarkWord());
+            args.addConst("headerSize", headerSize);
+            args.addConst("log2ElementSize", log2ElementSize);
+            args.addConst("fillContents", newArrayNode.fillContents());
+            args.addConst("maybeUnroll", newArrayNode.length().isConstant());
+            args.addConst("typeContext", MetaUtil.toJavaName(arrayType, false));
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
+            template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
+        }
+
+        private static int instanceSize(HotSpotResolvedObjectType type) {
+            int size = type.instanceSize();
+            assert (size % wordSize()) == 0;
+            assert size >= 0;
+            return size;
+        }
+    }
+
+    private static final SnippetCounter.Group countersNew = SnippetCounters.getValue() ? new SnippetCounter.Group("NewInstance") : null;
+    private static final SnippetCounter new_eden = new SnippetCounter(countersNew, "eden", "used edenAllocate");
+
+    private static final SnippetCounter.Group countersNewArray = SnippetCounters.getValue() ? new SnippetCounter.Group("NewArray") : null;
+    private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop");
+    private static final SnippetCounter newarray_eden = new SnippetCounter(countersNewArray, "eden", "used edenAllocate");
+}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Wed Apr 23 15:48:38 2014 +0200
@@ -36,11 +36,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.gpu.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
@@ -49,10 +50,11 @@
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.ptx.*;
+import com.oracle.graal.lir.ptx.PTXControlFlow.PTXPredicatedLIRInstruction;
 import com.oracle.graal.lir.ptx.PTXMemOp.LoadReturnAddrOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -339,7 +341,7 @@
         Assembler masm = createAssembler(frameMap);
         PTXFrameContext frameContext = new PTXFrameContext();
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
-        crb.setFrameSize(0);
+        crb.setTotalFrameSize(0);
         return crb;
     }
 
@@ -409,12 +411,20 @@
         assert codeCacheOwner != null : lir + " is not associated with a method";
 
         RegisterAnalysis registerAnalysis = new RegisterAnalysis();
+        // Assume no predicate registers are used
+        int maxPredRegNum = -1;
 
         for (AbstractBlock<?> b : lir.codeEmittingOrder()) {
             for (LIRInstruction op : lir.getLIRforBlock(b)) {
                 if (op instanceof LabelOp) {
                     // Don't consider this as a definition
                 } else {
+                    if (op instanceof PTXPredicatedLIRInstruction) {
+                        // Update maximum predicate register number if op uses a larger number
+                        int opPredRegNum = ((PTXPredicatedLIRInstruction) op).getPredRegNum();
+                        maxPredRegNum = (opPredRegNum > maxPredRegNum) ? opPredRegNum : maxPredRegNum;
+                    }
+                    // Record registers used in the kernel
                     registerAnalysis.op = op;
                     op.forEachTemp(registerAnalysis);
                     op.forEachOutput(registerAnalysis);
@@ -422,13 +432,13 @@
             }
         }
 
+        // Emit register declarations
         Assembler asm = crb.asm;
         registerAnalysis.emitDeclarations(asm);
 
         // emit predicate register declaration
-        int maxPredRegNum = lir.numVariables();
-        if (maxPredRegNum > 0) {
-            asm.emitString(".reg .pred %p<" + maxPredRegNum + ">;");
+        if (maxPredRegNum > -1) {
+            asm.emitString(".reg .pred %p<" + ++maxPredRegNum + ">;");
         }
     }
 
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -47,7 +47,7 @@
         HotSpotDisassemblerProvider disassembler = host.getDisassembler();
         SuitesProvider suites = new DefaultSuitesProvider();
         HotSpotRegistersProvider registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None);
-        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
+        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection());
         return new PTXHotSpotBackend(runtime, providers);
     }
 
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.meta.*;
 
 public class PTXHotSpotForeignCallsProvider implements HotSpotForeignCallsProvider {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,12 +25,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.ptx.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.gen.*;
 
 /**
  * LIR generator specialized for PTX HotSpot.
@@ -59,13 +60,43 @@
         throw GraalInternalError.unimplemented();
     }
 
-    public Value emitCompress(Value pointer, CompressEncoding encoding) {
+    @Override
+    public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
+        // TODO
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
         // TODO
         throw GraalInternalError.unimplemented();
     }
 
-    public Value emitUncompress(Value pointer, CompressEncoding encoding) {
-        // TODO
+    public void emitLeaveCurrentStackFrame() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitLeaveUnpackFramesStackFrame() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public SaveRegistersOp emitSaveAllRegisters() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
         throw GraalInternalError.unimplemented();
     }
 }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.ptx;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 
 package com.oracle.graal.hotspot.ptx;
 
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.ptx.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 
 public class PTXHotSpotRegisterConfig implements RegisterConfig {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,13 +31,12 @@
 import static com.oracle.graal.hotspot.ptx.PTXWrapperBuilder.LaunchArg.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
-import static java.lang.reflect.Modifier.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.java.*;
@@ -47,7 +46,6 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
@@ -61,8 +59,8 @@
  * <li>PINNED: a buffer into which the address of pinned objects is saved.</li>
  * <li>OBJECT_OFFSETS: the offsets of the object values in PARAMS.</li>
  * </ul>
- * 
- * 
+ *
+ *
  * The PARAMS buffer is the {@code CU_LAUNCH_PARAM_BUFFER_POINTER} buffer passed in the
  * {@code extra} argument to the {@code cuLaunchKernel} function. This buffer contains the
  * parameters to the call. The buffer is word aligned and each parameter is aligned in the buffer
@@ -74,13 +72,13 @@
  * The object pointers in PARAMS are specified by OBJECT_OFFSETS.
  * <p>
  * As a concrete example, for a kernel whose Java method signature is:
- * 
+ *
  * <pre>
  *     static int kernel(int p1, short p2, Object p3, long p4)
  * </pre>
- * 
+ *
  * the graph created is shown below as psuedo-code:
- * 
+ *
  * <pre>
  *     int kernel_wrapper(int p1, short p2, oop p3, long p4) {
  *         address kernelAddr = kernel.start;
@@ -121,7 +119,7 @@
     /**
      * The size of the buffer holding the kernel parameters and the extra word for storing the
      * pointer to device memory for the return value.
-     * 
+     *
      * @see LaunchArg#ParametersAndReturnValueBufferSize
      */
     int bufSize;
@@ -152,7 +150,7 @@
 
     /**
      * Creates the graph implementing the CPU to GPU transition.
-     * 
+     *
      * @param method a method that has been compiled to GPU binary code
      * @param kernel the installed GPU binary for {@code method}
      * @see PTXWrapperBuilder
@@ -163,7 +161,7 @@
         int intSize = Integer.SIZE / Byte.SIZE;
         Kind wordKind = providers.getCodeCache().getTarget().wordKind;
         Signature sig = method.getSignature();
-        boolean isStatic = isStatic(method.getModifiers());
+        boolean isStatic = method.isStatic();
         int sigCount = sig.getParameterCount(false);
         javaParameters = new ParameterNode[(!isStatic ? 1 : 0) + sigCount];
         javaParameterOffsetsInKernelParametersBuffer = new int[javaParameters.length];
@@ -192,7 +190,7 @@
             }
         }
 
-        InvokeNode kernelStart = createInvoke(getClass(), "getKernelStart", ConstantNode.forObject(kernel, providers.getMetaAccess(), getGraph()));
+        InvokeNode kernelStart = createInvoke(getClass(), "getKernelStart", ConstantNode.forConstant(HotSpotObjectConstant.forObject(kernel), providers.getMetaAccess(), getGraph()));
 
         AllocaNode buf = append(new AllocaNode(bufSize / wordSize, new BitSet()));
         ValueNode objectParametersOffsets;
@@ -290,8 +288,8 @@
             Debug.dump(getGraph(), "Initial kernel launch graph");
         }
 
-        rewriteWordTypes();
-        inlineInvokes();
+        rewriteWordTypes(providers.getSnippetReflection());
+        inlineInvokes(providers.getSnippetReflection());
 
         if (Debug.isDumpEnabled()) {
             Debug.dump(getGraph(), "Kernel launch graph before compilation");
@@ -300,7 +298,7 @@
 
     /**
      * Computes offset and size of space in PARAMS for a Java parameter.
-     * 
+     *
      * @param kind the kind of the parameter
      * @param javaParametersIndex the index of the Java parameter
      */
--- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/ReplacingStreams.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/ReplacingStreams.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.logging.*;
+import com.oracle.graal.hotspot.meta.*;
 
 public class ReplacingStreams {
 
@@ -172,7 +173,7 @@
                 if (constant.getKind() != Kind.Object) {
                     return obj;
                 }
-                Object contents = constant.asObject();
+                Object contents = HotSpotObjectConstant.asObject(constant);
                 if (contents == null) {
                     return obj;
                 }
@@ -182,12 +183,12 @@
                 }
                 placeholder = objectMap.get(contents);
                 if (placeholder != null) {
-                    return Constant.forObject(placeholder);
+                    return HotSpotObjectConstant.forObject(placeholder);
                 }
                 if (contents instanceof Remote) {
-                    return Constant.forObject(createRemoteCallPlaceholder(contents));
+                    return HotSpotObjectConstant.forObject(createRemoteCallPlaceholder(contents));
                 }
-                return Constant.forObject(createDummyPlaceholder(contents));
+                return HotSpotObjectConstant.forObject(createDummyPlaceholder(contents));
             }
             return obj;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.*;
+
+final class SPARCDeoptimizationStub extends DeoptimizationStub {
+
+    private RegisterConfig registerConfig;
+
+    public SPARCDeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
+        super(providers, target, linkage);
+        registerConfig = new SPARCHotSpotRegisterConfig(target, new Register[]{o0, o1, o2, o3, o4, o5, o7, l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, f0, f1, f2, f3, f4, f5, f6, f7});
+    }
+
+    @Override
+    public RegisterConfig getRegisterConfig() {
+        return registerConfig;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -49,6 +49,6 @@
         // [Deopt Handler Code]
         // 0xffffffff749bb60c: call 0xffffffff748da540 ; {runtime_call}
         // 0xffffffff749bb610: nop
-        SPARCCall.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP), null, false, info);
+        SPARCCall.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, false, info);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,10 +24,8 @@
 
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.sparc.SPARC.*;
-import static java.lang.reflect.Modifier.*;
-
 import java.util.*;
 
 import sun.misc.*;
@@ -45,8 +43,8 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Nop;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.RestoreWindow;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.hotspot.meta.*;
@@ -54,6 +52,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.*;
 
@@ -174,7 +173,7 @@
         // On SPARC we always use stack frames.
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
         CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, frameContext, compilationResult);
-        crb.setFrameSize(frameMap.frameSize());
+        crb.setTotalFrameSize(frameMap.totalFrameSize());
         StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
         if (deoptimizationRescueSlot != null && stub == null) {
             crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
@@ -201,7 +200,7 @@
         FrameMap frameMap = crb.frameMap;
         RegisterConfig regConfig = frameMap.registerConfig;
         HotSpotVMConfig config = getRuntime().getConfig();
-        Label unverifiedStub = installedCodeOwner == null || isStatic(installedCodeOwner.getModifiers()) ? null : new Label();
+        Label unverifiedStub = installedCodeOwner == null || installedCodeOwner.isStatic() ? null : new Label();
 
         // Emit the prefix
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -60,10 +60,11 @@
         // to be valid for the entire run of the VM.
         Assumptions assumptions = new Assumptions(false);
         Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null);
-        HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, runtime.getConfig(), assumptions, target);
+        HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider();
+        HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), assumptions, target);
         HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime);
         HotSpotSuitesProvider suites = new HotSpotSuitesProvider(runtime);
-        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
+        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection);
 
         return new SPARCHotSpotBackend(runtime, providers);
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -47,7 +47,7 @@
         // HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub);
         // frameContext.enter(crb);
         Register scratch = g3;
-        SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP));
+        SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER));
 
         // frameContext.leave(crb);
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -46,7 +46,8 @@
 
     @Override
     public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
-        Kind word = providers.getCodeCache().getTarget().wordKind;
+        TargetDescription target = providers.getCodeCache().getTarget();
+        Kind word = target.wordKind;
 
         // The calling convention for the exception handler stub is (only?) defined in
         // TemplateInterpreterGenerator::generate_throw_exception()
@@ -60,6 +61,8 @@
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
 
+        link(new SPARCDeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
+
         super.initialize(providers, config);
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.hotspot.sparc;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.gen.*;
 
 public interface SPARCHotSpotLIRGenerationResult extends LIRGenerationResult {
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,24 +27,25 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.sparc.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreOp;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
 public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator {
 
     final HotSpotVMConfig config;
+    private HotSpotLockStack lockStack;
 
     public SPARCHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
         super(providers, cc, lirGenRes);
@@ -65,11 +66,21 @@
 
     @Override
     public StackSlot getLockSlot(int lockDepth) {
-        return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth);
+        return getLockStack().makeLockSlot(lockDepth);
+    }
+
+    private HotSpotLockStack getLockStack() {
+        assert lockStack != null;
+        return lockStack;
+    }
+
+    protected void setLockStack(HotSpotLockStack lockStack) {
+        assert this.lockStack == null;
+        this.lockStack = lockStack;
     }
 
     @Override
-    protected boolean needOnlyOopMaps() {
+    public boolean needOnlyOopMaps() {
         // Stubs only need oop maps
         return getStub() != null;
     }
@@ -79,12 +90,13 @@
     }
 
     @Override
-    public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
+    public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) {
         HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
         Variable result;
-        DeoptimizingNode deoptInfo = null;
+        // TODO (je) check if this can be removed
+        LIRFrameState deoptInfo = null;
         if (hotspotLinkage.canDeoptimize()) {
-            deoptInfo = info;
+            deoptInfo = state;
             assert deoptInfo != null || getStub() != null;
         }
 
@@ -141,9 +153,9 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) {
         moveDeoptValuesToThread(actionAndReason, speculation);
-        append(new SPARCDeoptimizeOp(state(deopting)));
+        append(new SPARCDeoptimizeOp(state));
     }
 
     @Override
@@ -157,14 +169,10 @@
     }
 
     @Override
-    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) {
         SPARCAddressValue loadAddress = asAddressValue(address);
         Variable result = newVariable(kind);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
-        if (isCompressCandidate(access)) {
+        if (isCompressCandidate(null)) {
             if (config.useCompressedOops && kind == Kind.Object) {
                 // append(new LoadCompressedPointer(kind, result, loadAddress, access != null ?
                 // state(access) :
@@ -187,19 +195,15 @@
     }
 
     @Override
-    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) {
         SPARCAddressValue storeAddress = asAddressValue(address);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
-            if (canStoreConstant(c, isCompressCandidate(access))) {
+            if (canStoreConstant(c, isCompressCandidate(null))) {
                 if (inputVal.getKind() == Kind.Object) {
-                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(access)));
+                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(null)));
                 } else if (inputVal.getKind() == Kind.Long) {
-                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(access)));
+                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(null)));
                 } else {
                     append(new StoreConstantOp((Kind) kind, storeAddress, c, state, false));
                 }
@@ -207,7 +211,7 @@
             }
         }
         Variable input = load(inputVal);
-        if (isCompressCandidate(access)) {
+        if (isCompressCandidate(null)) {
             if (config.useCompressedOops && kind == Kind.Object) {
                 // if (input.getKind() == Kind.Object) {
                 // Variable scratch = newVariable(Kind.Long);
@@ -233,6 +237,11 @@
         }
     }
 
+    public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
+    }
+
     @Override
     public Value emitNot(Value input) {
         GraalInternalError.shouldNotReachHere("binary negation not implemented");
@@ -243,13 +252,50 @@
         return deoptimizationRescueSlot;
     }
 
-    public Value emitCompress(Value pointer, CompressEncoding encoding) {
+    @Override
+    public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
+        // TODO
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
         // TODO
         throw GraalInternalError.unimplemented();
     }
 
-    public Value emitUncompress(Value pointer, CompressEncoding encoding) {
-        // TODO
+    public SaveRegistersOp emitSaveAllRegisters() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitLeaveCurrentStackFrame() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitLeaveUnpackFramesStackFrame() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
+    }
+
+    public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
+        // TODO Auto-generated method stub
         throw GraalInternalError.unimplemented();
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,8 +26,6 @@
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
@@ -37,6 +35,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp;
 import com.oracle.graal.nodes.*;
@@ -46,6 +45,9 @@
 
     public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) {
         super(graph, lirGen);
+        assert gen instanceof SPARCHotSpotLIRGenerator;
+        assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder;
+        ((SPARCHotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
     }
 
     @Override
@@ -60,7 +62,7 @@
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
-        LIRFrameState info = gen.state(i);
+        LIRFrameState info = state(i);
         append(new SPARCHotSpotSafepointOp(info, getGen().config, gen));
     }
 
@@ -100,9 +102,8 @@
         } else {
             assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
             HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
-            assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method.";
-            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
-            append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
+            assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method.";
+            append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import java.util.*;
@@ -30,7 +30,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.sparc.*;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -33,8 +33,8 @@
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.nodes.spi.*;
 
 /**
  * Emits a safepoint poll.
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,44 +22,32 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import static com.oracle.graal.sparc.SPARC.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp;
-import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
- * A direct call that complies with the conventions for such calls in HotSpot. In particular, for
- * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call.
+ * A direct call that complies with the conventions for such calls in HotSpot. It doesn't use an
+ * inline cache so it's just a patchable call site.
  */
 @Opcode("CALL_DIRECT")
 final class SPARCHotspotDirectStaticCallOp extends DirectCallOp {
 
-    private final Constant metaspaceMethod;
     private final InvokeKind invokeKind;
 
-    SPARCHotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, Constant metaspaceMethod) {
+    SPARCHotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) {
         super(target, result, parameters, temps, state);
         assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
-        this.metaspaceMethod = metaspaceMethod;
         this.invokeKind = invokeKind;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-        // The mark for an invocation that uses an inline cache must be placed at the
-        // instruction that loads the Klass from the inline cache.
-        SPARCMove.move(crb, masm, g5.asValue(Kind.Long), metaspaceMethod);
         MarkId.recordMark(crb, invokeKind == InvokeKind.Static ? MarkId.INVOKESTATIC : MarkId.INVOKESPECIAL);
-        // SPARCMove.move(crb, masm, g3.asValue(Kind.Long), Constant.LONG_0);
-        new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, g3, true).emit(masm);
         super.emitCode(crb, masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,8 +24,8 @@
 
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import org.junit.*;
 
@@ -81,7 +81,7 @@
         assertEquals(0, result.getNodes().filter(ReadNode.class).count());
     }
 
-    public static Class getClassObject() {
+    public static Class<AheadOfTimeCompilationTest> getClassObject() {
         return AheadOfTimeCompilationTest.class;
     }
 
@@ -104,7 +104,7 @@
 
         NodeIterable<ConstantNode> filter = getConstantNodes(result);
         assertEquals(1, filter.count());
-        Object mirror = filter.first().asConstant().asObject();
+        Object mirror = HotSpotObjectConstant.asObject(filter.first().asConstant());
         assertEquals(Class.class, mirror.getClass());
         assertEquals(AheadOfTimeCompilationTest.class, mirror);
 
@@ -112,7 +112,7 @@
         assertEquals(0, result.getNodes().filter(ReadNode.class).count());
     }
 
-    public static Class getPrimitiveClassObject() {
+    public static Class<Integer> getPrimitiveClassObject() {
         return int.class;
     }
 
@@ -132,7 +132,7 @@
         StructuredGraph result = compile("getPrimitiveClassObject", false);
         NodeIterable<ConstantNode> filter = getConstantNodes(result);
         assertEquals(1, filter.count());
-        Object mirror = filter.first().asConstant().asObject();
+        Object mirror = HotSpotObjectConstant.asObject(filter.first().asConstant());
         assertEquals(Class.class, mirror.getClass());
         assertEquals(Integer.TYPE, mirror);
 
@@ -160,7 +160,7 @@
 
         NodeIterable<ConstantNode> filter = getConstantNodes(result);
         assertEquals(1, filter.count());
-        Object mirror = filter.first().asConstant().asObject();
+        Object mirror = HotSpotObjectConstant.asObject(filter.first().asConstant());
         assertEquals(String.class, mirror.getClass());
         assertEquals("test string", mirror);
 
@@ -193,7 +193,7 @@
         assertEquals(1, getConstantNodes(result).count());
         ConstantNode constant = getConstantNodes(result).first();
         assertEquals(Kind.Object, constant.getKind());
-        assertEquals(Boolean.TRUE, constant.asConstant().asObject());
+        assertEquals(Boolean.TRUE, HotSpotObjectConstant.asObject(constant.asConstant()));
     }
 
     private StructuredGraph compile(String test, boolean compileAOT) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.test;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import org.junit.*;
 
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -200,7 +200,7 @@
         while (j < objects.length) {
             if (!installedBenchmarkCode.isValid()) {
                 // This can get invalidated due to lack of MDO update
-                installedBenchmarkCode = getInstalledCode("queueTest");
+                installedBenchmarkCode = getInstalledCode("queueTest", Object.class, Object.class);
             }
             installedBenchmarkCode.executeVarargs(q, objects[j]);
             j++;
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -127,7 +127,7 @@
     }
 
     private static Method lookup(String className, String methodName) {
-        Class c;
+        Class<?> c;
         try {
             c = Class.forName(className);
             for (Method m : c.getDeclaredMethods()) {
@@ -180,7 +180,7 @@
         return result;
     }
 
-    private static byte[] readClassfile16(Class c) throws IOException {
+    private static byte[] readClassfile16(Class<? extends HotSpotCryptoSubstitutionTest> c) throws IOException {
         String classFilePath = "/" + c.getName().replace('.', '/') + ".class";
         InputStream stream = c.getResourceAsStream(classFilePath);
         int bytesToRead = stream.available();
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -74,7 +74,7 @@
         test("getSuperClass");
         test("getComponentType");
 
-        for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) {
+        for (Class<?> c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) {
             assertEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c));
             assertEquals(c.isInterface(), ClassSubstitutions.isInterface(c));
             assertEquals(c.isArray(), ClassSubstitutions.isArray(c));
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -33,8 +33,8 @@
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 
 public class HotSpotMonitorValueTest extends GraalCompilerTest {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeClassSubstitutionsTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.test.*;
+
+/**
+ * Tests HotSpot specific substitutions for {@link NodeClass}.
+ */
+public class HotSpotNodeClassSubstitutionsTest extends MethodSubstitutionTest {
+
+    @Test
+    public void test() {
+        test("get", ValueNode.class);
+    }
+
+    public static NodeClass get(Class<?> c) {
+        return NodeClass.get(c);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.test.*;
+
+/**
+ * Tests HotSpot specific substitutions for {@link Node}.
+ */
+public class HotSpotNodeSubstitutionsTest extends MethodSubstitutionTest {
+
+    @Test
+    public void test() {
+        StructuredGraph graph = new StructuredGraph();
+        test("getNodeClass", ConstantNode.forInt(42, graph));
+    }
+
+    public static NodeClass getNodeClass(Node n) {
+        return n.getNodeClass();
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,6 @@
 
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*;
-import static java.lang.reflect.Modifier.*;
 
 import java.lang.reflect.*;
 
@@ -38,7 +37,7 @@
  */
 public class HotSpotResolvedJavaFieldTest {
 
-    private static final Class[] classesWithInternalFields = {Class.class, ClassLoader.class};
+    private static final Class<?>[] classesWithInternalFields = {Class.class, ClassLoader.class};
 
     /**
      * Tests that {@link HotSpotResolvedJavaField#getModifiers()} only includes the modifiers
@@ -47,7 +46,7 @@
      */
     @Test
     public void testModifiersForInternal() {
-        for (Class c : classesWithInternalFields) {
+        for (Class<?> c : classesWithInternalFields) {
             ResolvedJavaType type = HotSpotResolvedObjectType.fromClass(c);
             for (ResolvedJavaField field : type.getInstanceFields(false)) {
                 if (field.isInternal()) {
@@ -63,7 +62,7 @@
      */
     @Test
     public void testCachingForInternalFields() {
-        for (Class c : classesWithInternalFields) {
+        for (Class<?> c : classesWithInternalFields) {
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
             for (ResolvedJavaField field : type.getInstanceFields(false)) {
                 if (field.isInternal()) {
@@ -79,7 +78,7 @@
     public void testIsInObject() {
         for (Field f : String.class.getDeclaredFields()) {
             HotSpotResolvedJavaField rf = (HotSpotResolvedJavaField) runtime().getHostProviders().getMetaAccess().lookupJavaField(f);
-            Assert.assertEquals(rf.toString(), rf.isInObject("a string"), !isStatic(rf.getModifiers()));
+            Assert.assertEquals(rf.toString(), rf.isInObject("a string"), !rf.isStatic());
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -89,7 +89,7 @@
             assert parameterTypes.length == args.length;
             for (int i = 0; i < argsToBind.length; i++) {
                 ParameterNode param = graph.getParameter(i);
-                Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]);
+                Constant c = HotSpotObjectConstant.forBoxedValue(parameterTypes[i].getKind(), argsToBind[i]);
                 ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph);
                 param.replaceAtUsages(replacement);
             }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -187,7 +187,7 @@
      */
     @Test
     public void test8() throws Exception {
-        test2("testUnsafeLoad", wr, new Long(32), null);
+        test2("testUnsafeLoad", wr, new Long(useCompressedOops() ? 20 : 32), null);
     }
 
     /**
@@ -207,7 +207,7 @@
      */
     @Test
     public void test9() throws Exception {
-        test2("testUnsafeLoad", wr, new Long(16), new Integer(16));
+        test2("testUnsafeLoad", wr, new Long(useCompressedOops() ? 10 : 16), new Integer(useCompressedOops() ? 10 : 16));
     }
 
     static Object[] src = new Object[1];
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -685,7 +685,7 @@
                 }
 
                 @Override
-                protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
+                protected Boolean afterSplit(BeginNode node, Boolean oldState) {
                     return false;
                 }
             };
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,14 +25,13 @@
 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.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.phases.common.InliningUtil.*;
 
 import java.io.*;
 import java.lang.management.*;
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
@@ -42,6 +41,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.baseline.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
@@ -57,9 +57,7 @@
 
 import edu.umd.cs.findbugs.annotations.*;
 
-public class CompilationTask implements Runnable, Comparable {
-
-    private static final long TIMESTAMP_START = System.currentTimeMillis();
+public class CompilationTask implements Runnable, Comparable<Object> {
 
     // Keep static finals in a group with withinEnqueue as the last one. CompilationTask can be
     // called from within it's own clinit so it needs to be careful about accessing state. Once
@@ -314,7 +312,7 @@
             }
 
             try (TimerCloseable b = CodeInstallationTime.start()) {
-                installedCode = installMethod(result);
+                installedCode = (HotSpotInstalledCode) installMethod(result);
                 if (!isOSR) {
                     ProfilingInfo profile = method.getProfilingInfo();
                     profile.setCompilerIRSize(StructuredGraph.class, graph.getNodeCount());
@@ -365,31 +363,30 @@
      */
     private void printCompilation() {
         final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI;
-        final int mod = method.getModifiers();
         String compilerName = "";
         if (HotSpotCIPrintCompilerName.getValue()) {
             compilerName = "Graal:";
         }
         HotSpotVMConfig config = backend.getRuntime().getConfig();
         int compLevel = config.compilationLevelFullOptimization;
-        char compLevelChar;
+        String compLevelString;
         if (config.tieredCompilation) {
-            compLevelChar = '-';
+            compLevelString = "- ";
             if (compLevel != -1) {
-                compLevelChar = (char) ('0' + compLevel);
+                compLevelString = (char) ('0' + compLevel) + " ";
             }
         } else {
-            compLevelChar = ' ';
+            compLevelString = "";
         }
         boolean hasExceptionHandlers = method.getExceptionHandlers().length > 0;
-        TTY.println(String.format("%s%7d %4d %c%c%c%c%c%c      %s %s(%d bytes)", compilerName, (System.currentTimeMillis() - TIMESTAMP_START), id, isOSR ? '%' : ' ',
-                        Modifier.isSynchronized(mod) ? 's' : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', Modifier.isNative(mod) ? 'n' : ' ', compLevelChar,
-                        MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize()));
+        TTY.println(String.format("%s%7d %4d %c%c%c%c%c %s      %s %s(%d bytes)", compilerName, backend.getRuntime().compilerToVm.getTimeStamp(), id, isOSR ? '%' : ' ', method.isSynchronized() ? 's'
+                        : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', method.isNative() ? 'n' : ' ', compLevelString, MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI +
+                        " " : "", method.getCodeSize()));
     }
 
-    private HotSpotInstalledCode installMethod(final CompilationResult compResult) {
+    private InstalledCode installMethod(final CompilationResult compResult) {
         final HotSpotCodeCacheProvider codeCache = backend.getProviders().getCodeCache();
-        HotSpotInstalledCode installedCode = null;
+        InstalledCode installedCode = null;
         try (Scope s = Debug.scope("CodeInstall", new DebugDumpScope(String.valueOf(id), true), codeCache, method)) {
             installedCode = codeCache.installMethod(method, compResult);
         } catch (Throwable e) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -35,8 +35,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.bytecode.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.HotSpotOptions.OptionConsumer;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.options.*;
@@ -311,7 +311,7 @@
         }
 
         println();
-        TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime);
+        println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime);
     }
 
     class CTWCompilationTask extends CompilationTask {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,7 +25,9 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.stack.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
@@ -34,7 +36,6 @@
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.word.*;
 
@@ -44,9 +45,9 @@
 public abstract class HotSpotBackend extends Backend {
 
     /**
-     * Descriptor for SharedRuntime::deopt_blob()-&gt;uncommon_trap().
+     * Descriptor for {@link DeoptimizationStub}.
      */
-    public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("deoptimize", void.class);
+    public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class);
 
     /**
      * Descriptor for {@link ExceptionHandlerStub}. This stub is called by the
@@ -96,7 +97,7 @@
 
     /**
      * Finds all the registers that are defined by some given LIR.
-     * 
+     *
      * @param lir the LIR to examine
      * @return the registers that are defined by or used as temps for any instruction in {@code lir}
      */
@@ -134,7 +135,7 @@
      * {@linkplain SaveRegistersOp#remove(Set) removed} as these registers are declared as
      * temporaries in the stub's {@linkplain ForeignCallLinkage linkage} (and thus will be saved by
      * the stub's caller).
-     * 
+     *
      * @param stub the stub to update
      * @param destroyedRegisters the registers destroyed by the stub
      * @param calleeSaveInfo a map from debug infos to the operations that provide their
@@ -158,6 +159,11 @@
     }
 
     @Override
+    public StackIntrospection getStackIntrospection() {
+        return runtime;
+    }
+
+    @Override
     public HotSpotProviders getProviders() {
         return (HotSpotProviders) super.getProviders();
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,11 +22,14 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.hotspot.data.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 
 /**
@@ -40,8 +43,8 @@
 
     public HotSpotCompiledRuntimeStub(TargetDescription target, Stub stub, CompilationResult compResult) {
         super(target, compResult);
+        this.stubName = stub.toString();
         assert checkStubInvariants(compResult);
-        this.stubName = stub.toString();
     }
 
     /**
@@ -50,6 +53,15 @@
     private boolean checkStubInvariants(CompilationResult compResult) {
         assert compResult.getExceptionHandlers().isEmpty();
         for (DataPatch data : compResult.getDataReferences()) {
+            if (data.data instanceof MetaspaceData) {
+                MetaspaceData meta = (MetaspaceData) data.data;
+                if (meta.annotation instanceof HotSpotResolvedObjectType && ((HotSpotResolvedObjectType) meta.annotation).getName().equals("[I")) {
+                    // special handling for NewArrayStub
+                    // embedding the type '[I' is safe, since it is never unloaded
+                    continue;
+                }
+            }
+
             assert !(data.data instanceof PatchedData) : this + " cannot have embedded object or metadata constant: " + data.data;
         }
         for (Infopoint infopoint : compResult.getInfopoints()) {
@@ -57,8 +69,13 @@
             Call call = (Call) infopoint;
             assert call.target instanceof HotSpotForeignCallLinkage : this + " cannot have non runtime call: " + call.target;
             HotSpotForeignCallLinkage linkage = (HotSpotForeignCallLinkage) call.target;
-            assert !linkage.isCompiledStub() : this + " cannot call compiled stub " + linkage;
+            assert !linkage.isCompiledStub() || linkage.getDescriptor() == UNCOMMON_TRAP_HANDLER : this + " cannot call compiled stub " + linkage;
         }
         return true;
     }
+
+    @Override
+    public String toString() {
+        return stubName != null ? stubName : super.toString();
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -64,4 +64,10 @@
     protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
         return new HotSpotLIRFrameState(frame, virtualObjectsArray, exceptionEdge);
     }
+
+    @Override
+    protected BytecodeFrame computeFrameForState(FrameState state) {
+        assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI;
+        return super.computeFrameForState(state);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Wed Apr 23 15:48:38 2014 +0200
@@ -151,7 +151,7 @@
         return regConfig.getCallingConvention(ccType, returnType, parameterTypes, target, false);
     }
 
-    private static JavaType asJavaType(Class type, MetaAccessProvider metaAccess, CodeCacheProvider codeCache) {
+    private static JavaType asJavaType(Class<?> type, MetaAccessProvider metaAccess, CodeCacheProvider codeCache) {
         if (WordBase.class.isAssignableFrom(type)) {
             return metaAccess.lookupJavaType(codeCache.getTarget().wordKind.toJavaClass());
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.Options.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -33,10 +33,12 @@
 import sun.reflect.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.stack.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -48,7 +50,7 @@
 /**
  * Singleton class holding the instance of the {@link GraalRuntime}.
  */
-public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider {
+public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider, StackIntrospection {
 
     private static final HotSpotGraalRuntime instance = new HotSpotGraalRuntime();
     static {
@@ -62,7 +64,7 @@
     public static HotSpotGraalRuntime runtime() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
-            Class cc = Reflection.getCallerClass();
+            Class<?> cc = Reflection.getCallerClass();
             if (cc != null && cc.getClassLoader() != null) {
                 sm.checkPermission(Graal.ACCESS_PERMISSION);
             }
@@ -153,7 +155,7 @@
      * Checks that a factory overriding is valid. A factory B can only override/replace a factory A
      * if the B.getClass() is a subclass of A.getClass(). This models the assumption that B is
      * extends the behavior of A and has therefore understood the behavior expected of A.
-     * 
+     *
      * @param baseFactory
      * @param overridingFactory
      */
@@ -265,15 +267,13 @@
 
     /**
      * Gets the Graal mirror for a {@link Class} object.
-     * 
+     *
      * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
      */
     public ResolvedJavaType fromClass(Class<?> javaClass) {
         return graalMirrors.get(javaClass);
     }
 
-    public static final String GRAAL_GPU_ISALIST_PROPERTY_NAME = "graal.gpu.isalist";
-
     /**
      * Gets the names of the supported GPU architectures for the purpose of finding the
      * corresponding {@linkplain HotSpotBackendFactory backend} objects.
@@ -320,7 +320,7 @@
 
     /**
      * Converts a name to a Java type.
-     * 
+     *
      * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
      * @param accessingType the context of resolution (may be null)
      * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
@@ -364,6 +364,10 @@
     public <T> T getCapability(Class<T> clazz) {
         if (clazz == RuntimeProvider.class) {
             return (T) this;
+        } else if (clazz == StackIntrospection.class) {
+            return (T) this;
+        } else if (clazz == SnippetReflectionProvider.class) {
+            return (T) getHostProviders().getSnippetReflection();
         }
         return null;
     }
@@ -383,7 +387,7 @@
 
     /**
      * The offset from the origin of an array to the first element.
-     * 
+     *
      * @return the offset in bytes
      */
     public static int getArrayBaseOffset(Kind kind) {
@@ -413,7 +417,7 @@
 
     /**
      * The scale used for the index when accessing elements of an array of this kind.
-     * 
+     *
      * @return the scale in order to convert the index into a byte offset
      */
     public static int getArrayIndexScale(Kind kind) {
@@ -440,4 +444,50 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
+
+    public Iterable<InspectedFrame> getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip) {
+        final long[] initialMetaMethods = toMeta(initialMethods);
+        final long[] matchingMetaMethods = toMeta(matchingMethods);
+        class StackFrameIterator implements Iterator<InspectedFrame> {
+
+            private HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, initialMetaMethods, initialSkip);
+            // we don't want to read ahead if hasNext isn't called
+            private boolean advanced = true;
+
+            public boolean hasNext() {
+                update();
+                return current != null;
+            }
+
+            public InspectedFrame next() {
+                update();
+                advanced = false;
+                return current;
+            }
+
+            private void update() {
+                if (!advanced) {
+                    current = compilerToVm.getNextStackFrame(current, matchingMetaMethods, 0);
+                    advanced = true;
+                }
+            }
+        }
+        return new Iterable<InspectedFrame>() {
+            public Iterator<InspectedFrame> iterator() {
+                return new StackFrameIterator();
+            }
+        };
+    }
+
+    private static long[] toMeta(ResolvedJavaMethod[] methods) {
+        if (methods == null) {
+            return null;
+        } else {
+            long[] result = new long[methods.length];
+            for (int i = 0; i < result.length; i++) {
+                result[i] = ((HotSpotResolvedJavaMethod) methods[i]).getMetaspaceMethod();
+            }
+            return result;
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,27 +24,41 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.gen.*;
 
 /**
  * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition
- * to abstract methods from {@link LIRGenerator} and {@link NodeLIRBuilderTool}.
+ * to abstract methods from {@link LIRGenerator} and {@link LIRGeneratorTool}.
  */
-public interface HotSpotLIRGenerator {
+public interface HotSpotLIRGenerator extends LIRGeneratorTool {
 
     /**
      * Emits an operation to make a tail call.
-     * 
+     *
      * @param args the arguments of the call
      * @param address the target address of the call
      */
     void emitTailcall(Value[] args, Value address);
 
+    void emitLeaveCurrentStackFrame();
+
+    void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo);
+
+    void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp);
+
+    void emitLeaveUnpackFramesStackFrame();
+
+    SaveRegistersOp emitSaveAllRegisters();
+
     void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason);
 
+    void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo);
+
+    Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp);
+
     /**
      * Gets a stack slot for a lock at a given lock nesting depth.
      */
@@ -52,7 +66,7 @@
 
     HotSpotProviders getProviders();
 
-    Value emitCompress(Value pointer, CompressEncoding encoding);
+    Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull);
 
-    Value emitUncompress(Value pointer, CompressEncoding encoding);
+    Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.hotspot;
 
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -33,8 +33,8 @@
 import java.nio.file.*;
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.common.*;
@@ -217,7 +217,7 @@
      * @param c the class in which the field is declared
      * @param name the name of the field
      */
-    private static void unconditionallyEnableTimerOrMetric(Class c, String name) {
+    private static void unconditionallyEnableTimerOrMetric(Class<?> c, String name) {
         try {
             Field field = c.getDeclaredField(name);
             String propertyName;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,10 +26,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 
@@ -41,8 +42,8 @@
 
     private final HotSpotVMConfig config;
 
-    public HotSpotReplacementsImpl(Providers providers, HotSpotVMConfig config, Assumptions assumptions, TargetDescription target) {
-        super(providers, assumptions, target);
+    public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, HotSpotVMConfig config, Assumptions assumptions, TargetDescription target) {
+        super(providers, snippetReflection, assumptions, target);
         this.config = config;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotStackFrameReference.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,83 @@
+/*
+ * 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;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.stack.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.*;
+
+public class HotSpotStackFrameReference implements InspectedFrame {
+
+    private CompilerToVM compilerToVM;
+
+    // information used to find the stack frame
+    private long stackPointer;
+    private int frameNumber;
+
+    // information about the stack frame's contents
+    private int bci;
+    private long metaspaceMethod;
+    private Object[] locals;
+    private boolean[] localIsVirtual;
+
+    public long getStackPointer() {
+        return stackPointer;
+    }
+
+    public int getFrameNumber() {
+        return frameNumber;
+    }
+
+    public Object getLocal(int index) {
+        return locals[index];
+    }
+
+    public boolean isVirtual(int index) {
+        return localIsVirtual == null ? false : localIsVirtual[index];
+    }
+
+    public void materializeVirtualObjects(boolean invalidateCode) {
+        compilerToVM.materializeVirtualObjects(this, invalidateCode);
+    }
+
+    public int getBytecodeIndex() {
+        return bci;
+    }
+
+    public ResolvedJavaMethod getMethod() {
+        return HotSpotResolvedJavaMethod.fromMetaspace(metaspaceMethod);
+    }
+
+    public boolean hasVirtualObjects() {
+        return localIsVirtual != null;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotStackFrameReference [stackPointer=" + stackPointer + ", frameNumber=" + frameNumber + ", bci=" + bci + ", method=" + getMethod() + ", locals=" + Arrays.toString(locals) +
+                        ", localIsVirtual=" + Arrays.toString(localIsVirtual) + "]";
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.io.*;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 
 /**
  * Represents a metaspace {@code Symbol}.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -857,6 +857,7 @@
     @HotSpotVMField(name = "Array<Klass*>::_length", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayLengthOffset;
     @HotSpotVMField(name = "Array<Klass*>::_data[0]", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayBaseOffset;
 
+    @HotSpotVMField(name = "InstanceKlass::_graal_node_class", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int klassNodeClassOffset;
     @HotSpotVMField(name = "InstanceKlass::_source_file_name_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int klassSourceFileNameIndexOffset;
     @HotSpotVMField(name = "InstanceKlass::_init_state", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int klassStateOffset;
     @HotSpotVMField(name = "InstanceKlass::_constants", type = "ConstantPool*", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassConstantsOffset;
@@ -961,7 +962,10 @@
         return javaThreadAnchorOffset + javaFrameAnchorFlagsOffset;
     }
 
+    // These are only valid on AMD64.
     @HotSpotVMConstant(name = "frame::arg_reg_save_area_bytes", archs = {"amd64"}) @Stable public int runtimeCallStackSize;
+    @HotSpotVMConstant(name = "frame::interpreter_frame_sender_sp_offset", archs = {"amd64"}) @Stable public int frameInterpreterFrameSenderSpOffset;
+    @HotSpotVMConstant(name = "frame::interpreter_frame_last_sp_offset", archs = {"amd64"}) @Stable public int frameInterpreterFrameLastSpOffset;
 
     @HotSpotVMField(name = "PtrQueue::_active", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueActiveOffset;
     @HotSpotVMField(name = "PtrQueue::_buf", type = "void**", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueBufferOffset;
@@ -1009,16 +1013,19 @@
     @HotSpotVMField(name = "ThreadShadow::_pending_failed_speculation", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingFailedSpeculationOffset;
 
     @HotSpotVMFlag(name = "UseHSAILDeoptimization") @Stable public boolean useHSAILDeoptimization;
+    @HotSpotVMFlag(name = "UseHSAILSafepoints") @Stable public boolean useHSAILSafepoints;
 
     /**
      * Offsets of Hsail deoptimization fields (defined in gpu_hsail.hpp). Used to propagate
      * exceptions from Hsail back to C++ runtime.
      */
+    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_notice_safepoints", type = "jint*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNoticeSafepointsOffset;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[0]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset0;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[1]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset1;
-    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_occurred", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptOffset;
+    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_occurred", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptOccurredOffset;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_never_ran_array", type = "jboolean *", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNeverRanArrayOffset;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_next_index", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptNextIndexOffset;
+    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_donor_threads", type = "JavaThread**", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDonorThreadsOffset;
 
     @HotSpotVMField(name = "Hsail::HSAILKernelDeoptimization::_workitemid", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptimizationWorkItem;
     @HotSpotVMField(name = "Hsail::HSAILKernelDeoptimization::_actionAndReason", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptimizationReason;
@@ -1054,6 +1061,7 @@
     @HotSpotVMConstant(name = "Method::_force_inline") @Stable public int methodFlagsForceInline;
     @HotSpotVMConstant(name = "Method::_dont_inline") @Stable public int methodFlagsDontInline;
     @HotSpotVMConstant(name = "Method::_hidden") @Stable public int methodFlagsHidden;
+    @HotSpotVMConstant(name = "Method::nonvirtual_vtable_index") @Stable public int nonvirtualVtableIndex;
 
     @HotSpotVMConstant(name = "JVM_ACC_MONITOR_MATCH") @Stable public int jvmAccMonitorMatch;
     @HotSpotVMConstant(name = "JVM_ACC_HAS_MONITOR_BYTECODES") @Stable public int jvmAccHasMonitorBytecodes;
@@ -1244,6 +1252,7 @@
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_start", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferStartOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_end", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferEndOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferTopOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_pf_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferPfTopOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_slow_allocations", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferSlowAllocationsOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_fast_refill_waste", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferFastRefillWasteOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_number_of_refills", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferNumberOfRefillsOffset;
@@ -1282,6 +1291,10 @@
         return threadTlabOffset + threadLocalAllocBufferTopOffset;
     }
 
+    public int threadTlabPfTopOffset() {
+        return threadTlabOffset + threadLocalAllocBufferPfTopOffset;
+    }
+
     @HotSpotVMFlag(name = "TLABStats") @Stable public boolean tlabStats;
     @Stable public boolean inlineContiguousAllocationSupported;
 
@@ -1340,7 +1353,6 @@
     }
 
     @Stable public long handleDeoptStub;
-    @Stable public long uncommonTrapStub;
 
     @HotSpotVMField(name = "StubRoutines::_aescrypt_encryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptEncryptBlockStub;
     @HotSpotVMField(name = "StubRoutines::_aescrypt_decryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptDecryptBlockStub;
@@ -1410,6 +1422,10 @@
 
     @Stable public int graalCountersSize;
 
+    @Stable public long deoptimizationFetchUnrollInfo;
+    @Stable public long deoptimizationUncommonTrap;
+    @Stable public long deoptimizationUnpackFrames;
+
     @HotSpotVMConstant(name = "Deoptimization::Reason_none") @Stable public int deoptReasonNone;
     @HotSpotVMConstant(name = "Deoptimization::Reason_null_check") @Stable public int deoptReasonNullCheck;
     @HotSpotVMConstant(name = "Deoptimization::Reason_range_check") @Stable public int deoptReasonRangeCheck;
@@ -1440,6 +1456,19 @@
     @HotSpotVMConstant(name = "Deoptimization::_reason_shift") @Stable public int deoptimizationReasonShift;
     @HotSpotVMConstant(name = "Deoptimization::_debug_id_shift") @Stable public int deoptimizationDebugIdShift;
 
+    @HotSpotVMConstant(name = "Deoptimization::Unpack_deopt") @Stable public int deoptimizationUnpackDeopt;
+    @HotSpotVMConstant(name = "Deoptimization::Unpack_exception") @Stable public int deoptimizationUnpackException;
+    @HotSpotVMConstant(name = "Deoptimization::Unpack_uncommon_trap") @Stable public int deoptimizationUnpackUncommonTrap;
+    @HotSpotVMConstant(name = "Deoptimization::Unpack_reexecute") @Stable public int deoptimizationUnpackReexecute;
+
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_size_of_deoptimized_frame", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_caller_adjustment", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockCallerAdjustmentOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_number_of_frames", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockNumberOfFramesOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_total_frame_sizes", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockTotalFrameSizesOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_sizes", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFrameSizesOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_pcs", type = "address*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFramePcsOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_initial_info", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockInitialInfoOffset;
+
     @HotSpotVMConstant(name = "vmIntrinsics::_invokeBasic") @Stable public int vmIntrinsicInvokeBasic;
     @HotSpotVMConstant(name = "vmIntrinsics::_linkToVirtual") @Stable public int vmIntrinsicLinkToVirtual;
     @HotSpotVMConstant(name = "vmIntrinsics::_linkToStatic") @Stable public int vmIntrinsicLinkToStatic;
@@ -1499,6 +1528,22 @@
             this.alignment = alignment;
         }
 
+        public int compress(long ptr) {
+            if (ptr == 0L) {
+                return 0;
+            } else {
+                return (int) ((ptr - base) >>> shift);
+            }
+        }
+
+        public long uncompress(int ptr) {
+            if (ptr == 0) {
+                return 0L;
+            } else {
+                return ((ptr & 0xFFFFFFFFL) << shift) + base;
+            }
+        }
+
         @Override
         public String toString() {
             return "base: " + base + " shift: " + shift + " alignment: " + alignment;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import sun.misc.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,7 +25,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -36,7 +36,7 @@
 
     /**
      * Copies the original bytecode of a given method into a given byte array.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object
      * @param code the array into which to copy the original bytecode
      * @return the value of {@code code}
@@ -49,7 +49,7 @@
 
     /**
      * Determines if a given metaspace Method object has balanced monitors.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object to query
      * @return true if the method has balanced monitors
      */
@@ -63,7 +63,7 @@
      * <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>
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object to query
      * @return true if the method can be inlined
      */
@@ -75,7 +75,7 @@
      * <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 should be inlined
      */
@@ -83,7 +83,7 @@
 
     /**
      * Used to implement {@link ResolvedJavaType#findUniqueConcreteMethod(ResolvedJavaMethod)}.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method on which to based the search
      * @return the metaspace Method result or 0 is there is no unique concrete method for
      *         {@code metaspaceMethod}
@@ -92,7 +92,7 @@
 
     /**
      * Returns the implementor for the given interface class.
-     * 
+     *
      * @param metaspaceKlass the metaspace klass to get the implementor for
      * @return the implementor as metaspace klass pointer or null if there is no implementor
      */
@@ -100,7 +100,7 @@
 
     /**
      * Determines if a given metaspace method is ignored by security stack walks.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object
      * @return true if the method is ignored
      */
@@ -108,7 +108,7 @@
 
     /**
      * Converts a name to a metaspace klass.
-     * 
+     *
      * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
      * @param accessingClass the context of resolution (may be null)
      * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
@@ -134,7 +134,7 @@
 
     /**
      * Looks up a class entry in a constant pool.
-     * 
+     *
      * @param metaspaceConstantPool metaspace constant pool pointer
      * @param cpi constant pool index
      * @return a metaspace Klass for a resolved method entry, a metaspace Symbol otherwise (with
@@ -144,7 +144,7 @@
 
     /**
      * Looks up a method entry in a constant pool.
-     * 
+     *
      * @param metaspaceConstantPool metaspace constant pool pointer
      * @param cpi constant pool index
      * @return a metaspace Method for a resolved method entry, 0 otherwise
@@ -154,12 +154,12 @@
     /**
      * Looks up a field entry in a constant pool and attempts to resolve it. The values returned in
      * {@code info} are:
-     * 
+     *
      * <pre>
      *     [(int) flags,   // only valid if field is resolved
      *      (int) offset]  // only valid if field is resolved
      * </pre>
-     * 
+     *
      * @param metaspaceConstantPool metaspace constant pool pointer
      * @param cpi constant pool index
      * @param info an array in which the details of the field are returned
@@ -221,16 +221,16 @@
 
     /**
      * Installs the result of a compilation into the code cache.
-     * 
+     *
      * @param compiledCode the result of a compilation
      * @param code the details of the installed CodeBlob are written to this object
      * @return the outcome of the installation as a {@link CodeInstallResult}.
      */
-    CodeInstallResult installCode(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog);
+    CodeInstallResult installCode(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog);
 
     /**
      * Notifies the VM of statistics for a completed compilation.
-     * 
+     *
      * @param id the identifier of the compilation
      * @param method the method compiled
      * @param osr specifies if the compilation was for on-stack-replacement
@@ -240,7 +240,7 @@
      * @param timeUnitsPerSecond the granularity of the units for the {@code time} value
      * @param installedCode the nmethod installed as a result of the compilation
      */
-    void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, HotSpotInstalledCode installedCode);
+    void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode);
 
     void printCompilationStatistics(boolean perCompiler, boolean aggregate);
 
@@ -257,7 +257,7 @@
     /**
      * Gets the metaspace Method object corresponding to a given {@link Class} object and slot
      * number.
-     * 
+     *
      * @param holder method holder
      * @param slot slot number of the method
      * @return the metaspace Method
@@ -270,9 +270,9 @@
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
-    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
-    Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    Object executeCompiledMethodVarargs(Object[] args, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
     long[] getLineNumberTable(long metaspaceMethod);
 
@@ -282,7 +282,7 @@
 
     String getFileName(HotSpotResolvedJavaType method);
 
-    Object readUnsafeUncompressedPointer(Object o, long displacement);
+    Class<?> getJavaMirror(long metaspaceKlass);
 
     long readUnsafeKlassPointer(Object o);
 
@@ -290,12 +290,12 @@
 
     /**
      * Invalidates the profiling information and restarts profiling upon the next invocation.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object
      */
     void reprofile(long metaspaceMethod);
 
-    void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
+    void invalidateInstalledCode(InstalledCode hotspotInstalledCode);
 
     /**
      * Collects the current values of all Graal benchmark counters, summed up over all threads.
@@ -311,17 +311,46 @@
 
     /**
      * Gets the names of the supported GPU architectures.
-     * 
+     *
      * @return a comma separated list of names
      */
     String getGPUs();
 
     /**
-     * 
+     *
      * @param metaspaceMethod the method to check
      * @param entryBCI
      * @param level the compilation level
      * @return true if the {@code metaspaceMethod} has code for {@code level}
      */
     boolean hasCompiledCodeForOSR(long metaspaceMethod, int entryBCI, int level);
+
+    /**
+     * Fetch the time stamp used for printing inside hotspot. It's relative to VM start to that all
+     * events can be ordered.
+     *
+     * @return milliseconds since VM start
+     */
+    long getTimeStamp();
+
+    /**
+     * Looks for the next Java stack frame with the given method.
+     *
+     * @param frame the starting point of the search, where {@code null} refers to the topmost frame
+     * @param methods the metaspace methods to look for, where {@code null} means that any frame is
+     *            returned
+     * @return the frame, or {@code null} if the end of the stack was reached during the search
+     */
+    HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, long[] methods, int initialSkip);
+
+    /**
+     * Materialized all virtual objects within the given stack frame and update the locals within
+     * the given stackFrame object.
+     *
+     * @param invalidate if {@code true}, the compiled method for the stack frame will be
+     *            invalidated.
+     */
+    void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
+
+    void resolveInvokeDynamic(long metaspaceConstantPool, int index);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -32,10 +32,10 @@
  */
 public class CompilerToVMImpl implements CompilerToVM {
 
-    private native int installCode0(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog);
+    private native int installCode0(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog);
 
     @Override
-    public CodeInstallResult installCode(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog) {
+    public CodeInstallResult installCode(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog) {
         return CodeInstallResult.getEnum(installCode0(compiledCode, code, speculationLog));
     }
 
@@ -120,7 +120,7 @@
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
     @Override
-    public native Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode);
+    public native Object executeCompiledMethodVarargs(Object[] args, InstalledCode hotspotInstalledCode);
 
     @Override
     public native long[] getLineNumberTable(long metaspaceMethod);
@@ -138,10 +138,10 @@
     public native void reprofile(long metaspaceMethod);
 
     @Override
-    public native void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
+    public native void invalidateInstalledCode(InstalledCode hotspotInstalledCode);
 
     @Override
-    public native Object readUnsafeUncompressedPointer(Object o, long displacement);
+    public native Class<?> getJavaMirror(long metaspaceKlass);
 
     @Override
     public native long readUnsafeKlassPointer(Object o);
@@ -150,12 +150,12 @@
     public native void doNotInlineOrCompile(long metaspaceMethod);
 
     @Override
-    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
+    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
         return executeCompiledMethodVarargs(new Object[]{arg1, arg2, arg3}, hotspotInstalledCode);
     }
 
     public synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond,
-                    HotSpotInstalledCode installedCode);
+                    InstalledCode installedCode);
 
     public synchronized native void printCompilationStatistics(boolean perCompiler, boolean aggregate);
 
@@ -175,4 +175,11 @@
 
     public native boolean hasCompiledCodeForOSR(long metaspaceMethod, int entryBCI, int level);
 
+    public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, long[] methods, int initialSkip);
+
+    public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
+
+    public native long getTimeStamp();
+
+    public native void resolveInvokeDynamic(long metaspaceConstantPool, int index);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +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.hotspot.bridge;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.meta.*;
-
-/**
- * A fast-path for {@link NodeClass} retrieval using {@link HotSpotResolvedObjectType}.
- */
-class FastNodeClassRegistry extends NodeClass.Registry {
-
-    @SuppressWarnings("unused")
-    static void initialize() {
-        new FastNodeClassRegistry();
-    }
-
-    private static HotSpotResolvedObjectType type(Class<? extends Node> key) {
-        return (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(key);
-    }
-
-    @Override
-    public NodeClass get(Class<? extends Node> key) {
-        return type(key).getNodeClass();
-    }
-
-    @Override
-    protected void registered(Class<? extends Node> key, NodeClass value) {
-        type(key).setNodeClass(value);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -34,9 +34,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.CompilationTask.Enqueueing;
 import com.oracle.graal.hotspot.CompileTheWorld.Config;
@@ -144,8 +144,6 @@
 
     public void startCompiler(boolean bootstrapEnabled) throws Throwable {
 
-        FastNodeClassRegistry.initialize();
-
         bootstrapRunning = bootstrapEnabled;
 
         if (LogFile.getValue() != null) {
@@ -250,7 +248,7 @@
 
     /**
      * Take action related to entering a new execution phase.
-     * 
+     *
      * @param phase the execution phase being entered
      */
     protected void phaseTransition(String phase) {
@@ -347,7 +345,7 @@
 
     private void enqueue(Method m) throws Throwable {
         JavaMethod javaMethod = runtime.getHostProviders().getMetaAccess().lookupJavaMethod(m);
-        assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) : javaMethod;
+        assert !((HotSpotResolvedJavaMethod) javaMethod).isAbstract() && !((HotSpotResolvedJavaMethod) javaMethod).isNative() : javaMethod;
         compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, false);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 
 /**
  * A data item that represents a metaspace pointer.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.type.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,7 +30,8 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -40,7 +41,6 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.replacements.nodes.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java	Wed Apr 23 15:48:38 2014 +0200
@@ -79,7 +79,7 @@
         return interf.cast(obj);
     }
 
-    private static ArrayList<CountingProxy> proxies = new ArrayList<>();
+    private static ArrayList<CountingProxy<?>> proxies = new ArrayList<>();
 
     static {
         if (ENABLED) {
@@ -87,7 +87,7 @@
 
                 @Override
                 public void run() {
-                    for (CountingProxy proxy : proxies) {
+                    for (CountingProxy<?> proxy : proxies) {
                         proxy.print();
                     }
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,8 +35,8 @@
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.code.CompilationResult.PrimitiveData;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
@@ -196,7 +196,7 @@
         return runtime.getConfig().runtimeCallStackSize;
     }
 
-    public HotSpotInstalledCode logOrDump(HotSpotInstalledCode installedCode, CompilationResult compResult) {
+    public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
         if (Debug.isDumpEnabled()) {
             Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
         }
@@ -206,7 +206,7 @@
         return installedCode;
     }
 
-    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
+    public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
         if (compResult.getId() == -1) {
             compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
         }
@@ -216,17 +216,21 @@
     }
 
     @Override
-    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log) {
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
         if (compResult.getId() == -1) {
             compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
         }
-        HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
-        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, hotspotMethod, compResult), code, log);
+        InstalledCode installedCode = predefinedInstalledCode;
+        if (installedCode == null) {
+            HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
+            installedCode = code;
+        }
+        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, hotspotMethod, compResult), installedCode, log);
         if (result != CodeInstallResult.OK) {
-            return null;
+            throw new BailoutException("Code installation failed: " + result);
         }
-        return logOrDump(code, compResult);
+        return logOrDump(installedCode, compResult);
     }
 
     @Override
@@ -251,14 +255,16 @@
     }
 
     public boolean needsDataPatch(Constant constant) {
-        return constant.getPrimitiveAnnotation() != null;
+        return constant instanceof HotSpotMetaspaceConstant;
     }
 
     public Data createDataItem(Constant constant, int alignment) {
-        if (constant.getPrimitiveAnnotation() != null) {
-            return new MetaspaceData(alignment, constant.asLong(), constant.getPrimitiveAnnotation(), false);
+        if (constant instanceof HotSpotMetaspaceConstant) {
+            // constant.getKind() == target.wordKind for uncompressed pointers
+            // otherwise, it's a compressed pointer
+            return new MetaspaceData(alignment, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), constant.getKind() != target.wordKind);
         } else if (constant.getKind().isObject()) {
-            return new OopData(alignment, constant.asObject(), false);
+            return new OopData(alignment, HotSpotObjectConstant.asObject(constant), false);
         } else {
             return new PrimitiveData(constant, alignment);
         }
@@ -271,7 +277,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long codeBlob = ((HotSpotInstalledCode) code).getCodeBlob();
+            long codeBlob = ((HotSpotInstalledCode) code).getAddress();
             return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.invoke.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.bytecode.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -368,13 +368,13 @@
                 return lookupType(cpi, opcode);
             case String:
                 Object string = runtime().getCompilerToVM().resolvePossiblyCachedConstantInPool(metaspaceConstantPool, cpi);
-                return Constant.forObject(string);
+                return HotSpotObjectConstant.forObject(string);
             case MethodHandle:
             case MethodHandleInError:
             case MethodType:
             case MethodTypeInError:
                 Object obj = runtime().getCompilerToVM().resolveConstantInPool(metaspaceConstantPool, cpi);
-                return Constant.forObject(obj);
+                return HotSpotObjectConstant.forObject(obj);
             default:
                 throw GraalInternalError.shouldNotReachHere("unknown constant pool tag " + tag);
         }
@@ -394,10 +394,15 @@
     }
 
     @Override
-    public Object lookupAppendix(int cpi, int opcode) {
+    public Constant lookupAppendix(int cpi, int opcode) {
         assert Bytecodes.isInvoke(opcode);
         final int index = toConstantPoolIndex(cpi, opcode);
-        return runtime().getCompilerToVM().lookupAppendixInPool(metaspaceConstantPool, index);
+        Object result = runtime().getCompilerToVM().lookupAppendixInPool(metaspaceConstantPool, index);
+        if (result == null) {
+            return null;
+        } else {
+            return HotSpotObjectConstant.forObject(result);
+        }
     }
 
     /**
@@ -496,7 +501,7 @@
                 break;
             case Bytecodes.INVOKEDYNAMIC:
                 // invokedynamic instructions point to a constant pool cache entry.
-                index = decodeConstantPoolCacheIndex(cpi);
+                index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag;
                 index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, index);
                 break;
             default:
@@ -512,13 +517,7 @@
                 index = getUncachedKlassRefIndexAt(index);
                 tag = getTagAt(index);
                 assert tag == JVM_CONSTANT.Class || tag == JVM_CONSTANT.UnresolvedClass || tag == JVM_CONSTANT.UnresolvedClassInError : tag;
-                break;
-            default:
-                // nothing
-                break;
-        }
-
-        switch (tag) {
+                // fall-through
             case Class:
             case UnresolvedClass:
             case UnresolvedClassInError:
@@ -529,6 +528,12 @@
                     unsafe.ensureClassInitialized(klass);
                 }
                 break;
+            case InvokeDynamic:
+                if (!isInvokedynamicIndex(cpi)) {
+                    throw new IllegalArgumentException("InvokeDynamic entries must be accessed");
+                }
+                runtime().getCompilerToVM().resolveInvokeDynamic(metaspaceConstantPool, cpi);
+                break;
             default:
                 // nothing
                 break;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -48,15 +48,34 @@
     }
 
     @Override
-    public Integer lookupArrayLength(Constant array) {
-        if (array.getKind() != Kind.Object || array.isNull() || !array.asObject().getClass().isArray()) {
+    public Integer readArrayLength(Constant array) {
+        if (array.getKind() != Kind.Object || array.isNull() || !HotSpotObjectConstant.asObject(array).getClass().isArray()) {
             return null;
         }
-        return Array.getLength(array.asObject());
+        return Array.getLength(HotSpotObjectConstant.asObject(array));
     }
 
     @Override
-    public Constant readUnsafeConstant(Kind kind, Object base, long displacement, boolean compressible) {
+    public Constant readUnsafeConstant(Kind kind, Constant baseConstant, long initialDisplacement) {
+        Object base;
+        long displacement;
+        if (baseConstant.getKind() == Kind.Object) {
+            base = HotSpotObjectConstant.asObject(baseConstant);
+            displacement = initialDisplacement;
+            if (base == null) {
+                return null;
+            }
+        } else if (baseConstant.getKind().isNumericInteger()) {
+            long baseLong = baseConstant.asLong();
+            if (baseLong == 0L) {
+                return null;
+            }
+            displacement = initialDisplacement + baseLong;
+            base = null;
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
         switch (kind) {
             case Boolean:
                 return Constant.forBoolean(base == null ? unsafe.getByte(displacement) != 0 : unsafe.getBoolean(base, displacement));
@@ -84,15 +103,132 @@
                 return Constant.forDouble(base == null ? unsafe.getDouble(displacement) : unsafe.getDouble(base, displacement));
             case Object: {
                 Object o = null;
-                if (compressible) {
+                if (baseConstant.getKind() == Kind.Object) {
                     o = unsafe.getObject(base, displacement);
+                } else if (baseConstant instanceof HotSpotMetaspaceConstant) {
+                    Object metaspaceObject = HotSpotMetaspaceConstant.getMetaspaceObject(baseConstant);
+                    if (metaspaceObject instanceof HotSpotResolvedObjectType && initialDisplacement == runtime.getConfig().classMirrorOffset) {
+                        o = ((HotSpotResolvedObjectType) metaspaceObject).mirror();
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere();
+                    }
                 } else {
-                    o = runtime.getCompilerToVM().readUnsafeUncompressedPointer(base, displacement);
+                    throw GraalInternalError.shouldNotReachHere();
                 }
-                return Constant.forObject(o);
+                return HotSpotObjectConstant.forObject(o);
             }
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
+
+    @Override
+    public Constant readRawConstant(Kind kind, Constant baseConstant, long initialDisplacement, int bits) {
+        Object base;
+        long displacement;
+        if (baseConstant.getKind() == Kind.Object) {
+            base = HotSpotObjectConstant.asObject(baseConstant);
+            displacement = initialDisplacement;
+            if (base == null) {
+                return null;
+            }
+        } else if (baseConstant.getKind().isNumericInteger()) {
+            long baseLong = baseConstant.asLong();
+            if (baseLong == 0L) {
+                return null;
+            }
+            displacement = initialDisplacement + baseLong;
+            base = null;
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        long rawValue;
+        switch (bits) {
+            case 8:
+                rawValue = base == null ? unsafe.getByte(displacement) : unsafe.getByte(base, displacement);
+                break;
+            case 16:
+                rawValue = base == null ? unsafe.getShort(displacement) : unsafe.getShort(base, displacement);
+                break;
+            case 32:
+                rawValue = base == null ? unsafe.getInt(displacement) : unsafe.getInt(base, displacement);
+                break;
+            case 64:
+                rawValue = base == null ? unsafe.getLong(displacement) : unsafe.getLong(base, displacement);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+
+        if (base != null && displacement == config().hubOffset) {
+            if (config().useCompressedClassPointers) {
+                assert bits == 32 && kind == Kind.Int;
+                long klassPointer = config().getKlassEncoding().uncompress((int) rawValue);
+                assert klassPointer == runtime.getCompilerToVM().readUnsafeKlassPointer(base);
+                return HotSpotMetaspaceConstant.forMetaspaceObject(kind, rawValue, HotSpotResolvedObjectType.fromMetaspaceKlass(klassPointer));
+            } else {
+                assert bits == 64 && kind == Kind.Long;
+                return HotSpotMetaspaceConstant.forMetaspaceObject(kind, rawValue, HotSpotResolvedObjectType.fromMetaspaceKlass(rawValue));
+            }
+        } else {
+            switch (kind) {
+                case Int:
+                    return Constant.forInt((int) rawValue);
+                case Long:
+                    return Constant.forLong(rawValue);
+                case Float:
+                    return Constant.forFloat(Float.intBitsToFloat((int) rawValue));
+                case Double:
+                    return Constant.forDouble(Double.longBitsToDouble(rawValue));
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Override
+    public Constant readArrayElement(Constant array, int index) {
+        if (array.getKind() != Kind.Object || array.isNull()) {
+            return null;
+        }
+        Object a = HotSpotObjectConstant.asObject(array);
+
+        if (index < 0 || index >= Array.getLength(a)) {
+            return null;
+        }
+
+        if (a instanceof Object[]) {
+            return HotSpotObjectConstant.forObject(((Object[]) a)[index]);
+        } else {
+            return Constant.forBoxedPrimitive(Array.get(a, index));
+        }
+    }
+
+    @Override
+    public Constant boxPrimitive(Constant source) {
+        if (!source.getKind().isPrimitive()) {
+            return null;
+        }
+        return HotSpotObjectConstant.forObject(source.asBoxedPrimitive());
+    }
+
+    @Override
+    public Constant unboxPrimitive(Constant source) {
+        if (!source.getKind().isObject()) {
+            return null;
+        }
+        return Constant.forBoxedPrimitive(HotSpotObjectConstant.asObject(source));
+    }
+
+    @Override
+    public ResolvedJavaType asJavaType(Constant constant) {
+        if (constant.getKind() == Kind.Object) {
+            Object obj = HotSpotObjectConstant.asObject(constant);
+            if (obj instanceof Class) {
+                return runtime.getHostProviders().getMetaAccess().lookupJavaType((Class<?>) obj);
+            }
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -38,7 +38,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long codeBlob = ((HotSpotInstalledCode) code).getCodeBlob();
+            long codeBlob = ((HotSpotInstalledCode) code).getAddress();
             return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,6 +30,7 @@
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
+import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*;
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
@@ -37,12 +38,13 @@
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
 import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*;
 import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*;
+import static com.oracle.graal.hotspot.stubs.DeoptimizationStub.*;
 import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*;
 import static com.oracle.graal.hotspot.stubs.NewArrayStub.*;
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
 import static com.oracle.graal.hotspot.stubs.StubUtil.*;
 import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*;
-import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
+import static com.oracle.graal.hotspot.meta.HotSpotLoweringProvider.RuntimeCalls.*;
 import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
 import static com.oracle.graal.replacements.Log.*;
 import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
@@ -64,26 +66,25 @@
         super(runtime, metaAccess, codeCache);
     }
 
-    private static void link(Stub stub) {
+    protected static void link(Stub stub) {
         stub.getLinkage().setCompiledStub(stub);
     }
 
     public static ForeignCallDescriptor lookupArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint) {
-        return (ForeignCallDescriptor) arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].get(kind);
+        return arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].get(kind);
     }
 
-    private static final EnumMap[][] arraycopyDescriptors = new EnumMap[2][2];
+    @SuppressWarnings("unchecked") private static final EnumMap<Kind, ForeignCallDescriptor>[][] arraycopyDescriptors = new EnumMap[2][2];
 
     static {
         // Populate the EnumMap instances
         for (int i = 0; i < arraycopyDescriptors.length; i++) {
             for (int j = 0; j < arraycopyDescriptors[i].length; j++) {
-                arraycopyDescriptors[i][j] = new EnumMap<Kind, ForeignCallDescriptor>(Kind.class);
+                arraycopyDescriptors[i][j] = new EnumMap<>(Kind.class);
             }
         }
     }
 
-    @SuppressWarnings("unchecked")
     private static ForeignCallDescriptor registerArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint) {
         String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + "Arraycopy";
         ForeignCallDescriptor desc = new ForeignCallDescriptor(name, void.class, Word.class, Word.class, Word.class);
@@ -102,7 +103,6 @@
     public void initialize(HotSpotProviders providers, HotSpotVMConfig c) {
         TargetDescription target = providers.getCodeCache().getTarget();
 
-        registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub(), NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
 
@@ -115,8 +115,11 @@
 
         registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(FETCH_UNROLL_INFO, c.deoptimizationFetchUnrollInfo, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(UNCOMMON_TRAP, c.deoptimizationUncommonTrap, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
 
         link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,45 +22,32 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.hotspot.*;
+
+import edu.umd.cs.findbugs.annotations.*;
 
 /**
  * Implementation of {@link InstalledCode} for HotSpot.
  */
-public abstract class HotSpotInstalledCode extends CompilerObject implements InstalledCode {
-
-    private static final long serialVersionUID = 156632908220561612L;
-
-    /**
-     * Raw address of this code blob.
-     */
-    private long codeBlob;
+public abstract class HotSpotInstalledCode extends InstalledCode {
 
     /**
      * Total size of the code blob.
      */
-    private int size;
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int size;
 
     /**
      * Start address of the code.
      */
-    private long codeStart;
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private long codeStart;
 
     /**
      * Size of the code.
      */
-    private int codeSize;
-
-    /**
-     * @return the address of this code blob
-     */
-    public long getCodeBlob() {
-        return codeBlob;
-    }
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int codeSize;
 
     /**
      * @return the total size of this code blob
@@ -77,13 +64,14 @@
             return null;
         }
         byte[] blob = new byte[size];
-        unsafe.copyMemory(null, codeBlob, blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size);
+        unsafe.copyMemory(null, getAddress(), blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size);
         return blob;
     }
 
     @Override
     public abstract String toString();
 
+    @Override
     public long getStart() {
         return codeStart;
     }
@@ -92,6 +80,7 @@
         return codeSize;
     }
 
+    @Override
     public byte[] getCode() {
         if (!isValid()) {
             return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -26,18 +26,20 @@
 import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
 import static com.oracle.graal.nodes.java.ArrayLengthNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
@@ -90,7 +92,7 @@
         newObjectSnippets = new NewObjectSnippets.Templates(providers, target);
         monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking);
         writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null);
-        boxingSnippets = new BoxingSnippets.Templates(providers, target);
+        boxingSnippets = new BoxingSnippets.Templates(providers, providers.getSnippetReflection(), target);
         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target);
         unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target);
         providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target));
@@ -110,6 +112,8 @@
             lowerStoreFieldNode((StoreFieldNode) n, tool);
         } else if (n instanceof CompareAndSwapNode) {
             lowerCompareAndSwapNode((CompareAndSwapNode) n);
+        } else if (n instanceof AtomicReadAndWriteNode) {
+            lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n);
         } else if (n instanceof LoadIndexedNode) {
             lowerLoadIndexedNode((LoadIndexedNode) n, tool);
         } else if (n instanceof StoreIndexedNode) {
@@ -134,8 +138,8 @@
             lowerOSRStartNode((OSRStartNode) n);
         } else if (n instanceof DynamicCounterNode) {
             lowerDynamicCounterNode((DynamicCounterNode) n);
-        } else if (n instanceof DeferredForeignCallNode) {
-            lowerDeferredForeignCallNode((DeferredForeignCallNode) n);
+        } else if (n instanceof BytecodeExceptionNode) {
+            lowerBytecodeExceptionNode((BytecodeExceptionNode) n);
         } else if (n instanceof CheckCastDynamicNode) {
             checkcastDynamicSnippets.lower((CheckCastDynamicNode) n, tool);
         } else if (n instanceof InstanceOfNode) {
@@ -219,7 +223,7 @@
             NodeInputList<ValueNode> parameters = callTarget.arguments();
             ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
             GuardingNode receiverNullCheck = null;
-            if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !ObjectStamp.isObjectNonNull(receiver)) {
+            if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isObjectNonNull(receiver)) {
                 receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool);
                 invoke.setGuard(receiverNullCheck);
             }
@@ -234,7 +238,7 @@
                         int vtableEntryOffset = hsMethod.vtableEntryOffset();
                         assert vtableEntryOffset > 0;
                         Kind wordKind = runtime.getTarget().wordKind;
-                        FloatingReadNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck);
+                        ValueNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck);
 
                         ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod);
                         // We use LocationNode.ANY_LOCATION for the reads that access the
@@ -307,7 +311,7 @@
     private void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) {
         StructuredGraph graph = loadField.graph();
         HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
-        ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object();
+        ValueNode object = loadField.isStatic() ? ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph) : loadField.object();
         assert loadField.getKind() != Kind.Illegal;
         BarrierType barrierType = getFieldLoadBarrierType(field);
 
@@ -351,7 +355,7 @@
     private void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) {
         StructuredGraph graph = storeField.graph();
         HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
-        ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object();
+        ValueNode object = storeField.isStatic() ? ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph) : storeField.object();
         BarrierType barrierType = getFieldStoreBarrierType(storeField);
 
         ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value());
@@ -370,16 +374,35 @@
         }
     }
 
-    private static void lowerCompareAndSwapNode(CompareAndSwapNode cas) {
-        // Separate out GC barrier semantics
+    private void lowerCompareAndSwapNode(CompareAndSwapNode cas) {
         StructuredGraph graph = cas.graph();
-        LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), cas.expected().getKind(), cas.displacement(), cas.offset(), graph, 1);
-        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, cas.expected(), cas.newValue(), getCompareAndSwapBarrier(cas),
-                        cas.expected().getKind() == Kind.Object));
+        Kind valueKind = cas.getValueKind();
+        LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), valueKind, cas.displacement(), cas.offset(), graph, 1);
+
+        ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected(), true);
+        ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue(), true);
+
+        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, getCompareAndSwapBarrierType(cas), false));
         atomicNode.setStateAfter(cas.stateAfter());
         graph.replaceFixedWithFixed(cas, atomicNode);
     }
 
+    private void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) {
+        StructuredGraph graph = n.graph();
+        Kind valueKind = n.getValueKind();
+        LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1);
+
+        ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
+
+        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, getAtomicReadAndWriteBarrierType(n), false));
+        memoryRead.setStateAfter(n.stateAfter());
+
+        ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead);
+
+        n.replaceAtUsages(readValue);
+        graph.replaceFixedWithFixed(n, memoryRead);
+    }
+
     private void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) {
         StructuredGraph graph = loadIndexed.graph();
         Kind elementKind = loadIndexed.elementKind();
@@ -406,10 +429,10 @@
 
         CheckCastNode checkcastNode = null;
         CheckCastDynamicNode checkcastDynamicNode = null;
-        if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) {
+        if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) {
             // Store check!
-            ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array);
-            if (arrayType != null && ObjectStamp.isExactType(array)) {
+            ResolvedJavaType arrayType = StampTool.typeOrNull(array);
+            if (arrayType != null && StampTool.isExactType(array)) {
                 ResolvedJavaType elementType = arrayType.getComponentType();
                 if (!MetaUtil.isJavaLangObject(elementType)) {
                     checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true));
@@ -418,7 +441,7 @@
                 }
             } else {
                 Kind wordKind = runtime.getTarget().wordKind;
-                FloatingReadNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck);
+                ValueNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck);
                 LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph);
                 /*
                  * Anchor the read of the element klass to the cfg, because it is only valid when
@@ -471,7 +494,7 @@
                 ReadNode memoryRead = createUnsafeRead(graph, load, null);
                 // An unsafe read must not float outside its block otherwise
                 // it may float above an explicit null check on its object.
-                memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
+                memoryRead.setGuard(BeginNode.prevBegin(load));
                 graph.replaceFixedWithFixed(load, memoryRead);
             }
         }
@@ -524,7 +547,7 @@
             assert loadHub.getKind() == wordKind;
             ValueNode object = loadHub.object();
             GuardingNode guard = loadHub.getGuard();
-            FloatingReadNode hub = createReadHub(graph, wordKind, object, guard);
+            ValueNode hub = createReadHub(graph, wordKind, object, guard);
             graph.replaceFloating(loadHub, hub);
         }
     }
@@ -661,11 +684,51 @@
         }
     }
 
-    private void lowerDeferredForeignCallNode(DeferredForeignCallNode deferred) {
-        StructuredGraph graph = deferred.graph();
+    static final class Exceptions {
+        protected static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException;
+        protected static final NullPointerException cachedNullPointerException;
+
+        static {
+            cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException();
+            cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]);
+            cachedNullPointerException = new NullPointerException();
+            cachedNullPointerException.setStackTrace(new StackTraceElement[0]);
+        }
+    }
+
+    public static final class RuntimeCalls {
+        public static final ForeignCallDescriptor CREATE_NULL_POINTER_EXCEPTION = new ForeignCallDescriptor("createNullPointerException", NullPointerException.class);
+        public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class);
+    }
+
+    private void lowerBytecodeExceptionNode(BytecodeExceptionNode node) {
+        StructuredGraph graph = node.graph();
         if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) {
-            ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, deferred.getDescriptor(), deferred.stamp(), deferred.getArguments()));
-            graph.replaceFixedWithFixed(deferred, foreignCallNode);
+            if (OmitHotExceptionStacktrace.getValue()) {
+                Throwable exception;
+                if (node.getExceptionClass() == NullPointerException.class) {
+                    exception = Exceptions.cachedNullPointerException;
+                } else if (node.getExceptionClass() == ArrayIndexOutOfBoundsException.class) {
+                    exception = Exceptions.cachedArrayIndexOutOfBoundsException;
+                } else {
+                    throw GraalInternalError.shouldNotReachHere();
+                }
+                FloatingNode exceptionNode = ConstantNode.forConstant(HotSpotObjectConstant.forObject(exception), metaAccess, graph);
+                graph.replaceFixedWithFloating(node, exceptionNode);
+
+            } else {
+                ForeignCallDescriptor descriptor;
+                if (node.getExceptionClass() == NullPointerException.class) {
+                    descriptor = RuntimeCalls.CREATE_NULL_POINTER_EXCEPTION;
+                } else if (node.getExceptionClass() == ArrayIndexOutOfBoundsException.class) {
+                    descriptor = RuntimeCalls.CREATE_OUT_OF_BOUNDS_EXCEPTION;
+                } else {
+                    throw GraalInternalError.shouldNotReachHere();
+                }
+
+                ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(), node.getArguments()));
+                graph.replaceFixedWithFixed(node, foreignCallNode);
+            }
         }
     }
 
@@ -703,6 +766,14 @@
 
         long displacement = 0;
         int indexScaling = 1;
+        boolean signExtend = false;
+        if (offset instanceof SignExtendNode) {
+            SignExtendNode extend = (SignExtendNode) offset;
+            if (extend.getResultBits() == 64) {
+                signExtend = true;
+                offset = extend.getInput();
+            }
+        }
         if (offset instanceof IntegerAddNode) {
             IntegerAddNode integerAddNode = (IntegerAddNode) offset;
             if (integerAddNode.y() instanceof ConstantNode) {
@@ -727,14 +798,17 @@
                 }
             }
         }
-
+        if (signExtend) {
+            // If we were using sign extended values before restore the sign extension.
+            offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64));
+        }
         return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling);
     }
 
     private static boolean addReadBarrier(UnsafeLoadNode load) {
         if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getKind() == Kind.Object && load.accessKind() == Kind.Object &&
-                        !ObjectStamp.isObjectAlwaysNull(load.object())) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(load.object());
+                        !StampTool.isObjectAlwaysNull(load.object())) {
+            ResolvedJavaType type = StampTool.typeOrNull(load.object());
             if (type != null && !type.isArray()) {
                 return true;
             }
@@ -755,18 +829,37 @@
         return metaspaceMethod;
     }
 
-    private FloatingReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) {
+    private ValueNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) {
         HotSpotVMConfig config = runtime.getConfig();
         LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        return graph.unique(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind), guard, BarrierType.NONE, config.useCompressedClassPointers));
+
+        Stamp hubStamp;
+        if (config.useCompressedClassPointers) {
+            hubStamp = StampFactory.forInteger(32);
+        } else {
+            hubStamp = StampFactory.forKind(wordKind);
+        }
+
+        FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(object, location, null, hubStamp, guard, BarrierType.NONE, false));
+        if (config.useCompressedClassPointers) {
+            return CompressionNode.uncompress(memoryRead, config.getKlassEncoding());
+        } else {
+            return memoryRead;
+        }
     }
 
     private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) {
         HotSpotVMConfig config = runtime.getConfig();
         LocationNode location = ConstantLocationNode.create(HUB_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        return graph.add(new WriteNode(object, value, location, BarrierType.NONE, config.useCompressedClassPointers));
+
+        ValueNode writeValue = value;
+        if (config.useCompressedClassPointers) {
+            writeValue = CompressionNode.compress(value, config.getKlassEncoding());
+        }
+
+        return graph.add(new WriteNode(object, writeValue, location, BarrierType.NONE, false));
     }
 
     private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) {
@@ -778,45 +871,53 @@
     }
 
     private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) {
-        BarrierType barrierType = BarrierType.NONE;
         if (storeField.field().getKind() == Kind.Object) {
-            barrierType = BarrierType.IMPRECISE;
+            return BarrierType.IMPRECISE;
         }
-        return barrierType;
+        return BarrierType.NONE;
     }
 
     private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) {
-        BarrierType barrierType = BarrierType.NONE;
         if (store.elementKind() == Kind.Object) {
-            barrierType = BarrierType.PRECISE;
+            return BarrierType.PRECISE;
         }
-        return barrierType;
+        return BarrierType.NONE;
     }
 
     private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) {
-        BarrierType barrierType = BarrierType.NONE;
         if (store.value().getKind() == Kind.Object) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(store.object());
+            ResolvedJavaType type = StampTool.typeOrNull(store.object());
             if (type != null && !type.isArray()) {
-                barrierType = BarrierType.IMPRECISE;
+                return BarrierType.IMPRECISE;
             } else {
-                barrierType = BarrierType.PRECISE;
+                return BarrierType.PRECISE;
             }
         }
-        return barrierType;
+        return BarrierType.NONE;
     }
 
-    private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
-        BarrierType barrierType = BarrierType.NONE;
+    private static BarrierType getCompareAndSwapBarrierType(CompareAndSwapNode cas) {
         if (cas.expected().getKind() == Kind.Object) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(cas.object());
+            ResolvedJavaType type = StampTool.typeOrNull(cas.object());
             if (type != null && !type.isArray()) {
-                barrierType = BarrierType.IMPRECISE;
+                return BarrierType.IMPRECISE;
             } else {
-                barrierType = BarrierType.PRECISE;
+                return BarrierType.PRECISE;
             }
         }
-        return barrierType;
+        return BarrierType.NONE;
+    }
+
+    private static BarrierType getAtomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) {
+        if (n.newValue().getKind() == Kind.Object) {
+            ResolvedJavaType type = StampTool.typeOrNull(n.object());
+            if (type != null && !type.isArray()) {
+                return BarrierType.IMPRECISE;
+            } else {
+                return BarrierType.PRECISE;
+            }
+        }
+        return BarrierType.NONE;
     }
 
     protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) {
@@ -902,7 +1003,7 @@
     }
 
     private static GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) {
-        if (ObjectStamp.isObjectNonNull(object)) {
+        if (StampTool.isObjectNonNull(object)) {
             return null;
         }
         return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.replacements.*;
 
@@ -54,7 +54,7 @@
         if (constant.getKind() != Kind.Object || constant.isNull()) {
             return null;
         }
-        Object o = constant.asObject();
+        Object o = HotSpotObjectConstant.asObject(constant);
         return HotSpotResolvedObjectType.fromClass(o.getClass());
     }
 
@@ -93,7 +93,7 @@
         }
     }
 
-    public ResolvedJavaMethod lookupJavaConstructor(Constructor reflectionConstructor) {
+    public ResolvedJavaMethod lookupJavaConstructor(Constructor<?> reflectionConstructor) {
         try {
             Class<?> holder = reflectionConstructor.getDeclaringClass();
             final int slot = reflectionConstructorSlot.getInt(reflectionConstructor);
@@ -295,7 +295,7 @@
             } else {
                 if (lookupJavaType.isArray()) {
                     // TODO(tw): Add compressed pointer support.
-                    int length = Array.getLength(constant.asObject());
+                    int length = Array.getLength(HotSpotObjectConstant.asObject(constant));
                     ResolvedJavaType elementType = lookupJavaType.getComponentType();
                     Kind elementKind = elementType.getKind();
                     final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstant.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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.hotspot.meta;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+
+public final class HotSpotMetaspaceConstant extends PrimitiveConstant {
+
+    private static final long serialVersionUID = 1003463314013122983L;
+
+    public static Constant forMetaspaceObject(Kind kind, long primitive, Object metaspaceObject) {
+        return new HotSpotMetaspaceConstant(kind, primitive, metaspaceObject);
+    }
+
+    public static Object getMetaspaceObject(Constant constant) {
+        return ((HotSpotMetaspaceConstant) constant).metaspaceObject;
+    }
+
+    private final Object metaspaceObject;
+
+    private HotSpotMetaspaceConstant(Kind kind, long primitive, Object metaspaceObject) {
+        super(kind, primitive);
+        this.metaspaceObject = metaspaceObject;
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode() ^ System.identityHashCode(metaspaceObject);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o == this || (o instanceof HotSpotMetaspaceConstant && super.equals(o) && Objects.equals(metaspaceObject, ((HotSpotMetaspaceConstant) o).metaspaceObject));
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "{" + metaspaceObject + "}";
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static java.lang.String.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,8 +24,6 @@
 
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 
@@ -40,8 +38,6 @@
  */
 public final class HotSpotNmethod extends HotSpotInstalledCode {
 
-    private static final long serialVersionUID = -1784683588947054103L;
-
     /**
      * This (indirect) Method* reference is safe since class redefinition preserves all methods
      * associated with nmethods in the code cache.
@@ -71,31 +67,25 @@
         return isExternal;
     }
 
-    @Override
     public ResolvedJavaMethod getMethod() {
         return method;
     }
 
     @Override
-    public boolean isValid() {
-        return getCodeBlob() != 0;
-    }
-
-    @Override
     public void invalidate() {
         runtime().getCompilerToVM().invalidateInstalledCode(this);
     }
 
     @Override
     public String toString() {
-        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getCodeBlob(), isDefault, name);
+        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getAddress(), isDefault, name);
     }
 
     protected boolean checkThreeObjectArgs() {
-        assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3;
+        assert method.getSignature().getParameterCount(!method.isStatic()) == 3;
         assert method.getSignature().getParameterKind(0) == Kind.Object;
         assert method.getSignature().getParameterKind(1) == Kind.Object;
-        assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object;
+        assert !method.isStatic() || method.getSignature().getParameterKind(2) == Kind.Object;
         return true;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,140 @@
+/*
+ * 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.hotspot.meta;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents a constant non-{@code null} object reference, within the compiler and across the
+ * compiler/runtime interface.
+ */
+public final class HotSpotObjectConstant extends Constant {
+
+    private static final long serialVersionUID = 3592151693708093496L;
+
+    public static Constant forObject(Object object) {
+        if (object == null) {
+            return Constant.NULL_OBJECT;
+        } else {
+            return new HotSpotObjectConstant(object);
+        }
+    }
+
+    public static Constant forBoxedValue(Kind kind, Object value) {
+        if (kind == Kind.Object) {
+            return HotSpotObjectConstant.forObject(value);
+        } else {
+            return Constant.forBoxedPrimitive(value);
+        }
+    }
+
+    public static Object asObject(Constant constant) {
+        if (constant.isNull()) {
+            return null;
+        } else {
+            return ((HotSpotObjectConstant) constant).object;
+        }
+    }
+
+    public static Object asBoxedValue(Constant constant) {
+        if (constant.isNull()) {
+            return null;
+        } else if (constant.getKind() == Kind.Object) {
+            return ((HotSpotObjectConstant) constant).object;
+        } else {
+            return constant.asBoxedPrimitive();
+        }
+    }
+
+    private final Object object;
+
+    private HotSpotObjectConstant(Object object) {
+        super(Kind.Object);
+        this.object = object;
+        assert object != null;
+    }
+
+    @Override
+    public boolean isNull() {
+        return false;
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return false;
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public int asInt() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public boolean asBoolean() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public long asLong() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public float asFloat() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public double asDouble() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public int hashCode() {
+        return System.identityHashCode(object);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o == this || (o instanceof HotSpotObjectConstant && super.equals(o) && object == ((HotSpotObjectConstant) o).object);
+    }
+
+    @Override
+    public String toValueString() {
+        if (object instanceof String) {
+            return (String) object;
+        } else {
+            return Kind.Object.format(object);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getKind().getJavaName() + "[" + Kind.Object.format(object) + "]";
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.meta;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
@@ -36,13 +37,16 @@
     private final HotSpotDisassemblerProvider disassembler;
     private final SuitesProvider suites;
     private final HotSpotRegistersProvider registers;
+    private final SnippetReflectionProvider snippetReflection;
 
     public HotSpotProviders(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls,
-                    LoweringProvider lowerer, Replacements replacements, HotSpotDisassemblerProvider disassembler, SuitesProvider suites, HotSpotRegistersProvider registers) {
+                    LoweringProvider lowerer, Replacements replacements, HotSpotDisassemblerProvider disassembler, SuitesProvider suites, HotSpotRegistersProvider registers,
+                    SnippetReflectionProvider snippetReflection) {
         super(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements);
         this.disassembler = disassembler;
         this.suites = suites;
         this.registers = registers;
+        this.snippetReflection = snippetReflection;
     }
 
     @Override
@@ -72,4 +76,7 @@
         return registers;
     }
 
+    public SnippetReflectionProvider getSnippetReflection() {
+        return snippetReflection;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,17 +23,16 @@
 package com.oracle.graal.hotspot.meta;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-import static java.lang.reflect.Modifier.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.replacements.*;
@@ -200,11 +199,10 @@
         assert !ImmutableCode.getValue() || isCalledForSnippets() : receiver;
 
         if (receiver == null) {
-            assert isStatic(modifiers);
-            if (Modifier.isFinal(getModifiers())) {
+            assert isStatic();
+            if (isFinal()) {
                 if (holder.isInitialized() && !holder.getName().equals(SystemClassName) && isEmbeddable()) {
                     return readValue(receiver);
-
                 }
             }
         } else {
@@ -212,14 +210,14 @@
              * for non-static final fields, we must assume that they are only initialized if they
              * have a non-default value.
              */
-            assert !isStatic(modifiers);
-            Object object = receiver.asObject();
+            assert !isStatic();
+            Object object = HotSpotObjectConstant.asObject(receiver);
 
             // Canonicalization may attempt to process an unsafe read before
             // processing a guard (e.g. a null check or a type check) for this read
             // so we need to check the object being read
             if (object != null && isInObject(object)) {
-                if (Modifier.isFinal(getModifiers())) {
+                if (isFinal()) {
                     Constant value = readValue(receiver);
                     if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) {
                         return value;
@@ -234,7 +232,7 @@
                     if (StableOptionValue.class.isAssignableFrom(clazz)) {
                         assert getName().equals("value") : "Unexpected field in " + StableOptionValue.class.getName() + " hierarchy:" + this;
                         StableOptionValue<?> option = (StableOptionValue<?>) object;
-                        return Constant.forObject(option.getValue());
+                        return HotSpotObjectConstant.forObject(option.getValue());
                     }
                 }
             }
@@ -244,12 +242,12 @@
 
     /**
      * Determines if a given object contains this field.
-     * 
+     *
      * @return true iff this is a non-static field and its declaring class is assignable from
      *         {@code object}'s class
      */
     public boolean isInObject(Object object) {
-        if (isStatic(modifiers)) {
+        if (isStatic()) {
             return false;
         }
         return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectType.fromClass(object.getClass()));
@@ -258,16 +256,15 @@
     @Override
     public Constant readValue(Constant receiver) {
         if (receiver == null) {
-            assert isStatic(modifiers);
+            assert isStatic();
             if (holder.isInitialized()) {
-                return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), holder.mirror(), offset, getKind() == Kind.Object);
+                return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), HotSpotObjectConstant.forObject(holder.mirror()), offset);
             }
             return null;
         } else {
-            assert !isStatic(modifiers);
-            Object object = receiver.asObject();
-            assert object != null && isInObject(object);
-            return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), object, offset, getKind() == Kind.Object);
+            assert !isStatic();
+            assert receiver.isNonNull() && isInObject(HotSpotObjectConstant.asObject(receiver));
+            return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver, offset);
         }
     }
 
@@ -332,7 +329,7 @@
 
     /**
      * Checks if this field has the {@link Stable} annotation.
-     * 
+     *
      * @return true if field has {@link Stable} annotation, false otherwise
      */
     public boolean isStable() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,18 +22,19 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
 import com.oracle.graal.nodes.*;
@@ -55,11 +56,10 @@
     private final HotSpotSignature signature;
     private HotSpotMethodData methodData;
     private byte[] code;
-    private SpeculationLog speculationLog;
 
     /**
      * Gets the holder of a HotSpot metaspace method native object.
-     * 
+     *
      * @param metaspaceMethod a metaspace Method object
      * @return the {@link ResolvedJavaType} corresponding to the holder of the
      *         {@code metaspaceMethod}
@@ -74,7 +74,7 @@
 
     /**
      * Gets the {@link ResolvedJavaMethod} for a HotSpot metaspace method native object.
-     * 
+     *
      * @param metaspaceMethod a metaspace Method object
      * @return the {@link ResolvedJavaMethod} corresponding to {@code metaspaceMethod}
      */
@@ -110,7 +110,7 @@
     /**
      * Returns a pointer to this method's constant method data structure (
      * {@code Method::_constMethod}).
-     * 
+     *
      * @return pointer to this method's ConstMethod
      */
     private long getConstMethod() {
@@ -134,7 +134,7 @@
 
     /**
      * Returns this method's flags ({@code Method::_flags}).
-     * 
+     *
      * @return flags of this method
      */
     private int getFlags() {
@@ -143,7 +143,7 @@
 
     /**
      * Returns this method's constant method flags ({@code ConstMethod::_flags}).
-     * 
+     *
      * @return flags of this method's ConstMethod
      */
     private int getConstMethodFlags() {
@@ -159,7 +159,11 @@
      * Gets the address of the C++ Method object for this method.
      */
     public Constant getMetaspaceMethodConstant() {
-        return Constant.forIntegerKind(getHostWordKind(), metaspaceMethod, this);
+        return HotSpotMetaspaceConstant.forMetaspaceObject(getHostWordKind(), metaspaceMethod, this);
+    }
+
+    public long getMetaspaceMethod() {
+        return metaspaceMethod;
     }
 
     @Override
@@ -182,8 +186,7 @@
 
     @Override
     public boolean canBeStaticallyBound() {
-        int modifiers = getModifiers();
-        return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) && !Modifier.isAbstract(modifiers);
+        return (isFinal() || isPrivate() || isStatic() || holder.isFinal()) && !isAbstract();
     }
 
     @Override
@@ -248,7 +251,7 @@
 
     /**
      * Returns true if this method has a {@code CallerSensitive} annotation.
-     * 
+     *
      * @return true if CallerSensitive annotation present, false otherwise
      */
     public boolean isCallerSensitive() {
@@ -257,7 +260,7 @@
 
     /**
      * Returns true if this method has a {@code ForceInline} annotation.
-     * 
+     *
      * @return true if ForceInline annotation present, false otherwise
      */
     public boolean isForceInline() {
@@ -266,7 +269,7 @@
 
     /**
      * Returns true if this method has a {@code DontInline} annotation.
-     * 
+     *
      * @return true if DontInline annotation present, false otherwise
      */
     public boolean isDontInline() {
@@ -283,7 +286,7 @@
     /**
      * Returns true if this method is one of the special methods that is ignored by security stack
      * walks.
-     * 
+     *
      * @return true if special method ignored by security stack walks, false otherwise
      */
     public boolean ignoredBySecurityStackWalk() {
@@ -310,18 +313,17 @@
 
     @Override
     public boolean isClassInitializer() {
-        return "<clinit>".equals(name) && Modifier.isStatic(getModifiers());
+        return "<clinit>".equals(name) && isStatic();
     }
 
     @Override
     public boolean isConstructor() {
-        return "<init>".equals(name) && !Modifier.isStatic(getModifiers());
+        return "<init>".equals(name) && !isStatic();
     }
 
     @Override
     public int getMaxLocals() {
-        int modifiers = getModifiers();
-        if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+        if (isAbstract() || isNative()) {
             return 0;
         }
         HotSpotVMConfig config = runtime().getConfig();
@@ -330,8 +332,7 @@
 
     @Override
     public int getMaxStackSize() {
-        int modifiers = getModifiers();
-        if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+        if (isAbstract() || isNative()) {
             return 0;
         }
         HotSpotVMConfig config = runtime().getConfig();
@@ -374,7 +375,7 @@
 
     /**
      * Gets the value of {@code Method::_code}.
-     * 
+     *
      * @return the value of {@code Method::_code}
      */
     private long getCompiledCode() {
@@ -384,7 +385,7 @@
 
     /**
      * Returns whether this method has compiled code.
-     * 
+     *
      * @return true if this method has compiled code, false otherwise
      */
     public boolean hasCompiledCode() {
@@ -451,7 +452,7 @@
     @Override
     public Annotation[][] getParameterAnnotations() {
         if (isConstructor()) {
-            Constructor javaConstructor = toJavaConstructor();
+            Constructor<?> javaConstructor = toJavaConstructor();
             return javaConstructor == null ? null : javaConstructor.getParameterAnnotations();
         }
         Method javaMethod = toJava();
@@ -486,7 +487,7 @@
     @Override
     public Type[] getGenericParameterTypes() {
         if (isConstructor()) {
-            Constructor javaConstructor = toJavaConstructor();
+            Constructor<?> javaConstructor = toJavaConstructor();
             return javaConstructor == null ? null : javaConstructor.getGenericParameterTypes();
         }
         Method javaMethod = toJava();
@@ -511,7 +512,7 @@
         }
     }
 
-    private Constructor toJavaConstructor() {
+    private Constructor<?> toJavaConstructor() {
         try {
             return holder.mirror().getDeclaredConstructor(signatureToTypes());
         } catch (NoSuchMethodException e) {
@@ -589,7 +590,7 @@
     /**
      * Returns the offset of this method into the v-table. The method must have a v-table entry as
      * indicated by {@link #isInVirtualMethodTable()}, otherwise an exception is thrown.
-     * 
+     *
      * @return the offset of this method into the v-table
      */
     public int vtableEntryOffset() {
@@ -608,19 +609,44 @@
 
     /**
      * Returns this method's virtual table index.
-     * 
+     *
      * @return virtual table index
      */
     private int getVtableIndex() {
+        assert !holder.isInterface();
         HotSpotVMConfig config = runtime().getConfig();
-        return unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset);
+        int result = unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset);
+        assert result >= config.nonvirtualVtableIndex : "must be linked";
+        return result;
     }
 
+    /**
+     * The {@link SpeculationLog} for methods compiled by Graal hang off this per-declaring-type
+     * {@link ClassValue}. The raw Method* value is safe to use as a key in the map as a) it is
+     * never moves and b) we never read from it.
+     * <p>
+     * One implication is that we will preserve {@link SpeculationLog}s for methods that have been
+     * redefined via class redefinition. It's tempting to periodically flush such logs but we cannot
+     * read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods
+     * are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal).
+     */
+    private static final ClassValue<Map<Long, SpeculationLog>> SpeculationLogs = new ClassValue<Map<Long, SpeculationLog>>() {
+        @Override
+        protected Map<Long, SpeculationLog> computeValue(java.lang.Class<?> type) {
+            return new HashMap<>(4);
+        }
+    };
+
     public SpeculationLog getSpeculationLog() {
-        if (speculationLog == null) {
-            speculationLog = new SpeculationLog();
+        Map<Long, SpeculationLog> map = SpeculationLogs.get(holder.mirror());
+        synchronized (map) {
+            SpeculationLog log = map.get(this.metaspaceMethod);
+            if (log == null) {
+                log = new HotSpotSpeculationLog();
+                map.put(metaspaceMethod, log);
+            }
+            return log;
         }
-        return speculationLog;
     }
 
     public int intrinsicId() {
@@ -636,13 +662,13 @@
 
         Object[] objArguments = new Object[arguments.length];
         for (int i = 0; i < arguments.length; i++) {
-            objArguments[i] = arguments[i].asBoxedValue();
+            objArguments[i] = HotSpotObjectConstant.asBoxedValue(arguments[i]);
         }
-        Object objReceiver = receiver != null ? receiver.asObject() : null;
+        Object objReceiver = receiver != null ? HotSpotObjectConstant.asObject(receiver) : null;
 
         try {
             Object objResult = javaMethod.invoke(objReceiver, objArguments);
-            return javaMethod.getReturnType() == void.class ? null : Constant.forBoxed(getSignature().getReturnKind(), objResult);
+            return javaMethod.getReturnType() == void.class ? null : HotSpotObjectConstant.forBoxedValue(getSignature().getReturnKind(), objResult);
 
         } catch (IllegalAccessException | InvocationTargetException ex) {
             throw new IllegalArgumentException(ex);
@@ -652,18 +678,18 @@
     @Override
     public Constant newInstance(Constant[] arguments) {
         assert isConstructor();
-        Constructor javaConstructor = toJavaConstructor();
+        Constructor<?> javaConstructor = toJavaConstructor();
         javaConstructor.setAccessible(true);
 
         Object[] objArguments = new Object[arguments.length];
         for (int i = 0; i < arguments.length; i++) {
-            objArguments[i] = arguments[i].asBoxedValue();
+            objArguments[i] = HotSpotObjectConstant.asBoxedValue(arguments[i]);
         }
 
         try {
             Object objResult = javaConstructor.newInstance(objArguments);
             assert objResult != null;
-            return Constant.forObject(objResult);
+            return HotSpotObjectConstant.forObject(objResult);
 
         } catch (IllegalAccessException | InvocationTargetException | InstantiationException ex) {
             throw new IllegalArgumentException(ex);
@@ -672,7 +698,7 @@
 
     /**
      * Allocates a compile id for this method by asking the VM for one.
-     * 
+     *
      * @param entryBCI entry bci
      * @return compile id
      */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,17 +23,15 @@
 package com.oracle.graal.hotspot.meta;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static java.lang.reflect.Modifier.*;
-
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.net.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -48,11 +46,6 @@
      */
     private final Class<?> javaClass;
 
-    /**
-     * Used for implemented a lazy binding from a {@link Node} type to a {@link NodeClass} value.
-     */
-    private NodeClass nodeClass;
-
     private HashMap<Long, HotSpotResolvedJavaField> fieldCache;
     private HashMap<Long, HotSpotResolvedJavaMethod> methodCache;
     private HotSpotResolvedJavaField[] instanceFields;
@@ -79,7 +72,7 @@
      */
     public static ResolvedJavaType fromMetaspaceKlass(long metaspaceKlass) {
         assert metaspaceKlass != 0;
-        Class javaClass = (Class) runtime().getCompilerToVM().readUnsafeUncompressedPointer(null, metaspaceKlass + runtime().getConfig().classMirrorOffset);
+        Class<?> javaClass = runtime().getCompilerToVM().getJavaMirror(metaspaceKlass);
         assert javaClass != null;
         return fromClass(javaClass);
     }
@@ -138,7 +131,7 @@
 
     @Override
     public ResolvedJavaType getComponentType() {
-        Class javaComponentType = mirror().getComponentType();
+        Class<?> javaComponentType = mirror().getComponentType();
         return javaComponentType == null ? null : fromClass(javaComponentType);
     }
 
@@ -146,7 +139,7 @@
     public ResolvedJavaType findUniqueConcreteSubtype() {
         HotSpotVMConfig config = runtime().getConfig();
         if (isArray()) {
-            return isFinal(getElementalType(this).getModifiers()) ? this : null;
+            return getElementalType(this).isFinal() ? this : null;
         } else if (isInterface()) {
             final long implementorMetaspaceKlass = runtime().getCompilerToVM().getKlassImplementor(metaspaceKlass());
 
@@ -162,20 +155,20 @@
              * than one implementors (see: InstanceKlass::add_implementor). The isInterface check
              * takes care of this fact since this class is an interface.
              */
-            if (isAbstract(type.getModifiers()) || type.isInterface() || !type.isLeafClass()) {
+            if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) {
                 return null;
             }
             return type;
         } else {
             HotSpotResolvedObjectType type = this;
-            while (isAbstract(type.getModifiers())) {
+            while (type.isAbstract()) {
                 long subklass = type.getSubklass();
                 if (subklass == 0 || unsafeReadWord(subklass + config.nextSiblingOffset) != 0) {
                     return null;
                 }
                 type = (HotSpotResolvedObjectType) fromMetaspaceKlass(subklass);
             }
-            if (isAbstract(type.getModifiers()) || type.isInterface() || !type.isLeafClass()) {
+            if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) {
                 return null;
             }
             return type;
@@ -204,14 +197,14 @@
 
     @Override
     public HotSpotResolvedObjectType getSuperclass() {
-        Class javaSuperclass = mirror().getSuperclass();
+        Class<?> javaSuperclass = mirror().getSuperclass();
         return javaSuperclass == null ? null : (HotSpotResolvedObjectType) fromClass(javaSuperclass);
     }
 
     @Override
     public ResolvedJavaType[] getInterfaces() {
         if (interfaces == null) {
-            Class[] javaInterfaces = mirror().getInterfaces();
+            Class<?>[] javaInterfaces = mirror().getInterfaces();
             ResolvedJavaType[] result = new ResolvedJavaType[javaInterfaces.length];
             for (int i = 0; i < javaInterfaces.length; i++) {
                 result[i] = fromClass(javaInterfaces[i]);
@@ -260,14 +253,14 @@
         if (isArray()) {
             return getComponentType().asExactType() != null ? this : null;
         }
-        return isFinal(getModifiers()) ? this : null;
+        return isFinal() ? this : null;
     }
 
     @Override
     public Constant getEncoding(Representation r) {
         switch (r) {
             case JavaClass:
-                return Constant.forObject(mirror());
+                return HotSpotObjectConstant.forObject(mirror());
             case ObjectHub:
                 return klass();
             default:
@@ -330,7 +323,7 @@
     @Override
     public boolean isInstance(Constant obj) {
         if (obj.getKind() == Kind.Object && !obj.isNull()) {
-            return mirror().isInstance(obj.asObject());
+            return mirror().isInstance(HotSpotObjectConstant.asObject(obj));
         }
         return false;
     }
@@ -363,7 +356,7 @@
     @Override
     public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) {
         assert method instanceof HotSpotMethod;
-        if (!isAbstract(method.getModifiers()) && method.getDeclaringClass().equals(this)) {
+        if (!method.isAbstract() && method.getDeclaringClass().equals(this)) {
             return method;
         }
 
@@ -372,7 +365,7 @@
             return null;
         }
         HotSpotResolvedJavaMethod resolvedMethod = HotSpotResolvedJavaMethod.fromMetaspace(resolvedMetaspaceMethod);
-        if (isAbstract(resolvedMethod.getModifiers())) {
+        if (resolvedMethod.isAbstract()) {
             return null;
         }
         return resolvedMethod;
@@ -661,7 +654,7 @@
      * Gets the metaspace Klass boxed in a {@link Constant}.
      */
     public Constant klass() {
-        return Constant.forIntegerKind(runtime().getTarget().wordKind, metaspaceKlass(), this);
+        return HotSpotMetaspaceConstant.forMetaspaceObject(runtime().getTarget().wordKind, metaspaceKlass(), this);
     }
 
     public boolean isPrimaryType() {
@@ -717,7 +710,7 @@
 
     @Override
     public ResolvedJavaMethod[] getDeclaredConstructors() {
-        Constructor[] constructors = mirror().getDeclaredConstructors();
+        Constructor<?>[] constructors = mirror().getDeclaredConstructors();
         ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
         for (int i = 0; i < constructors.length; i++) {
             result[i] = runtime().getHostProviders().getMetaAccess().lookupJavaConstructor(constructors[i]);
@@ -747,21 +740,7 @@
 
     @Override
     public Constant newArray(int length) {
-        return Constant.forObject(Array.newInstance(mirror(), length));
-    }
-
-    /**
-     * @return the {@link NodeClass} value (which may be {@code null}) associated with this type
-     */
-    public NodeClass getNodeClass() {
-        return nodeClass;
-    }
-
-    /**
-     * Sets the {@link NodeClass} value associated with this type.
-     */
-    public void setNodeClass(NodeClass nodeClass) {
-        this.nodeClass = nodeClass;
+        return HotSpotObjectConstant.forObject(Array.newInstance(mirror(), length));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 import java.net.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 
 /**
  * Implementation of {@link JavaType} for primitive HotSpot types.
@@ -253,6 +253,6 @@
 
     @Override
     public Constant newArray(int length) {
-        return Constant.forObject(Array.newInstance(mirror(), length));
+        return HotSpotObjectConstant.forObject(Array.newInstance(mirror(), length));
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.stubs.*;
 
 /**
@@ -32,8 +32,6 @@
  */
 public class HotSpotRuntimeStub extends HotSpotInstalledCode {
 
-    private static final long serialVersionUID = -6388648408298441748L;
-
     private final Stub stub;
 
     public HotSpotRuntimeStub(Stub stub) {
@@ -44,18 +42,21 @@
         return null;
     }
 
+    @Override
     public boolean isValid() {
         return true;
     }
 
+    @Override
     public void invalidate() {
     }
 
     @Override
     public String toString() {
-        return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", stub, getCodeBlob());
+        return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", stub, getAddress());
     }
 
+    @Override
     public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
         throw new GraalInternalError("Cannot call stub %s", stub);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.java.*;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.hotspot.meta;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+
+public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvider {
+
+    @Override
+    public Constant forObject(Object object) {
+        return HotSpotObjectConstant.forObject(object);
+    }
+
+    @Override
+    public Object asObject(Constant constant) {
+        return HotSpotObjectConstant.asObject(constant);
+    }
+
+    @Override
+    public Constant forBoxed(Kind kind, Object value) {
+        return HotSpotObjectConstant.forBoxedValue(kind, value);
+    }
+
+    @Override
+    public Object asBoxedValue(Constant constant) {
+        return HotSpotObjectConstant.asBoxedValue(constant);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSpeculationLog.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.hotspot.meta;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+public class HotSpotSpeculationLog extends SpeculationLog {
+
+    @Override
+    public Constant speculate(Object reason) {
+        addSpeculation(reason);
+        return HotSpotObjectConstant.forObject(reason);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.phases.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,17 +26,17 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 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;
+    private final Class<?>[] argumentTypes;
 
-    public HotSpotNativeFunctionHandle(InstalledCode code, String name, Class... argumentTypes) {
+    public HotSpotNativeFunctionHandle(InstalledCode code, String name, Class<?>... argumentTypes) {
         this.argumentTypes = argumentTypes;
         this.name = name;
         this.code = code;
@@ -63,7 +63,7 @@
         assert checkArgs(args);
         try {
             traceCall(args);
-            Object res = code.executeVarargs(args);
+            Object res = code.executeVarargs(args, null, null);
             traceResult(res);
             return res;
         } catch (InvalidInstalledCodeException e) {
@@ -76,7 +76,7 @@
         for (int i = 0; i < argumentTypes.length; i++) {
             Object arg = args[i];
             assert arg != null;
-            Class expectedType = argumentTypes[i];
+            Class<?> expectedType = argumentTypes[i];
             if (expectedType.isPrimitive()) {
                 Kind kind = Kind.fromJavaClass(expectedType);
                 expectedType = kind.toBoxedJavaClass();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,7 @@
 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.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.nfi.NativeCallStubGraphBuilder.*;
 
 import com.oracle.graal.api.code.*;
@@ -86,13 +86,13 @@
     }
 
     @Override
-    public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes) {
+    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) {
+    public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class<?> returnType, Class<?>... argumentTypes) {
         HotSpotNativeFunctionPointer functionPointer = null;
         for (NativeLibraryHandle libraryHandle : libraries) {
             functionPointer = lookupFunctionPointer(name, libraryHandle, false);
@@ -105,7 +105,7 @@
     }
 
     @Override
-    public HotSpotNativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes) {
+    public HotSpotNativeFunctionHandle getFunctionHandle(String name, Class<?> returnType, Class<?>... argumentTypes) {
         if (rtldDefault == null) {
             throw new UnsatisfiedLinkError(name);
         }
@@ -136,14 +136,14 @@
     }
 
     @Override
-    public HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) {
+    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) {
+    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);
@@ -152,7 +152,7 @@
     /**
      * Creates and installs a stub for calling a native function.
      */
-    private InstalledCode installNativeFunctionStub(long functionPointer, Class returnType, Class... argumentTypes) {
+    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();
@@ -161,7 +161,7 @@
                         DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, new CompilationResult(), CompilationResultBuilderFactory.Default);
         InstalledCode installedCode;
         try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) {
-            installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null);
+            installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null, null);
         }
         return installedCode;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,12 +27,12 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 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.*;
 
@@ -43,13 +43,13 @@
 
     /**
      * 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) {
+    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);
@@ -91,14 +91,14 @@
 
             ReturnNode returnNode = g.add(new ReturnNode(boxedResult));
             callNode.setNext(returnNode);
-            (new WordTypeRewriterPhase(providers.getMetaAccess(), Kind.Long)).apply(g);
+            (new WordTypeRewriterPhase(providers.getMetaAccess(), providers.getSnippetReflection(), 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) {
+    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++) {
@@ -111,7 +111,7 @@
                 last.setNext(boxedElement);
                 last = boxedElement;
             }
-            Class type = argumentTypes[i];
+            Class<?> type = argumentTypes[i];
             Kind kind = getKind(type);
             if (kind == Kind.Object) {
                 // array value
@@ -140,8 +140,8 @@
         return last;
     }
 
-    public static Kind getElementKind(Class clazz) {
-        Class componentType = clazz.getComponentType();
+    public static Kind getElementKind(Class<?> clazz) {
+        Class<?> componentType = clazz.getComponentType();
         if (componentType == null) {
             throw new IllegalArgumentException("Parameter type not supported: " + clazz);
         }
@@ -151,7 +151,7 @@
         throw new IllegalArgumentException("Parameter type not supported: " + clazz);
     }
 
-    private static Kind getKind(Class 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) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,12 +26,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Reserves a block of memory in the stack frame of a method. The block is reserved in the frame for
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -54,7 +54,7 @@
         ValueNode javaClass = getJavaClass();
         if (javaClass.isConstant()) {
             ValueNode object = getObject();
-            Class c = (Class) javaClass.asConstant().asObject();
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
             if (c != null && !c.isPrimitive()) {
                 HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
                 CheckCastNode checkcast = graph().add(new CheckCastNode(type, object, null, false));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,13 +24,14 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
 /**
  * {@link MacroNode Macro node} for {@link Class#getComponentType()}.
- * 
+ *
  * @see ClassSubstitutions#getComponentType(Class)
  */
 public class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable {
@@ -47,10 +48,10 @@
     public Node canonical(CanonicalizerTool tool) {
         ValueNode javaClass = getJavaClass();
         if (javaClass.isConstant()) {
-            Class c = (Class) javaClass.asConstant().asObject();
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
             if (c != null) {
-                Class componentType = c.getComponentType();
-                return ConstantNode.forObject(componentType, tool.getMetaAccess(), graph());
+                Class<?> componentType = c.getComponentType();
+                return ConstantNode.forConstant(HotSpotObjectConstant.forObject(componentType), tool.getMetaAccess(), graph());
             }
         }
         return this;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -47,7 +48,7 @@
     public Node canonical(CanonicalizerTool tool) {
         ValueNode javaClass = getJavaClass();
         if (javaClass.isConstant()) {
-            Class c = (Class) javaClass.asConstant().asObject();
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
             if (c != null) {
                 return ConstantNode.forInt(c.getModifiers(), graph());
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,13 +24,14 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
 /**
  * {@link MacroNode Macro node} for {@link Class#getSuperclass()}.
- * 
+ *
  * @see ClassSubstitutions#getSuperclass(Class)
  */
 public class ClassGetSuperclassNode extends MacroNode implements Canonicalizable {
@@ -47,10 +48,10 @@
     public Node canonical(CanonicalizerTool tool) {
         ValueNode javaClass = getJavaClass();
         if (javaClass.isConstant()) {
-            Class c = (Class) javaClass.asConstant().asObject();
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
             if (c != null) {
-                Class superclass = c.getSuperclass();
-                return ConstantNode.forObject(superclass, tool.getMetaAccess(), graph());
+                Class<?> superclass = c.getSuperclass();
+                return ConstantNode.forConstant(HotSpotObjectConstant.forObject(superclass), tool.getMetaAccess(), graph());
             }
         }
         return this;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -47,7 +48,7 @@
     public Node canonical(CanonicalizerTool tool) {
         ValueNode javaClass = getJavaClass();
         if (javaClass.isConstant()) {
-            Class c = (Class) javaClass.asConstant().asObject();
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
             if (c != null) {
                 return ConstantNode.forBoolean(c.isArray(), graph());
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -55,13 +55,13 @@
         ValueNode javaClass = getJavaClass();
         if (javaClass.isConstant()) {
             ValueNode object = getObject();
-            Class c = (Class) javaClass.asConstant().asObject();
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
             if (c != null) {
                 if (c.isPrimitive()) {
                     return ConstantNode.forBoolean(false, graph());
                 }
                 if (object.isConstant()) {
-                    Object o = object.asConstant().asObject();
+                    Object o = HotSpotObjectConstant.asObject(object.asConstant());
                     return ConstantNode.forBoolean(o != null && c.isInstance(o), graph());
                 }
                 HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -47,7 +48,7 @@
     public Node canonical(CanonicalizerTool tool) {
         ValueNode javaClass = getJavaClass();
         if (javaClass.isConstant()) {
-            Class c = (Class) javaClass.asConstant().asObject();
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
             if (c != null) {
                 return ConstantNode.forBoolean(c.isInterface(), graph());
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -47,7 +48,7 @@
     public Node canonical(CanonicalizerTool tool) {
         ValueNode javaClass = getJavaClass();
         if (javaClass.isConstant()) {
-            Class c = (Class) javaClass.asConstant().asObject();
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
             if (c != null) {
                 return ConstantNode.forBoolean(c.isPrimitive(), graph());
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.*;
@@ -73,7 +75,7 @@
                 } else if (input instanceof IntegerStamp) {
                     // compressed metaspace pointer
                     assert PrimitiveStamp.getBits(input) == 64;
-                    return StampFactory.forInteger(32, false);
+                    return StampFactory.forInteger(32);
                 }
                 break;
             case Uncompress:
@@ -84,7 +86,7 @@
                 } else if (input instanceof IntegerStamp) {
                     // metaspace pointer
                     assert PrimitiveStamp.getBits(input) == 32;
-                    return StampFactory.forInteger(64, false);
+                    return StampFactory.forInteger(64);
                 }
                 break;
         }
@@ -105,13 +107,21 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool();
+        boolean nonNull;
+        if (input.stamp() instanceof ObjectStamp) {
+            nonNull = StampTool.isObjectNonNull(input.stamp());
+        } else {
+            // metaspace pointers are never null
+            nonNull = true;
+        }
+
         Value result;
         switch (op) {
             case Compress:
-                result = hsGen.emitCompress(gen.operand(input), encoding);
+                result = hsGen.emitCompress(gen.operand(input), encoding, nonNull);
                 break;
             case Uncompress:
-                result = hsGen.emitUncompress(gen.operand(input), encoding);
+                result = hsGen.emitUncompress(gen.operand(input), encoding, nonNull);
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,11 +26,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Removes the current frame and tail calls the uncommon trap routine.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,8 +28,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.graal.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Emits code to enter a low-level stack frame specifically to call out to the C++ method
+ * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}.
+ */
+public class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable {
+
+    @Input private ValueNode framePc;
+    @Input private ValueNode senderSp;
+    @Input private ValueNode senderFp;
+
+    public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp) {
+        super(StampFactory.forVoid());
+        this.framePc = framePc;
+        this.senderSp = senderSp;
+        this.senderFp = senderFp;
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        Value operandValue = gen.operand(framePc);
+        Value senderSpValue = gen.operand(senderSp);
+        Value senderFpValue = gen.operand(senderFp);
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitEnterUnpackFramesStackFrame(operandValue, senderSpValue, senderFpValue);
+    }
+
+    @NodeIntrinsic
+    public static native void enterUnpackFramesStackFrame(Word framePc, Word senderSp, Word senderFp);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Intrinsification for getting the address of an object. The code path(s) between a call to
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,9 +26,9 @@
 
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
-import com.oracle.graal.nodes.type.*;
 
 public class HotSpotDirectCallTargetNode extends DirectCallTargetNode {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,8 +26,8 @@
 
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public class HotSpotIndirectCallTargetNode extends IndirectCallTargetNode {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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.graal.hotspot.nodes;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Emits code to leave (pop) the current low-level stack frame. This operation also removes the
+ * return address if its location is on the stack.
+ */
+public class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable {
+
+    public LeaveCurrentStackFrameNode() {
+        super(StampFactory.forVoid());
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveCurrentStackFrame();
+    }
+
+    @NodeIntrinsic
+    public static native void leaveCurrentStackFrame();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,57 @@
+/*
+ * 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.graal.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Emits code to leave (pop) the current low-level stack frame which is being deoptimized. This node
+ * is only used in {@link DeoptimizationStub}.
+ */
+public class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable {
+
+    @Input private ValueNode frameSize;
+    @Input private ValueNode initialInfo;
+
+    public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) {
+        super(StampFactory.forVoid());
+        this.frameSize = frameSize;
+        this.initialInfo = initialInfo;
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        Value frameSizeValue = gen.operand(frameSize);
+        Value initialInfoValue = gen.operand(initialInfo);
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveDeoptimizedStackFrame(frameSizeValue, initialInfoValue);
+    }
+
+    @NodeIntrinsic
+    public static native void leaveDeoptimizedStackFrame(int frameSize, Word initialInfo);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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.graal.hotspot.nodes;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Emits code to leave a low-level stack frame specifically to call out to the C++ method
+ * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}.
+ */
+public class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable {
+
+    public LeaveUnpackFramesStackFrameNode() {
+        super(StampFactory.forVoid());
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveUnpackFramesStackFrame();
+    }
+
+    @NodeIntrinsic
+    public static native void leaveUnpackFramesStackFrame();
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,8 +26,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,13 +24,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -63,7 +63,7 @@
     @Override
     public void generate(NodeLIRBuilder gen) {
         ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_ARRAY);
-        Variable result = gen.getLIRGenerator().emitForeignCall(linkage, this, gen.operand(hub), gen.operand(length));
+        Variable result = gen.getLIRGenerator().emitForeignCall(linkage, gen.state(this), gen.operand(hub), gen.operand(length));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -59,7 +59,7 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_INSTANCE);
-        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(hub));
+        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(hub));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 public class PrefetchAllocateNode extends FixedWithNextNode implements LIRGenLowerable {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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.graal.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.word.*;
+
+/**
+ * A call to the runtime code implementing the uncommon trap logic.
+ */
+public class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable {
+
+    @Input private ValueNode framePc;
+    @Input private ValueNode frameSize;
+    @Input private ValueNode senderSp;
+    @Input private ValueNode initialInfo;
+
+    public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) {
+        super(StampFactory.forVoid());
+        this.frameSize = frameSize;
+        this.framePc = framePc;
+        this.senderSp = senderSp;
+        this.initialInfo = initialInfo;
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        Value frameSizeValue = gen.operand(frameSize);
+        Value framePcValue = gen.operand(framePc);
+        Value senderSpValue = gen.operand(senderSp);
+        Value initialInfoValue = gen.operand(initialInfo);
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitPushInterpreterFrame(frameSizeValue, framePcValue, senderSpValue, initialInfoValue);
+    }
+
+    @NodeIntrinsic
+    public static native void pushInterpreterFrame(Word frameSize, Word framePc, Word senderSp, Word initialInfo);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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.graal.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Saves all allocatable registers.
+ */
+public class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable {
+
+    private SaveRegistersOp saveRegistersOp;
+
+    public SaveAllRegistersNode() {
+        super(StampFactory.forKind(Kind.Long));
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        saveRegistersOp = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitSaveAllRegisters();
+    }
+
+    /**
+     * @return the map from registers to the stack locations in they are saved
+     */
+    public SaveRegistersOp getSaveRegistersOp() {
+        assert saveRegistersOp != null : "saved registers op has not yet been created";
+        return saveRegistersOp;
+    }
+
+    /**
+     * @return a token that couples this node to an {@link UncommonTrapCallNode} so that the latter
+     *         has access to the {@linkplain SaveRegistersOp#getMap register save map}
+     */
+    @NodeIntrinsic
+    public static native long saveAllRegisters();
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Anchor, InputType.Guard})
 public final class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode {
@@ -37,7 +37,7 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        AbstractBeginNode prevBegin = BeginNode.prevBegin(this);
+        BeginNode prevBegin = BeginNode.prevBegin(this);
         replaceAtUsages(InputType.Anchor, prevBegin);
         replaceAtUsages(InputType.Guard, prevBegin);
         if (usages().isEmpty()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 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.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value})
 public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub.
@@ -68,7 +68,7 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         assert graph().start() instanceof StubStartNode;
-        ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor);
+        ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(descriptor);
         Value[] operands = operands(gen);
         Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, operands);
         if (result != null) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,19 +24,18 @@
 
 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.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Performs a tail call to the specified target compiled method, with the parameter taken from the
@@ -62,7 +61,7 @@
     public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) {
         HotSpotVMConfig config = runtime().getConfig();
         ResolvedJavaMethod method = frameState.method();
-        boolean isStatic = Modifier.isStatic(method.getModifiers());
+        boolean isStatic = method.isStatic();
 
         JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass());
         CallingConvention cc = res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.getLIRGeneratorTool().target(), false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,80 @@
+/*
+ * 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.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.word.*;
+
+/**
+ * A call to the runtime code implementing the uncommon trap logic.
+ */
+@NodeInfo(allowedUsageTypes = {InputType.Memory})
+public class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
+
+    @Input private ValueNode trapRequest;
+    @Input private SaveAllRegistersNode registerSaver;
+    private final ForeignCallsProvider foreignCalls;
+    public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("uncommonTrap", Word.class, Word.class, int.class);
+
+    public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) {
+        super(StampFactory.forKind(Kind.fromJavaClass(UNCOMMON_TRAP.getResultType())));
+        this.trapRequest = trapRequest;
+        this.registerSaver = (SaveAllRegistersNode) registerSaver;
+        this.foreignCalls = foreignCalls;
+    }
+
+    @Override
+    public LocationIdentity[] getLocationIdentities() {
+        return foreignCalls.getKilledLocations(UNCOMMON_TRAP);
+    }
+
+    public SaveRegistersOp getSaveRegistersOp() {
+        return registerSaver.getSaveRegistersOp();
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        Value trapRequestValue = gen.operand(trapRequest);
+        Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitUncommonTrapCall(trapRequestValue, getSaveRegistersOp());
+        gen.setResult(this, result);
+    }
+
+    @NodeIntrinsic
+    public static native Word uncommonTrap(long registerSaver, int trapRequest);
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return null;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,9 +27,9 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.hotspot.nodes.type;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.spi.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class NarrowOopStamp extends ObjectStamp {
 
@@ -76,7 +76,7 @@
     }
 
     @Override
-    public PlatformKind getPlatformKind(LIRTypeTool tool) {
+    public PlatformKind getPlatformKind(PlatformKindTool tool) {
         return NarrowOop;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,7 +25,9 @@
 import static com.oracle.graal.nodes.ConstantNode.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -44,7 +46,7 @@
     protected boolean verify(StructuredGraph graph, PhaseContext context) {
         for (ConstantNode node : getConstantNodes(graph)) {
             if (node.recordsUsages() || !node.gatherUsages(graph).isEmpty()) {
-                if (isObject(node) && !isNullReference(node) && !isInternedString(node)) {
+                if (isObject(node) && !isNullReference(node) && !isInternedString(node) && !isDirectMethodHandle(node)) {
                     throw new VerificationError("illegal object constant: " + node);
                 }
             }
@@ -57,7 +59,14 @@
     }
 
     private static boolean isNullReference(ConstantNode node) {
-        return isObject(node) && node.asConstant().asObject() == null;
+        return isObject(node) && node.asConstant().isNull();
+    }
+
+    private static boolean isDirectMethodHandle(ConstantNode node) {
+        if (!isObject(node)) {
+            return false;
+        }
+        return "Ljava/lang/invoke/DirectMethodHandle;".equals(StampTool.typeOrNull(node).getName());
     }
 
     @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
@@ -66,7 +75,7 @@
             return false;
         }
 
-        Object o = node.asConstant().asObject();
+        Object o = HotSpotObjectConstant.asObject(node.asConstant());
         if (!(o instanceof String)) {
             return false;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,10 +26,10 @@
 import static com.oracle.graal.nodes.ConstantNode.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -54,9 +54,9 @@
     }
 
     private FloatingReadNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, Constant constant) {
-        if (constant.getKind() == Kind.Object && constant.asObject() instanceof Class<?>) {
+        if (constant.getKind() == Kind.Object && HotSpotObjectConstant.asObject(constant) instanceof Class<?>) {
             MetaAccessProvider metaAccess = context.getMetaAccess();
-            ResolvedJavaType type = metaAccess.lookupJavaType((Class<?>) constant.asObject());
+            ResolvedJavaType type = metaAccess.lookupJavaType((Class<?>) HotSpotObjectConstant.asObject(constant));
             assert type instanceof HotSpotResolvedObjectType;
 
             Constant klass = ((HotSpotResolvedObjectType) type).klass();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.phases;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -75,12 +75,12 @@
     }
 
     protected void addG1PostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) {
-        final boolean alwaysNull = ObjectStamp.isObjectAlwaysNull(value);
+        final boolean alwaysNull = StampTool.isObjectAlwaysNull(value);
         graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(object, value, location, precise, alwaysNull)));
     }
 
     protected void addSerialPostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) {
-        final boolean alwaysNull = ObjectStamp.isObjectAlwaysNull(value);
+        final boolean alwaysNull = StampTool.isObjectAlwaysNull(value);
         final LocationNode loc = (precise ? location : null);
         graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(object, loc, precise, alwaysNull)));
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -52,7 +53,7 @@
 
     /**
      * Search for an instance field with the given name in a class.
-     * 
+     *
      * @param className name of the class to search in
      * @param fieldName name of the field to be searched
      * @return resolved java field
@@ -99,7 +100,7 @@
 
     /**
      * Get the receiver of a MethodHandle.invokeBasic call.
-     * 
+     *
      * @return the receiver argument node
      */
     private ValueNode getReceiver() {
@@ -108,7 +109,7 @@
 
     /**
      * Get the MemberName argument of a MethodHandle.linkTo* call.
-     * 
+     *
      * @return the MemberName argument node (which is the last argument)
      */
     private ValueNode getMemberName() {
@@ -118,7 +119,7 @@
     /**
      * Used from {@link MethodHandleInvokeBasicNode} to get the target {@link InvokeNode} if the
      * method handle receiver is constant.
-     * 
+     *
      * @return invoke node for the {@link java.lang.invoke.MethodHandle} target
      */
     protected InvokeNode getInvokeBasicTarget() {
@@ -137,7 +138,7 @@
      * Used from {@link MethodHandleLinkToStaticNode}, {@link MethodHandleLinkToSpecialNode},
      * {@link MethodHandleLinkToVirtualNode}, and {@link MethodHandleLinkToInterfaceNode} to get the
      * target {@link InvokeNode} if the member name argument is constant.
-     * 
+     *
      * @return invoke node for the member name target
      */
     protected InvokeNode getLinkToTarget() {
@@ -152,7 +153,7 @@
     /**
      * Helper function to get the {@link InvokeNode} for the vmtarget of a
      * java.lang.invoke.MemberName.
-     * 
+     *
      * @param memberName constant member name node
      * @return invoke node for the member name target
      */
@@ -162,7 +163,7 @@
         Constant vmtarget = memberNameVmtargetField.readValue(memberName);
 
         // Create a method from the vmtarget pointer
-        Class<?> c = (Class<?>) clazz.asObject();
+        Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(clazz);
         HotSpotResolvedObjectType holderClass = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
         HotSpotResolvedJavaMethod targetMethod = HotSpotResolvedJavaMethod.fromMetaspace(vmtarget.asLong());
 
@@ -171,7 +172,7 @@
         // to a direct call we must cast the receiver and arguments to its
         // actual types.
         HotSpotSignature signature = targetMethod.getSignature();
-        final boolean isStatic = Modifier.isStatic(targetMethod.getModifiers());
+        final boolean isStatic = targetMethod.isStatic();
         final int receiverSkip = isStatic ? 0 : 1;
 
         // Cast receiver to its type.
@@ -188,7 +189,7 @@
 
         // Try to get the most accurate receiver type
         if (this instanceof MethodHandleLinkToVirtualNode || this instanceof MethodHandleLinkToInterfaceNode) {
-            ResolvedJavaType receiverType = ObjectStamp.typeOrNull(getReceiver().stamp());
+            ResolvedJavaType receiverType = StampTool.typeOrNull(getReceiver().stamp());
             if (receiverType != null) {
                 ResolvedJavaMethod concreteMethod = receiverType.findUniqueConcreteMethod(targetMethod);
                 if (concreteMethod != null) {
@@ -212,7 +213,7 @@
     /**
      * Inserts a node to cast the argument at index to the given type if the given type is more
      * concrete than the argument type.
-     * 
+     *
      * @param index of the argument to be cast
      * @param type the type the argument should be cast to
      */
@@ -221,7 +222,7 @@
             ResolvedJavaType targetType = (ResolvedJavaType) type;
             if (!targetType.isPrimitive()) {
                 ValueNode argument = arguments.get(index);
-                ResolvedJavaType argumentType = ObjectStamp.typeOrNull(argument.stamp());
+                ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp());
                 if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) {
                     PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType)));
                     arguments.set(index, piNode);
@@ -233,12 +234,12 @@
     /**
      * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed
      * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}.
-     * 
+     *
      * @param targetMethod the method the be called
      * @return invoke node for the member name target
      */
     private InvokeNode createTargetInvokeNode(ResolvedJavaMethod targetMethod) {
-        InvokeKind invokeKind = Modifier.isStatic(targetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special;
+        InvokeKind invokeKind = targetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special;
         JavaType returnType = targetMethod.getSignature().getReturnType(null);
 
         // MethodHandleLinkTo* nodes have a trailing MemberName argument which
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
@@ -34,8 +36,6 @@
 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.graal.phases.*;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 import com.oracle.graal.runtime.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,6 +26,7 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.loop.phases.*;
@@ -33,7 +34,6 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -69,8 +69,8 @@
     }
 
     private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) {
-        ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp());
-        ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp());
+        ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp());
+        ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp());
 
         if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) {
             return null;
@@ -143,13 +143,13 @@
      * Returns true if this copy doesn't require store checks. Trivially true for primitive arrays.
      */
     private boolean isExact() {
-        ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp());
+        ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp());
         if (srcType.getComponentType().getKind().isPrimitive() || getSource() == getDestination()) {
             return true;
         }
 
-        ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp());
-        if (ObjectStamp.isExactType(getDestination().stamp())) {
+        ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp());
+        if (StampTool.isExactType(getDestination().stamp())) {
             if (destType != null && destType.isAssignableFrom(srcType)) {
                 return true;
             }
@@ -171,10 +171,10 @@
                     if (state.getState() == EscapeState.Virtual) {
                         type = state.getVirtualObject().type();
                     } else {
-                        type = ObjectStamp.typeOrNull(state.getMaterializedValue());
+                        type = StampTool.typeOrNull(state.getMaterializedValue());
                     }
                 } else {
-                    type = ObjectStamp.typeOrNull(entry);
+                    type = StampTool.typeOrNull(entry);
                 }
                 if (type == null || !destComponentType.isAssignableFrom(type)) {
                     return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,16 +22,16 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.GuardingPiNode.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -44,7 +45,7 @@
 
     private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccess, Assumptions assumptions) {
         if (getCallSite().isConstant() && !getCallSite().isNullConstant()) {
-            CallSite callSite = (CallSite) getCallSite().asConstant().asObject();
+            CallSite callSite = (CallSite) HotSpotObjectConstant.asObject(getCallSite().asConstant());
             MethodHandle target = callSite.getTarget();
             if (!(callSite instanceof ConstantCallSite)) {
                 if (assumptions == null || !assumptions.useOptimisticAssumptions()) {
@@ -52,7 +53,7 @@
                 }
                 assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target));
             }
-            return ConstantNode.forObject(target, metaAccess, graph());
+            return ConstantNode.forConstant(HotSpotObjectConstant.forObject(target), metaAccess, graph());
         }
         return null;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,14 +31,14 @@
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
@@ -69,8 +69,8 @@
 
         private final SnippetInfo dynamic = snippet(CheckCastDynamicSnippets.class, "checkcastDynamic");
 
-        public Templates(Providers providers, TargetDescription target) {
-            super(providers, target);
+        public Templates(HotSpotProviders providers, TargetDescription target) {
+            super(providers, providers.getSnippetReflection(), target);
         }
 
         public void lower(CheckCastDynamicNode checkcast, LoweringTool tool) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
@@ -63,35 +63,12 @@
     }
 
     @Fold
-    private static Class getAESCryptClass() {
+    private static Class<?> getAESCryptClass() {
         return AESCryptSubstitutions.AESCryptClass;
     }
 
-    @MethodSubstitution(isStatic = false, optional = true)
-    static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
-        if (getAESCryptClass().isInstance(embeddedCipher)) {
-            Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass);
-            crypt(rcvr, in, inOffset, inLength, out, outOffset, aesCipher, true);
-        } else {
-            encrypt(rcvr, in, inOffset, inLength, out, outOffset);
-        }
-    }
-
-    @MethodSubstitution(isStatic = false, optional = true)
-    static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
-        Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
-        if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
-            Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass);
-            crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false);
-        } else {
-            decrypt(realReceiver, in, inOffset, inLength, out, outOffset);
-        }
-    }
-
-    @MethodSubstitution(value = "encrypt", isStatic = false, optional = true)
-    static int encryptInt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
+    @MethodSubstitution(isStatic = false)
+    static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
         Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
         Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
@@ -99,12 +76,12 @@
             crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true);
             return inLength;
         } else {
-            return encryptInt(realReceiver, in, inOffset, inLength, out, outOffset);
+            return encrypt(realReceiver, in, inOffset, inLength, out, outOffset);
         }
     }
 
-    @MethodSubstitution(value = "decrypt", isStatic = false, optional = true)
-    static int decryptInt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
+    @MethodSubstitution(isStatic = false)
+    static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
         Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
         Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
@@ -112,7 +89,7 @@
             crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false);
             return inLength;
         } else {
-            return decryptInt(realReceiver, in, inOffset, inLength, out, outOffset);
+            return decrypt(realReceiver, in, inOffset, inLength, out, outOffset);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Substitutions for improving the performance of {@link CompositeValueClass#getClass()}.
+ */
+@ClassSubstitution(CompositeValueClass.class)
+public class CompositeValueClassSubstitutions {
+
+    /**
+     * A macro node for calls to {@link CompositeValueClass#get(Class)}. It can use the compiler's
+     * knowledge about node classes to replace itself with a constant value for a constant
+     * {@link Class} parameter.
+     */
+    public static class CompositeValueClassGetNode extends PureFunctionMacroNode {
+
+        public CompositeValueClassGetNode(Invoke invoke) {
+            super(invoke);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        protected Constant evaluate(Constant param, MetaAccessProvider metaAccess) {
+            if (param.isNull() || ImmutableCode.getValue()) {
+                return null;
+            }
+            return HotSpotObjectConstant.forObject(CompositeValueClass.get((Class<? extends CompositeValue>) HotSpotObjectConstant.asObject(param)));
+        }
+    }
+
+    @MacroSubstitution(isStatic = true, forced = true, macro = CompositeValueClassGetNode.class)
+    private static native CompositeValueClass get(Class<?> c);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Substitutions for improving the performance of {@link NodeClass#get}.
+ */
+@ClassSubstitution(NodeClass.class)
+public class HotSpotNodeClassSubstitutions {
+
+    /**
+     * A macro node for calls to {@link NodeClass#get(Class)}. It can use the compiler's knowledge
+     * about node classes to replace itself with a constant value for a constant {@link Class}
+     * parameter.
+     */
+    public static class NodeClassGetNode extends PureFunctionMacroNode {
+
+        public NodeClassGetNode(Invoke invoke) {
+            super(invoke);
+        }
+
+        @Override
+        protected Constant evaluate(Constant param, MetaAccessProvider metaAccess) {
+            if (param.isNull() || ImmutableCode.getValue()) {
+                return null;
+            }
+            return HotSpotObjectConstant.forObject(NodeClass.get((Class<?>) HotSpotObjectConstant.asObject(param)));
+        }
+    }
+
+    /**
+     * NOTE: A {@link MethodSubstitution} similar to
+     * {@link HotSpotNodeSubstitutions#getNodeClass(Node)} is not possible here because there is no
+     * guarantee that {@code c} is initialized (accessing a Class literal in Java is not a class
+     * initialization barrier).
+     */
+    @MacroSubstitution(isStatic = true, forced = true, macro = NodeClassGetNode.class)
+    public static native NodeClass get(Class<?> c);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.nodes.PiNode.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.word.*;
+
+@ClassSubstitution(Node.class)
+public class HotSpotNodeSubstitutions {
+
+    /**
+     * Gets the value of the {@code InstanceKlass::_graal_node_class} field from the InstanceKlass
+     * pointed to by {@code node}'s header.
+     */
+    @MethodSubstitution(isStatic = false)
+    public static NodeClass getNodeClass(final Node node) {
+        // HotSpot creates the NodeClass for each Node subclass while initializing it
+        // so we are guaranteed to read a non-null value here. As long as NodeClass
+        // is final, the stamp of the PiNode below will automatically be exact.
+        Word klass = loadHub(node);
+        return piCastNonNull(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
@@ -30,7 +30,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
@@ -80,6 +80,20 @@
         return config().threadExceptionPcOffset;
     }
 
+    public static final LocationIdentity LAST_JAVA_PC_LOCATION = new NamedLocationIdentity("LastJavaPc");
+
+    @Fold
+    public static int threadLastJavaPcOffset() {
+        return config().threadLastJavaPcOffset();
+    }
+
+    public static final LocationIdentity LAST_JAVA_FP_LOCATION = new NamedLocationIdentity("LastJavaFp");
+
+    @Fold
+    public static int threadLastJavaFpOffset() {
+        return config().threadLastJavaFpOffset();
+    }
+
     public static final LocationIdentity TLAB_TOP_LOCATION = new NamedLocationIdentity("TlabTop");
 
     @Fold
@@ -111,6 +125,16 @@
         return config().pendingExceptionOffset;
     }
 
+    public static final LocationIdentity PENDING_DEOPTIMIZATION_LOCATION = new NamedLocationIdentity("PendingDeoptimization");
+
+    /**
+     * @see HotSpotVMConfig#pendingDeoptimizationOffset
+     */
+    @Fold
+    private static int threadPendingDeoptimizationOffset() {
+        return config().pendingDeoptimizationOffset;
+    }
+
     public static final LocationIdentity OBJECT_RESULT_LOCATION = new NamedLocationIdentity("ObjectResult");
 
     @Fold
@@ -140,6 +164,14 @@
         thread.writeWord(threadExceptionPcOffset(), value, EXCEPTION_PC_LOCATION);
     }
 
+    public static void writeLastJavaPc(Word thread, Word value) {
+        thread.writeWord(threadLastJavaPcOffset(), value, LAST_JAVA_PC_LOCATION);
+    }
+
+    public static void writeLastJavaFp(Word thread, Word value) {
+        thread.writeWord(threadLastJavaFpOffset(), value, LAST_JAVA_FP_LOCATION);
+    }
+
     public static Word readTlabTop(Word thread) {
         return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION);
     }
@@ -174,6 +206,22 @@
     }
 
     /**
+     * Reads the pending deoptimization value for the given thread.
+     * 
+     * @return {@code true} if there was a pending deoptimization
+     */
+    public static int readPendingDeoptimization(Word thread) {
+        return thread.readInt(threadPendingDeoptimizationOffset(), PENDING_DEOPTIMIZATION_LOCATION);
+    }
+
+    /**
+     * Writes the pending deoptimization value for the given thread.
+     */
+    public static void writePendingDeoptimization(Word thread, int value) {
+        thread.writeInt(threadPendingDeoptimizationOffset(), value, PENDING_DEOPTIMIZATION_LOCATION);
+    }
+
+    /**
      * Gets and clears the object result from a runtime call stored in a thread local.
      *
      * @return the object that was in the thread local
@@ -498,6 +546,9 @@
     @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
     public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming);
 
+    @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true)
+    public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value);
+
     @SuppressWarnings("unused")
     @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
     private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity) {
@@ -556,6 +607,13 @@
         return config().arrayKlassOffset;
     }
 
+    public static final LocationIdentity KLASS_NODE_CLASS = new NamedLocationIdentity("KlassNodeClass");
+
+    @Fold
+    public static int klassNodeClassOffset() {
+        return config().klassNodeClassOffset;
+    }
+
     @Fold
     public static int classMirrorOffset() {
         return config().classMirrorOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -42,5 +42,8 @@
         replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class);
         replacements.registerSubstitutions(CRC32Substitutions.class);
         replacements.registerSubstitutions(ReflectionSubstitutions.class);
+        replacements.registerSubstitutions(HotSpotNodeClassSubstitutions.class);
+        replacements.registerSubstitutions(HotSpotNodeSubstitutions.class);
+        replacements.registerSubstitutions(CompositeValueClassSubstitutions.class);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints;
@@ -40,9 +41,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.options.*;
-import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
@@ -181,7 +180,7 @@
      * Type test used when the type being tested against is not known at compile time.
      */
     @Snippet
-    public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue) {
+    public static Object instanceofDynamic(Class<?> mirror, Object object, Object trueValue, Object falseValue) {
         if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
@@ -216,8 +215,8 @@
         private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary");
         private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic");
 
-        public Templates(Providers providers, TargetDescription target) {
-            super(providers, target);
+        public Templates(HotSpotProviders providers, TargetDescription target) {
+            super(providers, providers.getSnippetReflection(), target);
         }
 
         @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,12 +28,12 @@
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 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.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
@@ -66,7 +66,7 @@
         private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException");
 
         public Templates(HotSpotProviders providers, TargetDescription target) {
-            super(providers, target);
+            super(providers, providers.getSnippetReflection(), target);
         }
 
         public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -48,7 +48,6 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -417,8 +416,8 @@
 
         private final boolean useFastLocking;
 
-        public Templates(Providers providers, TargetDescription target, boolean useFastLocking) {
-            super(providers, target);
+        public Templates(HotSpotProviders providers, TargetDescription target, boolean useFastLocking) {
+            super(providers, providers.getSnippetReflection(), target);
             this.useFastLocking = useFastLocking;
         }
 
@@ -458,7 +457,7 @@
         }
 
         static boolean isTracingEnabledForType(ValueNode object) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(object.stamp());
+            ResolvedJavaType type = StampTool.typeOrNull(object.stamp());
             if (TRACE_TYPE_FILTER == null) {
                 return false;
             } else {
@@ -508,11 +507,11 @@
                     for (ReturnNode ret : rets) {
                         returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass());
                         String msg = "unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d";
-                        ConstantNode errMsg = ConstantNode.forObject(msg, providers.getMetaAccess(), graph);
+                        ConstantNode errMsg = ConstantNode.forConstant(HotSpotObjectConstant.forObject(msg), providers.getMetaAccess(), graph);
                         callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType));
                         invoke = graph.add(new InvokeNode(callTarget, 0));
                         List<ValueNode> stack = Collections.emptyList();
-                        FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false);
+                        FrameState stateAfter = new FrameState(graph.method(), BytecodeFrame.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false);
                         invoke.setStateAfter(graph.add(stateAfter));
                         graph.addBeforeFixed(ret, invoke);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,18 +24,19 @@
 
 import static com.oracle.graal.api.code.UnsignedMath.*;
 import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.Options.*;
 import static com.oracle.graal.nodes.PiArrayNode.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
@@ -46,9 +47,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.options.*;
-import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -106,7 +105,7 @@
         return ProfileAllocations.getValue();
     }
 
-    private static void profileAllocation(String path, long size, String typeContext) {
+    protected static void profileAllocation(String path, long size, String typeContext) {
         if (doProfile()) {
             String name = createName(path, typeContext);
 
@@ -348,7 +347,7 @@
     /**
      * Formats some allocated memory with an object header and zeroes out the rest.
      */
-    private static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean noAsserts, boolean useSnippetCounters) {
+    protected static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean noAsserts, boolean useSnippetCounters) {
         Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
         initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
@@ -382,8 +381,8 @@
         private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic");
         private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray");
 
-        public Templates(Providers providers, TargetDescription target) {
-            super(providers, target);
+        public Templates(HotSpotProviders providers, TargetDescription target) {
+            super(providers, providers.getSnippetReflection(), target);
         }
 
         /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,6 +29,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
@@ -59,7 +60,7 @@
             return null;
         }
 
-        ResolvedJavaType type = ObjectStamp.typeOrNull(getObject());
+        ResolvedJavaType type = StampTool.typeOrNull(getObject());
         if (type != null) {
             if (type.isArray()) {
                 Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getKind());
@@ -105,7 +106,7 @@
     /*
      * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an
      * exact type) and if it is a cloneable type.
-     * 
+     *
      * If yes, then the exact type is returned, otherwise it returns null.
      */
     private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.replacements.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
@@ -67,13 +67,10 @@
         if (usages().isEmpty()) {
             return null;
         } else {
-            Stamp stamp = getObject().stamp();
-            if (stamp instanceof ObjectStamp) {
-                ObjectStamp objectStamp = (ObjectStamp) stamp;
-                if (objectStamp.isExactType()) {
-                    Constant clazz = objectStamp.type().getEncoding(Representation.JavaClass);
-                    return ConstantNode.forConstant(clazz, tool.getMetaAccess(), graph());
-                }
+            if (StampTool.isExactType(getObject())) {
+                ResolvedJavaType type = StampTool.typeOrNull(getObject());
+                Constant clazz = type.getEncoding(Representation.JavaClass);
+                return ConstantNode.forConstant(clazz, tool.getMetaAccess(), graph());
             }
             return this;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.compiler.GraalCompiler.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -93,7 +94,7 @@
                     if (!method.ignoredBySecurityStackWalk()) {
                         // We have reached the desired frame; return the holder class.
                         HotSpotResolvedObjectType callerClass = method.getDeclaringClass();
-                        return ConstantNode.forObject(callerClass.mirror(), metaAccess, graph());
+                        return ConstantNode.forConstant(HotSpotObjectConstant.forObject(callerClass.mirror()), metaAccess, graph());
                     }
                     break;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,10 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -36,6 +37,6 @@
 
     @Override
     protected Constant evaluate(Constant param, MetaAccessProvider metaAccess) {
-        return ImmutableCode.getValue() || param.isNull() ? null : Constant.forInt(System.identityHashCode(param.asObject()));
+        return ImmutableCode.getValue() || param.isNull() ? null : Constant.forInt(System.identityHashCode(HotSpotObjectConstant.asObject(param)));
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,7 +29,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,11 +25,11 @@
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,10 +31,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
@@ -249,8 +249,8 @@
         private final SnippetInfo[] arraycopySnippets;
         private final SnippetInfo genericPrimitiveSnippet;
 
-        public Templates(Providers providers, TargetDescription target) {
-            super(providers, target);
+        public Templates(HotSpotProviders providers, TargetDescription target) {
+            super(providers, providers.getSnippetReflection(), target);
 
             arraycopySnippets = new SnippetInfo[Kind.values().length];
             arraycopySnippets[Kind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,10 +26,10 @@
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
@@ -52,8 +52,8 @@
 
         private final SnippetInfo unsafeLoad = snippet(UnsafeLoadSnippets.class, "lowerUnsafeLoad");
 
-        public Templates(Providers providers, TargetDescription target) {
-            super(providers, target);
+        public Templates(HotSpotProviders providers, TargetDescription target) {
+            super(providers, providers.getSnippetReflection(), target);
         }
 
         public void lower(UnsafeLoadNode load, LoweringTool tool) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
@@ -39,8 +40,6 @@
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
@@ -334,8 +333,8 @@
 
         private final CompressEncoding oopEncoding;
 
-        public Templates(Providers providers, TargetDescription target, CompressEncoding oopEncoding) {
-            super(providers, target);
+        public Templates(HotSpotProviders providers, TargetDescription target, CompressEncoding oopEncoding) {
+            super(providers, providers.getSnippetReflection(), target);
             this.oopEncoding = oopEncoding;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,277 @@
+/*
+ * 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.graal.hotspot.stubs;
+
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.hotspot.stubs.StubUtil.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Deoptimization stub.
+ *
+ * This is the entry point for code which is returning to a de-optimized frame.
+ *
+ * The steps taken by this frame are as follows:
+ *
+ * - push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all potentially
+ * live registers (at a pollpoint many registers can be live).
+ *
+ * - call the C routine: Deoptimization::fetch_unroll_info (this function returns information about
+ * the number and size of interpreter frames which are equivalent to the frame which is being
+ * deoptimized)
+ *
+ * - deallocate the unpack frame, restoring only results values. Other volatile registers will now
+ * be captured in the vframeArray as needed.
+ *
+ * - deallocate the deoptimization frame
+ *
+ * - in a loop using the information returned in the previous step push new interpreter frames (take
+ * care to propagate the return values through each new frame pushed)
+ *
+ * - create a dummy "unpack_frame" and save the return values (O0, O1, F0)
+ *
+ * - call the C routine: Deoptimization::unpack_frames (this function lays out values on the
+ * interpreter frame which was just created)
+ *
+ * - deallocate the dummy unpack_frame
+ *
+ * - ensure that all the return values are correctly set and then do a return to the interpreter
+ * entry point
+ */
+public class DeoptimizationStub extends SnippetStub {
+
+    private final TargetDescription target;
+
+    public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
+        super(providers, target, linkage);
+        this.target = target;
+    }
+
+    @Override
+    public boolean preservesRegisters() {
+        return false;
+    }
+
+    @Override
+    protected Object getConstantParameterValue(int index, String name) {
+        switch (index) {
+            case 0:
+                return providers.getRegisters().getThreadRegister();
+            case 1:
+                return providers.getRegisters().getStackPointerRegister();
+            default:
+                throw GraalInternalError.shouldNotReachHere("unknown parameter " + name + " at index " + index);
+        }
+    }
+
+    /**
+     * Uncommon trap.
+     *
+     * We save the argument return registers. We call the first C routine, fetch_unroll_info(). This
+     * routine captures the return values and returns a structure which describes the current frame
+     * size and the sizes of all replacement frames. The current frame is compiled code and may
+     * contain many inlined functions, each with their own JVM state. We pop the current frame, then
+     * push all the new frames. Then we call the C routine unpack_frames() to populate these frames.
+     * Finally unpack_frames() returns us the new target address. Notice that callee-save registers
+     * are BLOWN here; they have already been captured in the vframeArray at the time the return PC
+     * was patched.
+     *
+     * <p>
+     * <b>ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet
+     * because we change the current stack layout and so the code is very sensitive to register
+     * allocation.</b>
+     */
+    @Snippet
+    private static void uncommonTrapHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) {
+        final Word thread = registerAsWord(threadRegister);
+        long registerSaver = SaveAllRegistersNode.saveAllRegisters();
+
+        final int actionAndReason = readPendingDeoptimization(thread);
+        writePendingDeoptimization(thread, -1);
+
+        final Word unrollBlock = UncommonTrapCallNode.uncommonTrap(registerSaver, actionAndReason);
+
+        // Pop all the frames we must move/replace.
+        //
+        // Frame picture (youngest to oldest)
+        // 1: self-frame (no frame link)
+        // 2: deoptimizing frame (no frame link)
+        // 3: caller of deoptimizing frame (could be compiled/interpreted).
+
+        // Pop self-frame.
+        LeaveCurrentStackFrameNode.leaveCurrentStackFrame();
+
+        // Load the initial info we should save (e.g. frame pointer).
+        final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset());
+
+        // Pop deoptimized frame
+        final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset());
+        LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo);
+
+        /*
+         * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for
+         * total size of the interpreter frames plus shadow page size. Bang one page at a time
+         * because large sizes can bang beyond yellow and red zones.
+         */
+        final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset());
+        final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages();
+        Word stackPointer = readRegister(stackPointerRegister);
+
+        for (int i = 1; i < bangPages; i++) {
+            stackPointer.writeInt(-(i * pageSize()), i);
+        }
+
+        // Load number of interpreter frames.
+        final int numberOfFrames = unrollBlock.readInt(deoptimizationUnrollBlockNumberOfFramesOffset());
+
+        // Load address of array of frame sizes.
+        final Word frameSizes = unrollBlock.readWord(deoptimizationUnrollBlockFrameSizesOffset());
+
+        // Load address of array of frame PCs.
+        final Word framePcs = unrollBlock.readWord(deoptimizationUnrollBlockFramePcsOffset());
+
+        /*
+         * Get the current stack pointer (sender's original SP) before adjustment so that we can
+         * save it in the skeletal interpreter frame.
+         */
+        Word senderSp = readRegister(stackPointerRegister);
+
+        // Adjust old interpreter frame to make space for new frame's extra Java locals.
+        final int callerAdjustment = unrollBlock.readInt(deoptimizationUnrollBlockCallerAdjustmentOffset());
+        writeRegister(stackPointerRegister, readRegister(stackPointerRegister).subtract(callerAdjustment));
+
+        for (int i = 0; i < numberOfFrames; i++) {
+            final Word frameSize = frameSizes.readWord(i * wordSize());
+            final Word framePc = framePcs.readWord(i * wordSize());
+
+            // Push an interpreter frame onto the stack.
+            PushInterpreterFrameNode.pushInterpreterFrame(frameSize, framePc, senderSp, initialInfo);
+
+            // Get the current stack pointer (sender SP) and pass it to next frame.
+            senderSp = readRegister(stackPointerRegister);
+        }
+
+        // Get final return address.
+        final Word framePc = framePcs.readWord(numberOfFrames * wordSize());
+
+        /*
+         * Enter a frame to call out to unpack frames. Since we changed the stack pointer to an
+         * unknown alignment we need to align it here before calling C++ code.
+         */
+        final Word senderFp = initialInfo;
+        EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp);
+
+        // Pass uncommon trap mode to unpack frames.
+        final int mode = deoptimizationUnpackUncommonTrap();
+        unpackFrames(UNPACK_FRAMES, thread, mode);
+
+        LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame();
+    }
+
+    /**
+     * Reads the value of the passed register as a Word.
+     */
+    private static Word readRegister(Register register) {
+        return registerAsWord(register, false, false);
+    }
+
+    /**
+     * Writes the value of the passed register.
+     *
+     * @param value value the register should be set to
+     */
+    private static void writeRegister(Register register, Word value) {
+        writeRegisterAsWord(register, value);
+    }
+
+    @Fold
+    private static int stackShadowPages() {
+        return config().useStackBanging ? config().stackShadowPages : 0;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() {
+        return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockCallerAdjustmentOffset() {
+        return config().deoptimizationUnrollBlockCallerAdjustmentOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockNumberOfFramesOffset() {
+        return config().deoptimizationUnrollBlockNumberOfFramesOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockTotalFrameSizesOffset() {
+        return config().deoptimizationUnrollBlockTotalFrameSizesOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockFrameSizesOffset() {
+        return config().deoptimizationUnrollBlockFrameSizesOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockFramePcsOffset() {
+        return config().deoptimizationUnrollBlockFramePcsOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockInitialInfoOffset() {
+        return config().deoptimizationUnrollBlockInitialInfoOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnpackDeopt() {
+        return config().deoptimizationUnpackDeopt;
+    }
+
+    @Fold
+    private static int deoptimizationUnpackUncommonTrap() {
+        return config().deoptimizationUnpackUncommonTrap;
+    }
+
+    public static final ForeignCallDescriptor FETCH_UNROLL_INFO = descriptorFor(DeoptimizationStub.class, "fetchUnrollInfo");
+    public static final ForeignCallDescriptor UNPACK_FRAMES = descriptorFor(DeoptimizationStub.class, "unpackFrames");
+
+    @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
+    public static native Word fetchUnrollInfo(@ConstantNodeParameter ForeignCallDescriptor fetchUnrollInfo, Word thread);
+
+    @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
+    public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,7 @@
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition;
@@ -34,7 +35,6 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
@@ -63,7 +63,7 @@
 
     /**
      * Creates a stub for a call to code at a given address.
-     * 
+     *
      * @param address the address of the code to call
      * @param descriptor the signature of the call to this stub
      * @param prependThread true if the JavaThread value for the current thread is to be prepended
@@ -78,7 +78,7 @@
         super(providers, HotSpotForeignCallLinkage.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getForeignCalls(), descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee,
                         transition, reexecutable, killedLocations));
         this.prependThread = prependThread;
-        Class[] targetParameterTypes = createTargetParameters(descriptor);
+        Class<?>[] targetParameterTypes = createTargetParameters(descriptor);
         ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes);
         target = HotSpotForeignCallLinkage.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getForeignCalls(), targetSig, address, DESTROYS_REGISTERS, NativeCall, NativeCall,
                         transition, reexecutable, killedLocations);
@@ -91,10 +91,10 @@
         return target;
     }
 
-    private Class[] createTargetParameters(ForeignCallDescriptor descriptor) {
-        Class[] parameters = descriptor.getArgumentTypes();
+    private Class<?>[] createTargetParameters(ForeignCallDescriptor descriptor) {
+        Class<?>[] parameters = descriptor.getArgumentTypes();
         if (prependThread) {
-            Class[] newParameters = new Class[parameters.length + 1];
+            Class<?>[] newParameters = new Class[parameters.length + 1];
             System.arraycopy(parameters, 0, newParameters, 1, parameters.length);
             newParameters[0] = Word.class;
             return newParameters;
@@ -141,7 +141,7 @@
      * Creates a graph for this stub.
      * <p>
      * If the stub returns an object, the graph created corresponds to this pseudo code:
-     * 
+     *
      * <pre>
      *     Object foreignFunctionStub(args...) {
      *         foreignFunction(currentThread,  args);
@@ -152,10 +152,10 @@
      *         return verifyObject(getAndClearObjectResult(thread()));
      *     }
      * </pre>
-     * 
+     *
      * If the stub returns a primitive or word, the graph created corresponds to this pseudo code
      * (using {@code int} as the primitive return type):
-     * 
+     *
      * <pre>
      *     int foreignFunctionStub(args...) {
      *         int result = foreignFunction(currentThread,  args);
@@ -165,9 +165,9 @@
      *         return result;
      *     }
      * </pre>
-     * 
+     *
      * If the stub is void, the graph created corresponds to this pseudo code:
-     * 
+     *
      * <pre>
      *     void foreignFunctionStub(args...) {
      *         foreignFunction(currentThread,  args);
@@ -176,7 +176,7 @@
      *         }
      *     }
      * </pre>
-     * 
+     *
      * In each example above, the {@code currentThread} argument is the C++ JavaThread value (i.e.,
      * %r15 on AMD64) and is only prepended if {@link #prependThread} is true.
      */
@@ -203,8 +203,8 @@
             Debug.dump(graph, "Initial stub graph");
         }
 
-        kit.rewriteWordTypes();
-        kit.inlineInvokes();
+        kit.rewriteWordTypes(providers.getSnippetReflection());
+        kit.inlineInvokes(providers.getSnippetReflection());
 
         if (Debug.isDumpEnabled()) {
             Debug.dump(graph, "Stub graph before compilation");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
@@ -61,16 +60,10 @@
     protected Arguments makeArguments(SnippetInfo stub) {
         HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class);
 
-        // RuntimeStub cannot (currently) support oops or metadata embedded in the code so we
-        // convert the hub (i.e., Klass*) for int[] to be a naked word. This should be safe since
-        // the int[] class will never be unloaded.
-        Constant intArrayHub = intArrayType.klass();
-        intArrayHub = Constant.forIntegerKind(runtime().getTarget().wordKind, intArrayHub.asLong(), null);
-
         Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER);
         args.add("hub", null);
         args.add("length", null);
-        args.addConst("intArrayHub", intArrayHub);
+        args.addConst("intArrayHub", intArrayType.klass());
         args.addConst("threadRegister", providers.getRegisters().getThreadRegister());
         return args;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -65,7 +65,7 @@
         // convert the hub (i.e., Klass*) for int[] to be a naked word. This should be safe since
         // the int[] class will never be unloaded.
         Constant intArrayHub = intArrayType.klass();
-        intArrayHub = Constant.forIntegerKind(runtime().getTarget().wordKind, intArrayHub.asLong(), null);
+        intArrayHub = Constant.forIntegerKind(runtime().getTarget().wordKind, intArrayHub.asLong());
 
         Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER);
         args.add("hub", null);
@@ -231,7 +231,7 @@
      * @param log specifies if logging is enabled
      * @return the allocated chunk or {@link Word#zero()} if allocation fails
      */
-    static Word edenAllocate(Word sizeInBytes, boolean log) {
+    public static Word edenAllocate(Word sizeInBytes, boolean log) {
         Word heapTopAddress = Word.unsigned(heapTopAddress());
         Word heapEndAddress = Word.unsigned(heapEndAddress());
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,13 +26,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
@@ -45,8 +44,8 @@
 
     static class Template extends AbstractTemplates {
 
-        Template(Providers providers, TargetDescription target, Class<? extends Snippets> declaringClass) {
-            super(providers, target);
+        Template(HotSpotProviders providers, TargetDescription target, Class<? extends Snippets> declaringClass) {
+            super(providers, providers.getSnippetReflection(), target);
             this.info = snippet(declaringClass, null);
         }
 
@@ -65,7 +64,7 @@
 
     /**
      * Creates a new snippet stub.
-     * 
+     *
      * @param linkage linkage details for a call to the stub
      */
     public SnippetStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,18 +23,18 @@
 package com.oracle.graal.hotspot.stubs;
 
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
 import com.oracle.graal.hotspot.meta.*;
@@ -95,7 +95,7 @@
 
     /**
      * Creates a new stub.
-     * 
+     *
      * @param linkage linkage details for a call to the stub
      */
     public Stub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
@@ -125,8 +125,7 @@
     }
 
     /**
-     * Gets the method the stub's code will be {@linkplain InstalledCode#getMethod() associated}
-     * with once installed. This may be null.
+     * Gets the method the stub's code will be associated with once installed. This may be null.
      */
     protected abstract ResolvedJavaMethod getInstalledCodeOwner();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -69,7 +69,7 @@
         }
         assert found != null : "could not find foreign call named " + name + " in " + stubClass;
         List<Class<?>> paramList = Arrays.asList(found.getParameterTypes());
-        Class[] cCallTypes = paramList.subList(1, paramList.size()).toArray(new Class[paramList.size() - 1]);
+        Class<?>[] cCallTypes = paramList.subList(1, paramList.size()).toArray(new Class[paramList.size() - 1]);
         return new ForeignCallDescriptor(name, found.getReturnType(), cCallTypes);
     }
 
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Wed Apr 23 15:48:38 2014 +0200
@@ -131,6 +131,12 @@
     public static final Register d17 = new Register(81, 17, "d17", CPU);
     public static final Register d18 = new Register(82, 18, "d18", CPU);
     public static final Register d19 = new Register(83, 19, "d19", CPU);
+    public static final Register d20 = new Register(84, 20, "d20", CPU);
+
+    public static final Register threadRegister = d20;
+    public static final Register actionAndReasonReg = s32;
+    public static final Register codeBufferOffsetReg = s33;
+    public static final Register dregOopMapReg = s39;
 
     // @formatter:off
     public static final Register[] cRegisters = {
@@ -145,7 +151,7 @@
     };
 
     public static final Register[] dRegisters = {
-        d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15
+        d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, threadRegister
     };
 
     public static final Register[] qRegisters = {
@@ -154,9 +160,12 @@
 
     public static final Register[] allRegisters = {
         c0, c1, c2, c3, c4, c5, c6, c7, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15,
+        s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31,
         d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13,
         d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11,
-        q12, q13, q14, q15
+        q12, q13, q14, q15,
+        s32, s33, s34, s35, s36, s37, s38, s39,
+        d16, d17, d18, d19, threadRegister
     };
 
     // @formatter:on
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,7 +25,7 @@
 import java.io.*;
 import java.util.*;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.java.decompiler.block.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 import java.io.*;
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.java.decompiler.block.*;
 import com.oracle.graal.nodes.cfg.*;
 
@@ -46,7 +47,7 @@
             cfgBlocks.remove(0);
             if (firstBlock.isLoopHeader()) {
                 DecompilerLoopBlock loopBlock = new DecompilerLoopBlock(firstBlock, decompiler, decompiler.getSchedule(), infoStream);
-                Loop loop = firstBlock.getLoop();
+                Loop<Block> loop = firstBlock.getLoop();
 
                 for (int i = 0; i < cfgBlocks.size(); i++) {
                     if (loop.blocks.contains(cfgBlocks.get(i)) && cfgBlocks.get(i) != firstBlock) {
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerSyntaxLine.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerSyntaxLine.java	Wed Apr 23 15:48:38 2014 +0200
@@ -48,7 +48,7 @@
 
     protected static String getStringRepresentation(Node node) {
         if (node instanceof ConstantNode) {
-            return String.valueOf(((ConstantNode) node).asConstant().asBoxedValue());
+            return ((ConstantNode) node).asConstant().toValueString();
         } else if (node instanceof ParameterNode) {
             return "param_" + ((ParameterNode) node).index();
         } else {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,8 +25,6 @@
 
 import static com.oracle.graal.api.code.TypeCheckHints.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
-import static java.lang.reflect.Modifier.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -34,16 +32,15 @@
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.bytecode.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 
-public abstract class AbstractBytecodeParser<T extends KindProvider, F extends AbstractFrameStateBuilder<T>> {
+public abstract class AbstractBytecodeParser<T extends KindProvider, F extends AbstractFrameStateBuilder<T, F>> {
 
     static class Options {
         // @formatter:off
@@ -327,7 +324,7 @@
     private void genArithmeticOp(Kind result, int opcode) {
         T y = frameState.pop(result);
         T x = frameState.pop(result);
-        boolean isStrictFP = isStrict(method.getModifiers());
+        boolean isStrictFP = method.isStrict();
         T v;
         switch (opcode) {
             case IADD:
@@ -712,13 +709,6 @@
 
     protected abstract void emitNullCheck(T receiver);
 
-    protected static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException();
-    protected static final NullPointerException cachedNullPointerException = new NullPointerException();
-    static {
-        cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]);
-        cachedNullPointerException.setStackTrace(new StackTraceElement[0]);
-    }
-
     protected abstract void emitBoundsCheck(T index, T length);
 
     private static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions");
@@ -830,7 +820,7 @@
      *
      * @return an array of size successorCount with the accumulated probability for each successor.
      */
-    private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
+    public static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
         double[] probability = new double[successorCount];
         for (int i = 0; i < keySuccessors.length; i++) {
             probability[keySuccessors[i]] += keyProbabilities[i];
@@ -880,17 +870,11 @@
             }
         }
 
-        double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities);
-        T switchNode = append(genIntegerSwitch(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors));
-        for (int i = 0; i < actualSuccessors.size(); i++) {
-            setBlockSuccessor(switchNode, i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState));
-        }
+        genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors);
 
     }
 
-    protected abstract void setBlockSuccessor(T switchNode, int i, T createBlockTarget);
-
-    protected abstract T genIntegerSwitch(T value, int size, int[] keys, double[] keyProbabilities, int[] keySuccessors);
+    protected abstract void genIntegerSwitch(T value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors);
 
     private static class SuccessorInfo {
 
@@ -911,18 +895,8 @@
         return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI;
     }
 
-    protected abstract T genDeoptimization();
-
-    /**
-     * Returns a block begin node with the specified state. If the specified probability is 0, the
-     * block deoptimizes immediately.
-     */
-    protected abstract T createBlockTarget(double probability, BciBlock bciBlock, AbstractFrameStateBuilder<T> stateAfter);
-
     protected abstract void processBlock(BciBlock block);
 
-    protected abstract void appendGoto(T target);
-
     protected abstract void iterateBytecodesForBlock(BciBlock block);
 
     public void processBytecode(int bci, int opcode) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,19 +23,88 @@
 
 package com.oracle.graal.java;
 
-import com.oracle.graal.api.meta.*;
+import java.util.*;
 
-public abstract class AbstractFrameStateBuilder<T extends KindProvider> {
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.java.BciBlockMapping.BciBlock;
+import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
+
+public abstract class AbstractFrameStateBuilder<T extends KindProvider, S extends AbstractFrameStateBuilder<T, S>> {
 
     protected final ResolvedJavaMethod method;
     protected int stackSize;
+    protected final T[] locals;
+    protected final T[] stack;
+    protected T[] lockedObjects;
 
-    public AbstractFrameStateBuilder(ResolvedJavaMethod method) {
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    protected boolean rethrowException;
+
+    public AbstractFrameStateBuilder(ResolvedJavaMethod method, T[] l, T[] s, T[] lo) {
         this.method = method;
+        this.locals = l;
+        this.stack = s;
+        this.lockedObjects = lo;
+    }
+
+    protected AbstractFrameStateBuilder(S other) {
+        this.method = other.method;
+        this.stackSize = other.stackSize;
+        this.locals = other.locals.clone();
+        this.stack = other.stack.clone();
+        this.lockedObjects = other.lockedObjects == getEmtpyArray() ? getEmtpyArray() : other.lockedObjects.clone();
+        this.rethrowException = other.rethrowException;
+
+        assert locals.length == method.getMaxLocals();
+        assert stack.length == Math.max(1, method.getMaxStackSize());
     }
 
-    protected AbstractFrameStateBuilder(AbstractFrameStateBuilder other) {
-        this.method = other.method;
+    public abstract S copy();
+
+    protected abstract T[] getEmtpyArray();
+
+    public abstract boolean isCompatibleWith(S other);
+
+    public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) {
+        /*
+         * (lstadler) if somebody is tempted to remove/disable this clearing code: it's possible to
+         * remove it for normal compilations, but not for OSR compilations - otherwise dead object
+         * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with
+         * Kind.Illegal, because the conflicting branch might not have been parsed.
+         */
+        if (liveness == null) {
+            return;
+        }
+        if (liveIn) {
+            for (int i = 0; i < locals.length; i++) {
+                if (!liveness.localIsLiveIn(block, i)) {
+                    locals[i] = null;
+                }
+            }
+        } else {
+            for (int i = 0; i < locals.length; i++) {
+                if (!liveness.localIsLiveOut(block, i)) {
+                    locals[i] = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    public boolean rethrowException() {
+        return rethrowException;
+    }
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    public void setRethrowException(boolean b) {
+        rethrowException = b;
     }
 
     /**
@@ -43,7 +112,9 @@
      *
      * @return the size of the local variables
      */
-    public abstract int localsSize();
+    public int localsSize() {
+        return locals.length;
+    }
 
     /**
      * Gets the current size (height) of the stack.
@@ -58,7 +129,9 @@
      * @param i the index into the locals
      * @return the instruction that produced the value for the specified local
      */
-    public abstract T localAt(int i);
+    public T localAt(int i) {
+        return locals[i];
+    }
 
     /**
      * Get the value on the stack at the specified stack index.
@@ -66,7 +139,9 @@
      * @param i the index into the stack, with {@code 0} being the bottom of the stack
      * @return the instruction at the specified position in the stack
      */
-    public abstract T stackAt(int i);
+    public T stackAt(int i) {
+        return stack[i];
+    }
 
     /**
      * Loads the local variable at the specified index, checking that the returned value is non-null
@@ -75,7 +150,12 @@
      * @param i the index of the local variable to load
      * @return the instruction that produced the specified local
      */
-    public abstract T loadLocal(int i);
+    public T loadLocal(int i) {
+        T x = locals[i];
+        assert !isTwoSlot(x.getKind()) || locals[i + 1] == null;
+        assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind());
+        return x;
+    }
 
     /**
      * Stores a given local variable at the specified index. If the value occupies two slots, then
@@ -84,9 +164,26 @@
      * @param i the index at which to store
      * @param x the instruction which produces the value for the local
      */
-    public abstract void storeLocal(int i, T x);
+    public void storeLocal(int i, T x) {
+        assert x == null || x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x;
+        locals[i] = x;
+        if (x != null && isTwoSlot(x.getKind())) {
+            // if this is a double word, then kill i+1
+            locals[i + 1] = null;
+        }
+        if (x != null && i > 0) {
+            T p = locals[i - 1];
+            if (p != null && isTwoSlot(p.getKind())) {
+                // if there was a double word at i - 1, then kill it
+                locals[i - 1] = null;
+            }
+        }
+    }
 
-    public abstract void storeStack(int i, T x);
+    public void storeStack(int i, T x) {
+        assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values";
+        stack[i] = x;
+    }
 
     /**
      * Pushes an instruction onto the stack with the expected type.
@@ -94,51 +191,76 @@
      * @param kind the type expected for this instruction
      * @param x the instruction to push onto the stack
      */
-    public abstract void push(Kind kind, T x);
+    public void push(Kind kind, T x) {
+        assert x.getKind() != Kind.Void && x.getKind() != Kind.Illegal;
+        xpush(assertKind(kind, x));
+        if (isTwoSlot(kind)) {
+            xpush(null);
+        }
+    }
 
     /**
      * Pushes a value onto the stack without checking the type.
      *
      * @param x the instruction to push onto the stack
      */
-    public abstract void xpush(T x);
+    public void xpush(T x) {
+        assert x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal);
+        stack[stackSize++] = x;
+    }
 
     /**
      * Pushes a value onto the stack and checks that it is an int.
      *
      * @param x the instruction to push onto the stack
      */
-    public abstract void ipush(T x);
+    public void ipush(T x) {
+        xpush(assertInt(x));
+    }
 
     /**
      * Pushes a value onto the stack and checks that it is a float.
      *
      * @param x the instruction to push onto the stack
      */
-    public abstract void fpush(T x);
+    public void fpush(T x) {
+        xpush(assertFloat(x));
+    }
 
     /**
      * Pushes a value onto the stack and checks that it is an object.
      *
      * @param x the instruction to push onto the stack
      */
-    public abstract void apush(T x);
+    public void apush(T x) {
+        xpush(assertObject(x));
+    }
 
     /**
      * Pushes a value onto the stack and checks that it is a long.
      *
      * @param x the instruction to push onto the stack
      */
-    public abstract void lpush(T x);
+    public void lpush(T x) {
+        xpush(assertLong(x));
+        xpush(null);
+    }
 
     /**
      * Pushes a value onto the stack and checks that it is a double.
      *
      * @param x the instruction to push onto the stack
      */
-    public abstract void dpush(T x);
+    public void dpush(T x) {
+        xpush(assertDouble(x));
+        xpush(null);
+    }
 
-    public abstract void pushReturn(Kind kind, T x);
+    public void pushReturn(Kind kind, T x) {
+        if (kind != Kind.Void) {
+            push(kind.getStackKind(), x);
+        }
+    }
 
     /**
      * Pops an instruction off the stack with the expected type.
@@ -146,49 +268,70 @@
      * @param kind the expected type
      * @return the instruction on the top of the stack
      */
-    public abstract T pop(Kind kind);
+    public T pop(Kind kind) {
+        assert kind != Kind.Void;
+        if (isTwoSlot(kind)) {
+            xpop();
+        }
+        return assertKind(kind, xpop());
+    }
 
     /**
      * Pops a value off of the stack without checking the type.
      *
      * @return x the instruction popped off the stack
      */
-    public abstract T xpop();
+    public T xpop() {
+        T result = stack[--stackSize];
+        return result;
+    }
 
     /**
      * Pops a value off of the stack and checks that it is an int.
      *
      * @return x the instruction popped off the stack
      */
-    public abstract T ipop();
+    public T ipop() {
+        return assertInt(xpop());
+    }
 
     /**
      * Pops a value off of the stack and checks that it is a float.
      *
      * @return x the instruction popped off the stack
      */
-    public abstract T fpop();
+    public T fpop() {
+        return assertFloat(xpop());
+    }
 
     /**
      * Pops a value off of the stack and checks that it is an object.
      *
      * @return x the instruction popped off the stack
      */
-    public abstract T apop();
+    public T apop() {
+        return assertObject(xpop());
+    }
 
     /**
      * Pops a value off of the stack and checks that it is a long.
      *
      * @return x the instruction popped off the stack
      */
-    public abstract T lpop();
+    public T lpop() {
+        assertHigh(xpop());
+        return assertLong(xpop());
+    }
 
     /**
      * Pops a value off of the stack and checks that it is a double.
      *
      * @return x the instruction popped off the stack
      */
-    public abstract T dpop();
+    public T dpop() {
+        assertHigh(xpop());
+        return assertDouble(xpop());
+    }
 
     /**
      * Pop the specified number of slots off of this stack and return them as an array of
@@ -196,7 +339,19 @@
      *
      * @return an array containing the arguments off of the stack
      */
-    public abstract T[] popArguments(int slotSize, int argSize);
+    public T[] popArguments(int slotSize, int argSize) {
+        int base = stackSize - slotSize;
+        List<T> r = new ArrayList<>(argSize);
+        int stackindex = 0;
+        while (stackindex < slotSize) {
+            T element = stack[base + stackindex];
+            assert element != null;
+            r.add(element);
+            stackindex += stackSlots(element.getKind());
+        }
+        stackSize = base;
+        return r.toArray(getEmtpyArray());
+    }
 
     /**
      * Peeks an element from the operand stack.
@@ -206,7 +361,17 @@
      *            ignored.
      * @return The peeked argument.
      */
-    public abstract T peek(int argumentNumber);
+    public T peek(int argumentNumber) {
+        int idx = stackSize() - 1;
+        for (int i = 0; i < argumentNumber; i++) {
+            if (stackAt(idx) == null) {
+                idx--;
+                assert isTwoSlot(stackAt(idx).getKind());
+            }
+            idx--;
+        }
+        return stackAt(idx);
+    }
 
     public static int stackSlots(Kind kind) {
         return isTwoSlot(kind) ? 2 : 1;
@@ -224,4 +389,38 @@
         return kind == Kind.Long || kind == Kind.Double;
     }
 
+    private T assertKind(Kind kind, T x) {
+        assert x != null && x.getKind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind());
+        return x;
+    }
+
+    private T assertLong(T x) {
+        assert x != null && (x.getKind() == Kind.Long);
+        return x;
+    }
+
+    private T assertInt(T x) {
+        assert x != null && (x.getKind() == Kind.Int);
+        return x;
+    }
+
+    private T assertFloat(T x) {
+        assert x != null && (x.getKind() == Kind.Float);
+        return x;
+    }
+
+    private T assertObject(T x) {
+        assert x != null && (x.getKind() == Kind.Object);
+        return x;
+    }
+
+    private T assertDouble(T x) {
+        assert x != null && (x.getKind() == Kind.Double);
+        return x;
+    }
+
+    private void assertHigh(T x) {
+        assert x == null;
+    }
+
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,17 +23,17 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.bytecode.Bytecodes.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.bytecode.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph
@@ -82,12 +82,14 @@
         public boolean isLoopHeader;
         public int loopId;
 
-        public FixedWithNextNode firstInstruction;
-        public HIRFrameStateBuilder entryState;
+        /**
+         * XXX to be removed - currently only used by baseline compiler
+         */
+        public Loop<BciBlock> loop;
+        public boolean isLoopEnd;
 
-        // public ArrayList<BciBlock> successors = new ArrayList<>(2);
-        // public ArrayList<BciBlock> predecessors = new ArrayList<>(2); // only used in the
-        // baseline
+        public FixedWithNextNode firstInstruction;
+        public AbstractFrameStateBuilder<?, ?> entryState;
 
         public long exits;
 
@@ -148,14 +150,12 @@
             return sb.toString();
         }
 
-        public Loop getLoop() {
-            // TODO Auto-generated method stub
-            return null;
+        public Loop<BciBlock> getLoop() {
+            return loop;
         }
 
         public int getLoopDepth() {
-            // TODO Auto-generated method stub
-            return 0;
+            return Long.bitCount(loops);
         }
 
         public boolean isLoopHeader() {
@@ -163,13 +163,11 @@
         }
 
         public boolean isLoopEnd() {
-            // TODO Auto-generated method stub
-            return false;
+            return isLoopEnd;
         }
 
         public boolean isExceptionEntry() {
-            // TODO Auto-generated method stub
-            return false;
+            return isExceptionEntry;
         }
 
         public BciBlock getSuccessor(int index) {
@@ -720,6 +718,10 @@
         for (BciBlock successor : block.getSuccessors()) {
             // Recursively process successors.
             loops |= computeBlockOrder(successor);
+            if (block.visited && successor.active) {
+                // Reached block via backward branch.
+                block.isLoopEnd = true;
+            }
         }
 
         block.loops = loops;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -117,26 +117,7 @@
                         String desc = null;
                         if (constant instanceof Constant) {
                             Constant c = ((Constant) constant);
-                            switch (c.getKind()) {
-                                case Int :
-                                    desc = String.valueOf(c.asInt());
-                                    break;
-                                case Float:
-                                    desc = String.valueOf(c.asFloat());
-                                    break;
-                                case Object:
-                                    desc = Kind.Object.format(c.asObject());
-                                    break;
-                                case Double :
-                                    desc = String.valueOf(c.asDouble());
-                                    break;
-                                case Long :
-                                    desc = String.valueOf(c.asLong());
-                                    break;
-                                default:
-                                    desc = c.toString();
-                                    break;
-                            }
+                            desc = c.toValueString();
                         } else {
                             desc = constant.toString();
                         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,11 +25,7 @@
 import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
-import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-import static java.lang.reflect.Modifier.*;
-
-import java.lang.reflect.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -37,6 +33,9 @@
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.bytecode.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
@@ -45,7 +44,6 @@
 import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
@@ -59,12 +57,6 @@
  */
 public class GraphBuilderPhase extends BasePhase<HighTierContext> {
 
-    public static final class RuntimeCalls {
-
-        public static final ForeignCallDescriptor CREATE_NULL_POINTER_EXCEPTION = new ForeignCallDescriptor("createNullPointerException", NullPointerException.class);
-        public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class);
-    }
-
     private final GraphBuilderConfiguration graphBuilderConfig;
 
     public GraphBuilderPhase(GraphBuilderConfiguration graphBuilderConfig) {
@@ -122,13 +114,10 @@
             }
         }
 
-        private BciBlock[] loopHeaders;
-        private LocalLiveness liveness;
-
         /**
          * Gets the current frame state being processed by this builder.
          */
-        protected AbstractFrameStateBuilder<ValueNode> getCurrentFrameState() {
+        protected HIRFrameStateBuilder getCurrentFrameState() {
             return parser.getFrameState();
         }
 
@@ -200,6 +189,8 @@
 
         class BytecodeParser extends AbstractBytecodeParser<ValueNode, HIRFrameStateBuilder> {
 
+            private BciBlock[] loopHeaders;
+            private LocalLiveness liveness;
             /**
              * Head of placeholder list.
              */
@@ -225,9 +216,9 @@
                     liveness = blockMap.liveness;
 
                     lastInstr = currentGraph.start();
-                    if (isSynchronized(method.getModifiers())) {
+                    if (method.isSynchronized()) {
                         // add a monitor enter to the start block
-                        currentGraph.start().setStateAfter(frameState.create(FrameState.BEFORE_BCI));
+                        currentGraph.start().setStateAfter(frameState.create(BytecodeFrame.BEFORE_BCI));
                         methodSynchronizedObject = synchronizedObject(frameState, method);
                         lastInstr = genMonitorEnter(methodSynchronizedObject);
                     }
@@ -290,12 +281,12 @@
             protected void finishPrepare(FixedWithNextNode startInstr) {
             }
 
-            private BciBlock unwindBlock(int bci) {
+            private BciBlock unwindBlock() {
                 if (unwindBlock == null) {
                     unwindBlock = new ExceptionDispatchBlock();
                     unwindBlock.startBci = -1;
                     unwindBlock.endBci = -1;
-                    unwindBlock.deoptBci = bci;
+                    unwindBlock.deoptBci = method.isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI;
                     unwindBlock.setId(Integer.MAX_VALUE);
                 }
                 return unwindBlock;
@@ -415,7 +406,7 @@
             }
 
             private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) {
-                assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci";
+                assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci";
                 Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci));
 
                 BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
@@ -425,7 +416,7 @@
                  * unwind immediately.
                  */
                 if (bci != currentBlock.endBci || dispatchBlock == null) {
-                    dispatchBlock = unwindBlock(bci);
+                    dispatchBlock = unwindBlock();
                 }
 
                 HIRFrameStateBuilder dispatchState = frameState.copy();
@@ -642,7 +633,7 @@
 
             @Override
             protected void emitNullCheck(ValueNode receiver) {
-                if (ObjectStamp.isObjectNonNull(receiver.stamp())) {
+                if (StampTool.isObjectNonNull(receiver.stamp())) {
                     return;
                 }
                 BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this));
@@ -650,16 +641,10 @@
                 append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.01));
                 lastInstr = falseSucc;
 
-                if (OmitHotExceptionStacktrace.getValue()) {
-                    ValueNode exception = ConstantNode.forObject(cachedNullPointerException, metaAccess, currentGraph);
-                    trueSucc.setNext(handleException(exception, bci()));
-                } else {
-                    DeferredForeignCallNode call = currentGraph.add(new DeferredForeignCallNode(CREATE_NULL_POINTER_EXCEPTION));
-                    call.setStamp(StampFactory.exactNonNull(metaAccess.lookupJavaType(CREATE_NULL_POINTER_EXCEPTION.getResultType())));
-                    call.setStateAfter(frameState.create(bci()));
-                    trueSucc.setNext(call);
-                    call.setNext(handleException(call, bci()));
-                }
+                BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
+                exception.setStateAfter(frameState.create(bci()));
+                trueSucc.setNext(exception);
+                exception.setNext(handleException(exception, bci()));
             }
 
             @Override
@@ -669,16 +654,10 @@
                 append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.99));
                 lastInstr = trueSucc;
 
-                if (OmitHotExceptionStacktrace.getValue()) {
-                    ValueNode exception = ConstantNode.forObject(cachedArrayIndexOutOfBoundsException, metaAccess, currentGraph);
-                    falseSucc.setNext(handleException(exception, bci()));
-                } else {
-                    DeferredForeignCallNode call = currentGraph.add(new DeferredForeignCallNode(CREATE_OUT_OF_BOUNDS_EXCEPTION, index));
-                    call.setStamp(StampFactory.exactNonNull(metaAccess.lookupJavaType(CREATE_OUT_OF_BOUNDS_EXCEPTION.getResultType())));
-                    call.setStateAfter(frameState.create(bci()));
-                    falseSucc.setNext(call);
-                    call.setNext(handleException(call, bci()));
-                }
+                BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
+                exception.setStateAfter(frameState.create(bci()));
+                falseSucc.setNext(exception);
+                exception.setNext(handleException(exception, bci()));
             }
 
             @Override
@@ -720,9 +699,9 @@
             @Override
             protected void genInvokeDynamic(JavaMethod target) {
                 if (target instanceof ResolvedJavaMethod) {
-                    Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC);
+                    Constant appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC);
                     if (appendix != null) {
-                        frameState.apush(ConstantNode.forObject(appendix, metaAccess, currentGraph));
+                        frameState.apush(ConstantNode.forConstant(appendix, metaAccess, currentGraph));
                     }
                     ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(false), target.getSignature().getParameterCount(false));
                     appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args);
@@ -741,10 +720,10 @@
                      * https://wikis.oracle.com/display/HotSpotInternals/Method+handles
                      * +and+invokedynamic
                      */
-                    boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers());
-                    Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL);
+                    boolean hasReceiver = !((ResolvedJavaMethod) target).isStatic();
+                    Constant appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL);
                     if (appendix != null) {
-                        frameState.apush(ConstantNode.forObject(appendix, metaAccess, currentGraph));
+                        frameState.apush(ConstantNode.forConstant(appendix, metaAccess, currentGraph));
                     }
                     ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver));
                     if (hasReceiver) {
@@ -834,7 +813,7 @@
                     append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci())));
                 }
 
-                synchronizedEpilogue(FrameState.AFTER_BCI, x);
+                synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x);
                 if (frameState.lockDepth() != 0) {
                     throw new BailoutException("unbalanced monitors");
                 }
@@ -890,13 +869,12 @@
             }
 
             @Override
-            protected void setBlockSuccessor(ValueNode switchNode, int i, ValueNode createBlockTarget) {
-                ((IntegerSwitchNode) switchNode).setBlockSuccessor(i, (AbstractBeginNode) createBlockTarget);
-            }
-
-            @Override
-            protected ValueNode genIntegerSwitch(ValueNode value, int size, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
-                return new IntegerSwitchNode(value, size, keys, keyProbabilities, keySuccessors);
+            protected void genIntegerSwitch(ValueNode value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+                double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities);
+                IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors));
+                for (int i = 0; i < actualSuccessors.size(); i++) {
+                    switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState));
+                }
             }
 
             @Override
@@ -997,7 +975,7 @@
                             }
                             lastLoopExit = loopExit;
                             Debug.log("Target %s (%s) Exits %s, scanning framestates...", targetBlock, target, loop);
-                            newState.insertLoopProxies(loopExit, loop.entryState);
+                            newState.insertLoopProxies(loopExit, (HIRFrameStateBuilder) loop.entryState);
                             loopExit.setStateAfter(newState.create(bci));
                         }
 
@@ -1008,25 +986,17 @@
                 return new Target(target, state);
             }
 
-            @Override
-            protected ValueNode genDeoptimization() {
-                return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
-            }
-
-            protected FixedNode createTarget(double probability, BciBlock block, AbstractFrameStateBuilder<ValueNode> stateAfter) {
+            private FixedNode createTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) {
                 assert probability >= 0 && probability <= 1.01 : probability;
                 if (isNeverExecutedCode(probability)) {
-                    return (FixedNode) genDeoptimization();
+                    return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
                 } else {
                     assert block != null;
                     return createTarget(block, stateAfter);
                 }
-
             }
 
-            protected FixedNode createTarget(BciBlock block, AbstractFrameStateBuilder<ValueNode> abstractState) {
-                assert abstractState instanceof HIRFrameStateBuilder;
-                HIRFrameStateBuilder state = (HIRFrameStateBuilder) abstractState;
+            private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state) {
                 assert block != null && state != null;
                 assert !block.isExceptionEntry || state.stackSize() == 1;
 
@@ -1047,7 +1017,7 @@
                 }
 
                 // We already saw this block before, so we have to merge states.
-                if (!block.entryState.isCompatibleWith(state)) {
+                if (!((HIRFrameStateBuilder) block.entryState).isCompatibleWith(state)) {
                     throw new BailoutException("stacks do not match; bytecodes would not verify");
                 }
 
@@ -1060,7 +1030,7 @@
                     LoopBeginNode loopBegin = (LoopBeginNode) block.firstInstruction;
                     Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state);
                     FixedNode result = target.fixed;
-                    block.entryState.merge(loopBegin, target.state);
+                    ((HIRFrameStateBuilder) block.entryState).merge(loopBegin, target.state);
 
                     Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
                     return result;
@@ -1095,7 +1065,7 @@
                 AbstractEndNode newEnd = currentGraph.add(new EndNode());
                 Target target = checkLoopExit(newEnd, block, state);
                 FixedNode result = target.fixed;
-                block.entryState.merge(mergeNode, target.state);
+                ((HIRFrameStateBuilder) block.entryState).merge(mergeNode, target.state);
                 mergeNode.addForwardEnd(newEnd);
 
                 Debug.log("createTarget %s: merging state, result: %s", block, result);
@@ -1106,18 +1076,17 @@
              * Returns a block begin node with the specified state. If the specified probability is
              * 0, the block deoptimizes immediately.
              */
-            @Override
-            protected AbstractBeginNode createBlockTarget(double probability, BciBlock block, AbstractFrameStateBuilder<ValueNode> stateAfter) {
+            private BeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) {
                 FixedNode target = createTarget(probability, block, stateAfter);
-                AbstractBeginNode begin = AbstractBeginNode.begin(target);
+                BeginNode begin = BeginNode.begin(target);
 
-                assert !(target instanceof DeoptimizeNode && begin.stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize "
+                assert !(target instanceof DeoptimizeNode && begin instanceof BeginStateSplitNode && ((BeginStateSplitNode) begin).stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize "
                                 + "to a bci _before_ the actual if, so that the interpreter can update the profiling information.";
                 return begin;
             }
 
             private ValueNode synchronizedObject(HIRFrameStateBuilder state, ResolvedJavaMethod target) {
-                if (isStatic(target.getModifiers())) {
+                if (target.isStatic()) {
                     return appendConstant(target.getDeclaringClass().getEncoding(Representation.JavaClass));
                 } else {
                     return state.loadLocal(0);
@@ -1134,7 +1103,7 @@
                 try (Indent indent = Debug.logAndIndent("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, block.firstInstruction, block.isLoopHeader)) {
 
                     lastInstr = block.firstInstruction;
-                    frameState = block.entryState;
+                    frameState = (HIRFrameStateBuilder) block.entryState;
                     parser.setCurrentFrameState(frameState);
                     currentBlock = block;
 
@@ -1183,13 +1152,12 @@
             private void createUnwind() {
                 assert frameState.stackSize() == 1 : frameState;
                 ValueNode exception = frameState.apop();
-                append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true));
-                synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null);
+                synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null);
                 append(new UnwindNode(exception));
             }
 
             private void synchronizedEpilogue(int bci, ValueNode returnValue) {
-                if (Modifier.isSynchronized(method.getModifiers())) {
+                if (method.isSynchronized()) {
                     MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue);
                     if (returnValue != null) {
                         frameState.push(returnValue.getKind(), returnValue);
@@ -1216,7 +1184,7 @@
                     ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType;
                     for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
                         if (skippedType.isAssignableFrom(resolvedCatchType)) {
-                            BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock(block.deoptBci) : block.getSuccessor(1);
+                            BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1);
                             ValueNode exception = frameState.stackAt(0);
                             FixedNode trueSuccessor = currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
                             FixedNode nextDispatch = createTarget(nextBlock, frameState);
@@ -1227,7 +1195,7 @@
                 }
 
                 if (initialized) {
-                    BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock(block.deoptBci) : block.getSuccessor(1);
+                    BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1);
                     ValueNode exception = frameState.stackAt(0);
                     CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false));
                     frameState.apop();
@@ -1243,10 +1211,7 @@
                 }
             }
 
-            @Override
-            protected void appendGoto(ValueNode targetNode) {
-                assert targetNode instanceof FixedNode;
-                FixedNode target = (FixedNode) targetNode;
+            private void appendGoto(FixedNode target) {
                 if (lastInstr != null) {
                     lastInstr.setNext(target);
                 }
@@ -1332,7 +1297,7 @@
                         frameState.clearNonLiveLocals(currentBlock, liveness, false);
                     }
                     if (lastInstr instanceof StateSplit) {
-                        if (lastInstr.getClass() == AbstractBeginNode.class) {
+                        if (lastInstr.getClass() == BeginNode.class) {
                             // BeginNodes do not need a frame state
                         } else {
                             StateSplit stateSplit = (StateSplit) lastInstr;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,54 +23,37 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.graph.iterators.NodePredicates.*;
-import static com.oracle.graal.nodes.ValueNodeUtil.*;
-import static java.lang.reflect.Modifier.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.Verbosity;
-import com.oracle.graal.java.BciBlockMapping.BciBlock;
-import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
-public class HIRFrameStateBuilder extends AbstractFrameStateBuilder<ValueNode> {
+public class HIRFrameStateBuilder extends AbstractFrameStateBuilder<ValueNode, HIRFrameStateBuilder> {
 
     private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0];
     private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0];
 
-    private final ValueNode[] locals;
-    private final ValueNode[] stack;
-    private ValueNode[] lockedObjects;
     private MonitorIdNode[] monitorIds;
     private final StructuredGraph graph;
 
-    /**
-     * @see BytecodeFrame#rethrowException
-     */
-    private boolean rethrowException;
-
     public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) {
-        super(method);
+        super(method, new ValueNode[method.getMaxLocals()], new ValueNode[Math.max(1, method.getMaxStackSize())], EMPTY_ARRAY);
 
         assert graph != null;
 
-        this.locals = new ValueNode[method.getMaxLocals()];
-        // we always need at least one stack slot (for exceptions)
-        this.stack = new ValueNode[Math.max(1, method.getMaxStackSize())];
-        this.lockedObjects = EMPTY_ARRAY;
         this.monitorIds = EMPTY_MONITOR_ARRAY;
         this.graph = graph;
 
         int javaIndex = 0;
         int index = 0;
-        if (!isStatic(method.getModifiers())) {
+        if (!method.isStatic()) {
             // add the receiver
             ParameterNode receiver = graph.unique(new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass())));
             storeLocal(javaIndex, receiver);
@@ -85,7 +68,7 @@
             if (eagerResolve) {
                 type = type.resolve(accessingClass);
             }
-            Kind kind = type.getKind().getStackKind();
+            Kind kind = type.getKind();
             Stamp stamp;
             if (kind == Kind.Object && type instanceof ResolvedJavaType) {
                 stamp = StampFactory.declared((ResolvedJavaType) type);
@@ -103,12 +86,7 @@
         super(other);
         assert other.graph != null;
         graph = other.graph;
-        locals = other.locals.clone();
-        stack = other.stack.clone();
-        lockedObjects = other.lockedObjects == EMPTY_ARRAY ? EMPTY_ARRAY : other.lockedObjects.clone();
         monitorIds = other.monitorIds == EMPTY_MONITOR_ARRAY ? EMPTY_MONITOR_ARRAY : other.monitorIds.clone();
-        stackSize = other.stackSize;
-        rethrowException = other.rethrowException;
 
         assert locals.length == method.getMaxLocals();
         assert stack.length == Math.max(1, method.getMaxStackSize());
@@ -116,6 +94,11 @@
     }
 
     @Override
+    protected ValueNode[] getEmtpyArray() {
+        return EMPTY_ARRAY;
+    }
+
+    @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("[locals: [");
@@ -142,10 +125,12 @@
         return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false));
     }
 
+    @Override
     public HIRFrameStateBuilder copy() {
         return new HIRFrameStateBuilder(this);
     }
 
+    @Override
     public boolean isCompatibleWith(HIRFrameStateBuilder other) {
         assert method.equals(other.method) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method";
         assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds";
@@ -272,7 +257,7 @@
         }
     }
 
-    public void insertProxies(AbstractBeginNode begin) {
+    public void insertProxies(BeginNode begin) {
         for (int i = 0; i < localsSize(); i++) {
             ValueNode value = localAt(i);
             if (value != null) {
@@ -316,57 +301,9 @@
         }
     }
 
-    public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) {
-        if (liveness == null) {
-            return;
-        }
-        if (liveIn) {
-            for (int i = 0; i < locals.length; i++) {
-                if (!liveness.localIsLiveIn(block, i)) {
-                    locals[i] = null;
-                }
-            }
-        } else {
-            for (int i = 0; i < locals.length; i++) {
-                if (!liveness.localIsLiveOut(block, i)) {
-                    locals[i] = null;
-                }
-            }
-        }
-    }
-
-    /**
-     * @see BytecodeFrame#rethrowException
-     */
-    public boolean rethrowException() {
-        return rethrowException;
-    }
-
-    /**
-     * @see BytecodeFrame#rethrowException
-     */
-    public void setRethrowException(boolean b) {
-        rethrowException = b;
-    }
-
-    @Override
-    public int localsSize() {
-        return locals.length;
-    }
-
-    @Override
-    public ValueNode localAt(int i) {
-        return locals[i];
-    }
-
-    @Override
-    public ValueNode stackAt(int i) {
-        return stack[i];
-    }
-
     /**
      * Adds a locked monitor to this frame state.
-     * 
+     *
      * @param object the object whose monitor will be locked.
      */
     public void pushLock(ValueNode object, MonitorIdNode monitorId) {
@@ -380,7 +317,7 @@
 
     /**
      * Removes a locked monitor from this frame state.
-     * 
+     *
      * @return the object whose monitor was removed from the locks list.
      */
     public ValueNode popLock() {
@@ -404,159 +341,6 @@
         return lockedObjects.length;
     }
 
-    @Override
-    public ValueNode loadLocal(int i) {
-        ValueNode x = locals[i];
-        assert !x.isDeleted();
-        assert !isTwoSlot(x.getKind()) || locals[i + 1] == null;
-        assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind());
-        return x;
-    }
-
-    @Override
-    public void storeLocal(int i, ValueNode x) {
-        assert x == null || x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x;
-        locals[i] = x;
-        if (x != null && isTwoSlot(x.getKind())) {
-            // if this is a double word, then kill i+1
-            locals[i + 1] = null;
-        }
-        if (x != null && i > 0) {
-            ValueNode p = locals[i - 1];
-            if (p != null && isTwoSlot(p.getKind())) {
-                // if there was a double word at i - 1, then kill it
-                locals[i - 1] = null;
-            }
-        }
-    }
-
-    @Override
-    public void storeStack(int i, ValueNode x) {
-        assert x == null || x.isAlive() && (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values";
-        stack[i] = x;
-    }
-
-    @Override
-    public void push(Kind kind, ValueNode x) {
-        assert x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal;
-        xpush(assertKind(kind, x));
-        if (isTwoSlot(kind)) {
-            xpush(null);
-        }
-    }
-
-    @Override
-    public void xpush(ValueNode x) {
-        assert x == null || (x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal);
-        stack[stackSize++] = x;
-    }
-
-    @Override
-    public void ipush(ValueNode x) {
-        xpush(assertInt(x));
-    }
-
-    @Override
-    public void fpush(ValueNode x) {
-        xpush(assertFloat(x));
-    }
-
-    @Override
-    public void apush(ValueNode x) {
-        xpush(assertObject(x));
-    }
-
-    @Override
-    public void lpush(ValueNode x) {
-        xpush(assertLong(x));
-        xpush(null);
-    }
-
-    @Override
-    public void dpush(ValueNode x) {
-        xpush(assertDouble(x));
-        xpush(null);
-    }
-
-    @Override
-    public void pushReturn(Kind kind, ValueNode x) {
-        if (kind != Kind.Void) {
-            push(kind.getStackKind(), x);
-        }
-    }
-
-    @Override
-    public ValueNode pop(Kind kind) {
-        assert kind != Kind.Void;
-        if (isTwoSlot(kind)) {
-            xpop();
-        }
-        return assertKind(kind, xpop());
-    }
-
-    @Override
-    public ValueNode xpop() {
-        ValueNode result = stack[--stackSize];
-        assert result == null || !result.isDeleted();
-        return result;
-    }
-
-    @Override
-    public ValueNode ipop() {
-        return assertInt(xpop());
-    }
-
-    @Override
-    public ValueNode fpop() {
-        return assertFloat(xpop());
-    }
-
-    @Override
-    public ValueNode apop() {
-        return assertObject(xpop());
-    }
-
-    @Override
-    public ValueNode lpop() {
-        assertHigh(xpop());
-        return assertLong(xpop());
-    }
-
-    @Override
-    public ValueNode dpop() {
-        assertHigh(xpop());
-        return assertDouble(xpop());
-    }
-
-    @Override
-    public ValueNode[] popArguments(int slotSize, int argSize) {
-        int base = stackSize - slotSize;
-        ValueNode[] r = new ValueNode[argSize];
-        int argIndex = 0;
-        int stackindex = 0;
-        while (stackindex < slotSize) {
-            ValueNode element = stack[base + stackindex];
-            assert element != null;
-            r[argIndex++] = element;
-            stackindex += stackSlots(element.getKind());
-        }
-        stackSize = base;
-        return r;
-    }
-
-    @Override
-    public ValueNode peek(int argumentNumber) {
-        int idx = stackSize() - 1;
-        for (int i = 0; i < argumentNumber; i++) {
-            if (stackAt(idx) == null) {
-                idx--;
-                assert isTwoSlot(stackAt(idx).getKind());
-            }
-            idx--;
-        }
-        return stackAt(idx);
-    }
-
     public boolean contains(ValueNode value) {
         for (int i = 0; i < localsSize(); i++) {
             if (localAt(i) == value) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,10 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
-import static java.lang.reflect.Modifier.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
@@ -84,7 +83,7 @@
         this.optionValueType = metaAccess.lookupJavaType(OptionValue.class);
         this.option = option;
         this.boxingTypes = new HashSet<>();
-        for (Class c : new Class[]{Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}) {
+        for (Class<?> c : new Class[]{Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}) {
             this.boxingTypes.add(metaAccess.lookupJavaType(c));
         }
     }
@@ -114,9 +113,9 @@
             if (node instanceof StoreFieldNode) {
                 ResolvedJavaField field = ((StoreFieldNode) node).field();
                 verify(field.getDeclaringClass().equals(declaringClass), node, "store to field " + format("%H.%n", field));
-                verify(isStatic(field.getModifiers()), node, "store to field " + format("%H.%n", field));
+                verify(field.isStatic(), node, "store to field " + format("%H.%n", field));
                 if (optionValueType.isAssignableFrom((ResolvedJavaType) field.getType())) {
-                    verify(isFinal(field.getModifiers()), node, "option field " + format("%H.%n", field) + " not final");
+                    verify(field.isFinal(), node, "option field " + format("%H.%n", field) + " not final");
                 } else {
                     verify((field.isSynthetic()), node, "store to non-synthetic field " + format("%H.%n", field));
                 }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -64,7 +64,7 @@
             assert parameterTypes.length == args.length;
             for (int i = 0; i < args.length; i++) {
                 ParameterNode param = graph.getParameter(i);
-                Constant c = Constant.forBoxed(parameterTypes[i].getKind(), args[i]);
+                Constant c = getSnippetReflection().forBoxed(parameterTypes[i].getKind(), args[i]);
                 ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph);
                 param.replaceAtUsages(replacement);
             }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,8 @@
 
 package com.oracle.graal.jtt.hotpath;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
 
 /*
@@ -104,7 +106,8 @@
      * different implementation may return different results. The 11 ulp delta allowed for test(100)
      * tries to account for that but is not guaranteed to work forever.
      */
-    // @Test
+    @Ignore("failure-prone because of the variabiliy of pow/cos/sin")
+    @Test
     public void run0() throws Throwable {
         double expected = 0.6248571921291398d;
         runTestWithDelta(11 * Math.ulp(expected), "test", 100);
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6186134.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6186134.java	Wed Apr 23 15:48:38 2014 +0200
@@ -43,7 +43,7 @@
             return num-- > 0;
         }
 
-        public ArrayList test1() {
+        public ArrayList<?> test1() {
             ArrayList<Object> res = new ArrayList<>();
             int maxResults = Integer.MAX_VALUE;
             int n = 0;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6823354.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6823354.java	Wed Apr 23 15:48:38 2014 +0200
@@ -198,10 +198,10 @@
     }
 
     static void loadandrunclass(String classname) throws Exception {
-        Class cl = Class.forName(classname);
+        Class<?> cl = Class.forName(classname);
         URLClassLoader apploader = (URLClassLoader) cl.getClassLoader();
         ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent());
-        Class c = loader.loadClass(classname);
+        Class<?> c = loader.loadClass(classname);
         Runnable r = (Runnable) c.newInstance();
         r.run();
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,30 +22,16 @@
  */
 package com.oracle.graal.jtt.hotspot;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
 
-//@formatter:off
-
-/**
- * @test
- * @bug 6959129
- * @summary COMPARISON WITH INTEGER.MAX_INT DOES NOT WORK CORRECTLY IN THE CLIENT VM.
- *
- *          This test will not run properly without assertions
- *
- * @run main/othervm -ea Test6959129
- */
 public class Test6959129 extends JTTTest {
 
-    public static int test() {
+    public static long test() {
         int min = Integer.MAX_VALUE - 30000;
         int max = Integer.MAX_VALUE;
-        try {
-            maxMoves(min, max);
-        } catch (AssertionError e) {
-            return 95;
-        }
-        return 97;
+        return maxMoves(min, max);
     }
 
     /**
@@ -55,7 +41,9 @@
         long n = n2;
         long moves = 0;
         while (n != 1) {
-            assert n > 1;
+            if (n <= 1) {
+                throw new IllegalStateException();
+            }
             if (isEven(n)) {
                 n = n / 2;
             } else {
@@ -86,7 +74,7 @@
         return maxmoves;
     }
 
-    //@Test
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAllocateInstance01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAllocateInstance01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -43,7 +43,7 @@
         return newObject.field01;
     }
 
-    public static void testClassForException(Class clazz) throws SecurityException, InstantiationException {
+    public static void testClassForException(Class<?> clazz) throws SecurityException, InstantiationException {
         final Unsafe unsafe = getUnsafe();
         unsafe.allocateInstance(clazz);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
 
     public static String test(int i) throws ClassNotFoundException {
         String clname = null;
-        Class cl = null;
+        Class<?> cl = null;
         if (i == 0) {
             clname = "java.lang.Object";
             cl = Object.class;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java	Wed Apr 23 15:48:38 2014 +0200
@@ -33,7 +33,7 @@
 
     public static String test(int i) throws ClassNotFoundException {
         String clname = null;
-        Class cl = null;
+        Class<?> cl = null;
         if (i == 0) {
             clname = "java.lang.Object[]";
             cl = Object.class;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getComponentType01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getComponentType01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
 public final class Class_getComponentType01 extends JTTTest {
 
     public static String test(int i) {
-        Class cl = Object.class;
+        Class<?> cl = Object.class;
         if (i == 0) {
             cl = int.class;
         } else if (i == 1) {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getModifiers01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getModifiers01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -39,7 +39,7 @@
     private static class Private {
     }
 
-    public static int test(Class c) {
+    public static int test(Class<?> c) {
         return c.getModifiers();
     }
 
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getSuperClass01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getSuperClass01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
 public final class Class_getSuperClass01 extends JTTTest {
 
     public static String test(int i) {
-        Class cl = Object.class;
+        Class<?> cl = Object.class;
         if (i == 0) {
             cl = int.class;
         } else if (i == 1) {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isAssignableFrom01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isAssignableFrom01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
 public final class Class_isAssignableFrom01 extends JTTTest {
 
     public static boolean test(int i) {
-        Class source = Object.class;
+        Class<?> source = Object.class;
         if (i == 0) {
             source = int.class;
         }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isAssignableFrom02.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isAssignableFrom02.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
 public final class Class_isAssignableFrom02 extends JTTTest {
 
     public static boolean test(int i) {
-        Class source = Object.class;
+        Class<?> source = Object.class;
         if (i == 0) {
             source = int.class;
         }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isAssignableFrom03.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isAssignableFrom03.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
 public final class Class_isAssignableFrom03 extends JTTTest implements Cloneable {
 
     public static boolean test(int i) {
-        Class source = Object.class;
+        Class<?> source = Object.class;
         if (i == 0) {
             source = int.class;
         }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance07.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance07.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,7 +35,7 @@
     static final String[] sarray = {};
     static final Object thisObject = new Class_isInstance07();
 
-    public static boolean test(int i, Class c) {
+    public static boolean test(int i, Class<?> c) {
         Object object = null;
         if (i == 0) {
             object = obj;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Int_less02.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Int_less02.java	Wed Apr 23 15:48:38 2014 +0200
@@ -20,8 +20,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-/*
- */
 package com.oracle.graal.jtt.lang;
 
 import org.junit.*;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/JDK_ClassLoaders02.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/JDK_ClassLoaders02.java	Wed Apr 23 15:48:38 2014 +0200
@@ -20,26 +20,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
- *
- * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product
- * that is described in this document. In particular, and without limitation, these intellectual property
- * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or
- * more additional patents or pending patent applications in the U.S. and in other countries.
- *
- * U.S. Government Rights - Commercial software. Government users are subject to the Sun
- * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its
- * supplements.
- *
- * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or
- * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks
- * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the
- * U.S. and other countries.
- *
- * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open
- * Company, Ltd.
- */
 package com.oracle.graal.jtt.lang;
 
 import java.net.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/LambdaEagerTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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.jtt.lang;
+
+import java.util.*;
+import java.util.function.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.options.*;
+import com.oracle.graal.options.OptionValue.OverrideScope;
+
+public class LambdaEagerTest extends GraalCompilerTest {
+
+    private static final EnumSet<DeoptimizationReason> UNRESOLVED_UNREACHED = EnumSet.of(DeoptimizationReason.Unresolved, DeoptimizationReason.UnreachedCode);
+
+    private static int doBinary(IntBinaryOperator op, int x, int y) {
+        return op.applyAsInt(x, y);
+    }
+
+    private static int add(int x, int y) {
+        return x + y;
+    }
+
+    public static int nonCapturing(int x, int y) {
+        return doBinary((a, b) -> a + b, x, y);
+    }
+
+    public static int nonCapturing2(int x, int y) {
+        return doBinary(LambdaEagerTest::add, x, y);
+    }
+
+    public static int capturing(int x, int y, int z) {
+        return doBinary((a, b) -> a + b - z, x, y);
+    }
+
+    @Test
+    public void testEagerResolveNonCapturing01() {
+        Result expected = new Result(3, null);
+        testAgainstExpected(getMethod("nonCapturing"), expected, UNRESOLVED_UNREACHED, 1, 2);
+    }
+
+    @Test
+    public void testEagerResolveNonCapturing02() {
+        Result expected = new Result(3, null);
+        testAgainstExpected(getMethod("nonCapturing2"), expected, UNRESOLVED_UNREACHED, 1, 2);
+    }
+
+    @Test
+    public void testEagerResolveCapturing() {
+        Result expected = new Result(0, null);
+        testAgainstExpected(getMethod("capturing"), expected, UNRESOLVED_UNREACHED, 1, 2, 3);
+    }
+
+    @Override
+    protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile) {
+        try (OverrideScope scope = OptionValue.override(GraalOptions.InlineEverything, true)) {
+            return super.getCode(method, graph, forceCompile);
+        }
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,8 +26,6 @@
 
 import com.oracle.graal.jtt.*;
 
-/*
- */
 public class Loop07 extends JTTTest {
 
     public static String test(int arg) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07_2.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.jtt.loop;
+
+import org.junit.*;
+
+import com.oracle.graal.jtt.*;
+
+public class Loop07_2 extends JTTTest {
+
+    public static int test(int arg) {
+        int count = arg;
+        for (int i = 0; i < arg; i++) {
+            count++;
+        }
+        return count;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", 0);
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", 10);
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        runTest("test", 25);
+    }
+
+}
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
 
 public class FloatingReads extends JTTTest {
@@ -61,22 +63,22 @@
         return a + b + c;
     }
 
-    // @Test
+    @Test
     public void run0() {
         runTest("test", 10);
     }
 
-    // @Test
+    @Test
     public void run1() {
         runTest("test", 1000);
     }
 
-    // @Test
+    @Test
     public void run2() {
         runTest("test", 1);
     }
 
-    // @Test
+    @Test
     public void run3() {
         runTest("test", 0);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -71,7 +71,7 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -62,7 +62,7 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -41,7 +41,7 @@
         }
     }
 
-    @Test
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter02.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter02.java	Wed Apr 23 15:48:38 2014 +0200
@@ -45,7 +45,7 @@
         }
     }
 
-    @Test
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -57,22 +57,22 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run2() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run3() throws Throwable {
         runTest("test", 15);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java	Wed Apr 23 15:48:38 2014 +0200
@@ -57,17 +57,17 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java	Wed Apr 23 15:48:38 2014 +0200
@@ -63,17 +63,17 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java	Wed Apr 23 15:48:38 2014 +0200
@@ -67,32 +67,32 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,9 +30,9 @@
 
 /**
  * Inspired by {@code com.sun.media.sound.DirectAudioDevice$DirectDL.drain()}.
- * 
+ *
  * Two loop exits hold a monitor while merging.
- * 
+ *
  */
 public final class SynchronizedLoopExit01 extends JTTTest {
 
@@ -53,7 +53,7 @@
         return b;
     }
 
-    @Test
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java	Wed Apr 23 15:48:38 2014 +0200
@@ -85,12 +85,12 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0, 0);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1, 500);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java	Wed Apr 23 15:48:38 2014 +0200
@@ -68,7 +68,7 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java	Wed Apr 23 15:48:38 2014 +0200
@@ -66,7 +66,7 @@
 
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java	Wed Apr 23 15:48:38 2014 +0200
@@ -66,7 +66,7 @@
         }
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -43,7 +43,7 @@
         cont = false;
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java	Wed Apr 23 15:48:38 2014 +0200
@@ -50,7 +50,7 @@
         cont = false;
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java	Wed Apr 23 15:48:38 2014 +0200
@@ -47,7 +47,7 @@
         cont = false;
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,17 +35,17 @@
         return System.currentTimeMillis() - before >= i;
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 10);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 20);
     }
 
-    @LongTest
+    @LongTest(timeout = 20000)
     public void run2() throws Throwable {
         runTest("test", 100);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_yield01.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_yield01.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,7 +35,7 @@
         return true;
     }
 
-    @Test
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.AMD64Move.MemOp;
 import com.oracle.graal.lir.asm.*;
@@ -82,6 +82,27 @@
     }
 
     /**
+     * Unary operation with separate source and destination operand but register only.
+     */
+    public static class Unary2RegOp extends AMD64LIRInstruction {
+
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG}) protected AllocatableValue x;
+
+        public Unary2RegOp(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            emit(crb, masm, opcode, result, x, null);
+        }
+    }
+
+    /**
      * Unary operation with single operand for source and destination.
      */
     public static class Unary1Op extends AMD64LIRInstruction {
@@ -431,9 +452,6 @@
             case LNOT:
                 masm.notq(asLongReg(result));
                 break;
-            case L2I:
-                masm.andl(asIntReg(result), 0xFFFFFFFF);
-                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -568,6 +586,9 @@
                 case I2L:
                     masm.movslq(asLongReg(dst), asIntReg(src));
                     break;
+                case L2I:
+                    masm.movl(asIntReg(dst), asLongReg(src));
+                    break;
                 case F2D:
                     masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src));
                     break;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import java.lang.reflect.*;
@@ -38,7 +38,7 @@
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.lir.gen.*;
 
 /**
  * Emits code which compares two arrays of the same length. If the CPU supports any vector
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,7 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.AMD64Move.MemOp;
 import com.oracle.graal.lir.asm.*;
@@ -65,7 +65,8 @@
                             (name().startsWith("S") && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) ||
                             (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind() == Kind.Int) || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) ||
                             (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) ||
-                            (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+                            (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double) : String.format(
+                            "%s(%s, %s)", opcode, x, y);
         }
     }
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Wed Apr 23 15:48:38 2014 +0200
@@ -33,12 +33,12 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class AMD64ControlFlow {
 
@@ -261,7 +261,7 @@
         @Use({REG, STACK, CONST}) protected Value falseValue;
         private final ConditionFlag condition;
 
-        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+        public CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue) {
             this.result = result;
             this.condition = intCond(condition);
             this.trueValue = trueValue;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.lir.*;
 
 /**
@@ -33,7 +34,7 @@
  *
  * <pre>
  *   Base       Contents
- *
+ * 
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -88,8 +89,7 @@
 
     @Override
     protected int alignFrameSize(int size) {
-        int x = size + returnAddressSize() + (target.stackAlignment - 1);
-        return (x / target.stackAlignment) * target.stackAlignment - returnAddressSize();
+        return NumUtil.roundUp(size + returnAddressSize(), target.stackAlignment) - returnAddressSize();
     }
 
     @Override
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Wed Apr 23 15:48:38 2014 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
 import com.oracle.graal.lir.StandardOp.MoveOp;
@@ -396,12 +396,15 @@
     @Opcode("CAS")
     public static class CompareAndSwapOp extends AMD64LIRInstruction {
 
+        private final Kind accessKind;
+
         @Def protected AllocatableValue result;
         @Use({COMPOSITE}) protected AMD64AddressValue address;
         @Use protected AllocatableValue cmpValue;
         @Use protected AllocatableValue newValue;
 
-        public CompareAndSwapOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+        public CompareAndSwapOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+            this.accessKind = accessKind;
             this.result = result;
             this.address = address;
             this.cmpValue = cmpValue;
@@ -410,7 +413,90 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            compareAndSwap(crb, masm, result, address, cmpValue, newValue);
+            assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax);
+
+            if (crb.target.isMP) {
+                masm.lock();
+            }
+            switch (accessKind) {
+                case Int:
+                    masm.cmpxchgl(asRegister(newValue), address.toAddress());
+                    break;
+                case Long:
+                case Object:
+                    masm.cmpxchgq(asRegister(newValue), address.toAddress());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Opcode("ATOMIC_READ_AND_ADD")
+    public static class AtomicReadAndAddOp extends AMD64LIRInstruction {
+
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Use protected AllocatableValue delta;
+
+        public AtomicReadAndAddOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue delta) {
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.delta = delta;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            move(accessKind, crb, masm, result, delta);
+            if (crb.target.isMP) {
+                masm.lock();
+            }
+            switch (accessKind) {
+                case Int:
+                    masm.xaddl(address.toAddress(), asRegister(result));
+                    break;
+                case Long:
+                    masm.xaddq(address.toAddress(), asRegister(result));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Opcode("ATOMIC_READ_AND_WRITE")
+    public static class AtomicReadAndWriteOp extends AMD64LIRInstruction {
+
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Use protected AllocatableValue newValue;
+
+        public AtomicReadAndWriteOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue newValue) {
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.newValue = newValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            move(accessKind, crb, masm, result, newValue);
+            switch (accessKind) {
+                case Int:
+                    masm.xchgl(asRegister(result), address.toAddress());
+                    break;
+                case Long:
+                case Object:
+                    masm.xchgq(asRegister(result), address.toAddress());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
         }
     }
 
@@ -641,24 +727,4 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
-
-    protected static void compareAndSwap(CompilationResultBuilder crb, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue,
-                    AllocatableValue newValue) {
-        assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax);
-
-        if (crb.target.isMP) {
-            masm.lock();
-        }
-        switch (cmpValue.getKind()) {
-            case Int:
-                masm.cmpxchgl(asRegister(newValue), address.toAddress());
-                break;
-            case Long:
-            case Object:
-                masm.cmpxchgq(asRegister(newValue), address.toAddress());
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.AMD64Move.MemOp;
 import com.oracle.graal.lir.asm.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.asm.*;
 
 public class AMD64TestOp extends AMD64LIRInstruction {
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILBitManipulationOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILBitManipulationOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,20 +26,26 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 /**
  * Implementation of compare operations.
  */
 public enum HSAILCompare {
-    ICMP,
-    LCMP,
-    ACMP,
-    FCMP,
-    DCMP;
+    ICMP(Kind.Int),
+    LCMP(Kind.Long),
+    ACMP(Kind.Object),
+    FCMP(Kind.Float),
+    DCMP(Kind.Double);
+
+    public final Kind kind;
+
+    private HSAILCompare(Kind kind) {
+        this.kind = kind;
+    }
 
     public static class CompareOp extends HSAILLIRInstruction {
 
@@ -60,7 +66,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            emit(crb, masm, condition, x, y, z, unordered);
+            emit(crb, masm, opcode, condition, x, y, z, unordered);
         }
 
         @Override
@@ -72,8 +78,8 @@
     }
 
     @SuppressWarnings("unused")
-    public static void emit(CompilationResultBuilder crb, HSAILAssembler masm, Condition condition, Value x, Value y, Value z, boolean unorderedIsTrue) {
-        emitCompare(masm, condition, x, y, unorderedIsTrue);
+    public static void emit(CompilationResultBuilder crb, HSAILAssembler masm, HSAILCompare opcode, Condition condition, Value x, Value y, Value z, boolean unorderedIsTrue) {
+        masm.emitCompare(opcode.kind, x, y, conditionToString(condition), unorderedIsTrue, isUnsignedCompare(condition));
     }
 
     public static String conditionToString(Condition condition) {
@@ -110,9 +116,4 @@
                 return false;
         }
     }
-
-    private static void emitCompare(HSAILAssembler masm, Condition condition, Value src0, Value src1, boolean unordered) {
-        masm.emitCompare(src0, src1, conditionToString(condition), unordered, isUnsignedCompare(condition));
-    }
-
 }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,13 +29,13 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.hsail.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 /**
  * Implementation of control flow instructions.
@@ -101,7 +101,7 @@
                         case Int:
                         case Long:
                             // Generate cascading compare and branches for each case.
-                            masm.emitCompare(key, keyConstants[index], HSAILCompare.conditionToString(condition), false, false);
+                            masm.emitCompare(key.getKind(), key, keyConstants[index], HSAILCompare.conditionToString(condition), false, false);
                             masm.cbr(masm.nameOf(target));
                             break;
                         case Object:
@@ -129,11 +129,17 @@
         }
     }
 
+    public interface DeoptimizingOp {
+        public LIRFrameState getFrameState();
+
+        public int getCodeBufferPos();
+    }
+
     /***
      * The ALIVE annotation is so we can get a scratch32 register that does not clobber
      * actionAndReason.
      */
-    public static class DeoptimizeOp extends ReturnOp {
+    public static class DeoptimizeOp extends ReturnOp implements DeoptimizingOp {
 
         @Alive({REG, CONST}) protected Value actionAndReason;
         @State protected LIRFrameState frameState;
@@ -173,6 +179,8 @@
             // debugInfo)
             codeBufferPos = masm.position();
 
+            masm.emitComment("/* HSAIL Deoptimization pos=" + codeBufferPos + ", bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */");
+
             // get the bitmap of $d regs that contain references
             ReferenceMap referenceMap = frameState.debugInfo().getReferenceMap();
             for (int dreg = HSAIL.d0.number; dreg <= HSAIL.d15.number; dreg++) {
@@ -181,14 +189,9 @@
                 }
             }
 
-            // here we will by convention use some never-allocated registers to pass to the epilogue
-            // deopt code
-            // todo: define these in HSAIL.java
-            // we need to pass the actionAndReason and the codeBufferPos
-
-            AllocatableValue actionAndReasonReg = HSAIL.s32.asValue(Kind.Int);
-            AllocatableValue codeBufferOffsetReg = HSAIL.s33.asValue(Kind.Int);
-            AllocatableValue dregOopMapReg = HSAIL.s39.asValue(Kind.Int);
+            AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
+            AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
+            AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int);
             masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason);
             masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
             masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap));
@@ -286,10 +289,10 @@
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
             if (crb.isSuccessorEdge(trueDestination)) {
-                HSAILCompare.emit(crb, masm, condition.negate(), x, y, z, !unordered);
+                HSAILCompare.emit(crb, masm, opcode, condition.negate(), x, y, z, !unordered);
                 masm.cbr(masm.nameOf(falseDestination.label()));
             } else {
-                HSAILCompare.emit(crb, masm, condition, x, y, z, unordered);
+                HSAILCompare.emit(crb, masm, opcode, condition, x, y, z, unordered);
                 masm.cbr(masm.nameOf(trueDestination.label()));
                 if (!crb.isSuccessorEdge(falseDestination)) {
                     masm.jmp(falseDestination.label());
@@ -320,7 +323,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            HSAILCompare.emit(crb, masm, condition, left, right, right, false);
+            HSAILCompare.emit(crb, masm, opcode, condition, left, right, right, false);
             cmove(masm, result, trueValue, falseValue);
         }
     }
@@ -336,7 +339,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            HSAILCompare.emit(crb, masm, condition, left, right, right, unorderedIsTrue);
+            HSAILCompare.emit(crb, masm, opcode, condition, left, right, right, unorderedIsTrue);
             cmove(masm, result, trueValue, falseValue);
         }
     }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,8 +28,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.hsail.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
@@ -95,6 +95,13 @@
             super(moveKind);
             this.result = result;
             this.input = input;
+            checkForNullObjectInput();
+        }
+
+        private void checkForNullObjectInput() {
+            if (result.getKind() == Kind.Object && isConstant(input) && input.getKind() == Kind.Long && ((Constant) input).asLong() == 0) {
+                input = Constant.NULL_OBJECT;
+            }
         }
 
         @Override
@@ -311,24 +318,26 @@
         private final long base;
         private final int shift;
         private final int alignment;
+        private final boolean nonNull;
 
         @Def({REG}) protected AllocatableValue result;
         @Temp({REG, HINT}) protected AllocatableValue scratch;
         @Use({REG}) protected AllocatableValue input;
 
-        public CompressPointer(AllocatableValue result, AllocatableValue scratch, AllocatableValue input, long base, int shift, int alignment) {
+        public CompressPointer(AllocatableValue result, AllocatableValue scratch, AllocatableValue input, long base, int shift, int alignment, boolean nonNull) {
             this.result = result;
             this.scratch = scratch;
             this.input = input;
             this.base = base;
             this.shift = shift;
             this.alignment = alignment;
+            this.nonNull = nonNull;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
             masm.emitMov(Kind.Long, scratch, input);
-            boolean testForNull = (input.getKind() == Kind.Object);
+            boolean testForNull = !nonNull;
             encodePointer(masm, scratch, base, shift, alignment, testForNull);
             masm.emitConvert(result, scratch, "u32", "u64");
         }
@@ -339,22 +348,24 @@
         private final long base;
         private final int shift;
         private final int alignment;
+        private final boolean nonNull;
 
         @Def({REG, HINT}) protected AllocatableValue result;
         @Use({REG}) protected AllocatableValue input;
 
-        public UncompressPointer(AllocatableValue result, AllocatableValue input, long base, int shift, int alignment) {
+        public UncompressPointer(AllocatableValue result, AllocatableValue input, long base, int shift, int alignment, boolean nonNull) {
             this.result = result;
             this.input = input;
             this.base = base;
             this.shift = shift;
             this.alignment = alignment;
+            this.nonNull = nonNull;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
             masm.emitConvert(result, input, "u64", "u32");
-            boolean testForNull = (result.getKind() == Kind.Object);
+            boolean testForNull = !nonNull;
             decodePointer(masm, result, base, shift, alignment, testForNull);
         }
     }
@@ -414,12 +425,15 @@
     @Opcode("CAS")
     public static class CompareAndSwapOp extends HSAILLIRInstruction {
 
+        private final Kind accessKind;
+
         @Def protected AllocatableValue result;
         @Use({COMPOSITE}) protected HSAILAddressValue address;
         @Use protected AllocatableValue cmpValue;
         @Use protected AllocatableValue newValue;
 
-        public CompareAndSwapOp(AllocatableValue result, HSAILAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+        public CompareAndSwapOp(Kind accessKind, AllocatableValue result, HSAILAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+            this.accessKind = accessKind;
             this.result = result;
             this.address = address;
             this.cmpValue = cmpValue;
@@ -428,54 +442,40 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            masm.emitAtomicCas(result, address.toAddress(), cmpValue, newValue);
+            masm.emitAtomicCas(accessKind, result, address.toAddress(), cmpValue, newValue);
         }
     }
 
-    @Opcode("CAS")
-    public static class CompareAndSwapCompressedOp extends CompareAndSwapOp {
+    @Opcode("ATOMIC_READ_AND_ADD")
+    public static class AtomicReadAndAddOp extends HSAILLIRInstruction {
 
-        @Temp({REG}) private AllocatableValue scratchCmpValue64;
-        @Temp({REG}) private AllocatableValue scratchNewValue64;
-        @Temp({REG}) private AllocatableValue scratchCmpValue32;
-        @Temp({REG}) private AllocatableValue scratchNewValue32;
-        @Temp({REG}) private AllocatableValue scratchCasResult32;
-        private final long base;
-        private final int shift;
-        private final int alignment;
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Use({COMPOSITE}) protected HSAILAddressValue address;
+        @Use({REG, CONST}) protected Value delta;
 
-        public CompareAndSwapCompressedOp(AllocatableValue result, HSAILAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, AllocatableValue scratchCmpValue64,
-                        AllocatableValue scratchNewValue64, AllocatableValue scratchCmpValue32, AllocatableValue scratchNewValue32, AllocatableValue scratchCasResult32, long base, int shift,
-                        int alignment) {
-            super(result, address, cmpValue, newValue);
-            this.scratchCmpValue64 = scratchCmpValue64;
-            this.scratchNewValue64 = scratchNewValue64;
-            this.scratchCmpValue32 = scratchCmpValue32;
-            this.scratchNewValue32 = scratchNewValue32;
-            this.scratchCasResult32 = scratchCasResult32;
-            this.base = base;
-            this.shift = shift;
-            this.alignment = alignment;
+        public AtomicReadAndAddOp(Kind accessKind, AllocatableValue result, HSAILAddressValue address, Value delta) {
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.delta = delta;
+        }
+
+        public HSAILAddressValue getAddress() {
+            return address;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            // assume any encoded or decoded value could be null
-            boolean testForNull = true;
-            // set up scratch registers to be encoded versions
-            masm.emitMov(Kind.Long, scratchCmpValue64, cmpValue);
-            encodePointer(masm, scratchCmpValue64, base, shift, alignment, testForNull);
-            masm.emitMov(Kind.Long, scratchNewValue64, newValue);
-            encodePointer(masm, scratchNewValue64, base, shift, alignment, testForNull);
-            // get encoded versions into 32-bit registers
-            masm.emitConvertForceUnsigned(scratchCmpValue32, scratchCmpValue64);
-            masm.emitConvertForceUnsigned(scratchNewValue32, scratchNewValue64);
-            // finally do the cas
-            masm.emitAtomicCas(scratchCasResult32, address.toAddress(), scratchCmpValue32, scratchNewValue32);
-            // and convert the 32-bit CasResult back to 64-bit
-            masm.emitConvertForceUnsigned(result, scratchCasResult32);
-            // and decode/uncompress the 64-bit cas result
-            decodePointer(masm, result, base, shift, alignment, testForNull);
+            switch (accessKind) {
+                case Int:
+                case Long:
+                    masm.emitAtomicAdd(result, address.toAddress(), delta);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
         }
     }
 
@@ -521,4 +521,5 @@
             throw GraalInternalError.shouldNotReachHere();
         }
     }
+
 }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Wed Apr 23 15:48:38 2014 +0200
@@ -42,7 +42,7 @@
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Sub;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Ushr;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Xor;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,10 +28,10 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.asm.ptx.PTXAssembler.Setp;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public enum PTXCompare {
     ICMP,
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.lir.ptx;
 
+import static com.oracle.graal.compiler.common.calc.Condition.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
-import static com.oracle.graal.nodes.calc.Condition.*;
 
 import com.oracle.graal.api.code.CompilationResult.JumpTable;
 import com.oracle.graal.api.meta.*;
@@ -33,15 +33,27 @@
 import com.oracle.graal.asm.ptx.PTXAssembler.Setp;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Mov;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class PTXControlFlow {
 
+    public static abstract class PTXPredicatedLIRInstruction extends PTXLIRInstruction {
+        private int predRegNum;
+
+        PTXPredicatedLIRInstruction(int regNum) {
+            predRegNum = regNum;
+        }
+
+        public int getPredRegNum() {
+            return predRegNum;
+        }
+    }
+
     public static class ReturnOp extends PTXLIRInstruction {
 
         @Use({REG, ILLEGAL}) protected Value x;
@@ -69,26 +81,25 @@
         }
     }
 
-    public static class BranchOp extends PTXLIRInstruction implements StandardOp.BranchOp {
+    public static class BranchOp extends PTXPredicatedLIRInstruction implements StandardOp.BranchOp {
 
         protected final Condition condition;
         protected final LabelRef trueDestination;
         protected final LabelRef falseDestination;
-        protected int predRegNum;
 
         public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, int predReg) {
+            super(predReg);
             this.condition = condition;
             this.trueDestination = trueDestination;
             this.falseDestination = falseDestination;
-            this.predRegNum = predReg;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
             if (crb.isSuccessorEdge(trueDestination)) {
-                masm.bra(masm.nameOf(falseDestination.label()), predRegNum, false);
+                masm.bra(masm.nameOf(falseDestination.label()), getPredRegNum(), false);
             } else {
-                masm.bra(masm.nameOf(trueDestination.label()), predRegNum, true);
+                masm.bra(masm.nameOf(trueDestination.label()), getPredRegNum(), true);
                 if (!crb.isSuccessorEdge(falseDestination)) {
                     masm.jmp(falseDestination.label());
                 }
@@ -96,49 +107,47 @@
         }
     }
 
-    public static class CondMoveOp extends PTXLIRInstruction {
+    public static class CondMoveOp extends PTXPredicatedLIRInstruction {
 
         @Def({REG, HINT}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Use({REG, STACK, CONST}) protected Value falseValue;
         private final Condition condition;
-        private final int predicate;
 
         public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue, int predicateRegister) {
+            super(predicateRegister);
             this.result = result;
             this.condition = condition;
             this.trueValue = trueValue;
             this.falseValue = falseValue;
-            this.predicate = predicateRegister;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
-            cmove(crb, masm, result, false, condition, false, trueValue, falseValue, predicate);
+            cmove(crb, masm, result, false, condition, false, trueValue, falseValue, getPredRegNum());
         }
     }
 
-    public static class FloatCondMoveOp extends PTXLIRInstruction {
+    public static class FloatCondMoveOp extends PTXPredicatedLIRInstruction {
 
         @Def({REG}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Alive({REG}) protected Value falseValue;
         private final Condition condition;
         private final boolean unorderedIsTrue;
-        private final int predicate;
 
         public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue, int predicateRegister) {
+            super(predicateRegister);
             this.result = result;
             this.condition = condition;
             this.unorderedIsTrue = unorderedIsTrue;
             this.trueValue = trueValue;
             this.falseValue = falseValue;
-            this.predicate = predicateRegister;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
-            cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue, predicate);
+            cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue, getPredRegNum());
         }
     }
 
@@ -193,7 +202,7 @@
         }
     }
 
-    public static class StrategySwitchOp extends PTXLIRInstruction implements BlockEndOp {
+    public static class StrategySwitchOp extends PTXPredicatedLIRInstruction implements BlockEndOp {
 
         @Use({CONST}) protected Constant[] keyConstants;
         private final LabelRef[] keyTargets;
@@ -201,10 +210,9 @@
         @Alive({REG}) protected Value key;
         @Temp({REG, ILLEGAL}) protected Value scratch;
         private final SwitchStrategy strategy;
-        // Number of predicate register that would be set by this instruction.
-        protected int predRegNum;
 
         public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch, int predReg) {
+            super(predReg);
             this.strategy = strategy;
             this.keyConstants = strategy.keyConstants;
             this.keyTargets = keyTargets;
@@ -214,7 +222,6 @@
             assert keyConstants.length == keyTargets.length;
             assert keyConstants.length == strategy.keyProbabilities.length;
             assert (scratch.getKind() == Kind.Illegal) == (key.getKind() == Kind.Int || key.getKind() == Kind.Long);
-            predRegNum = predReg;
         }
 
         @Override
@@ -228,40 +235,38 @@
                             if (crb.codeCache.needsDataPatch(keyConstants[index])) {
                                 crb.recordInlineDataInCode(keyConstants[index]);
                             }
-                            new Setp(EQ, keyConstants[index], key, predRegNum).emit(masm);
+                            new Setp(EQ, keyConstants[index], key, getPredRegNum()).emit(masm);
                             break;
                         case Object:
                             assert condition == Condition.EQ || condition == Condition.NE;
                             PTXMove.move(crb, masm, scratch, keyConstants[index]);
-                            new Setp(condition, scratch, key, predRegNum).emit(masm);
+                            new Setp(condition, scratch, key, getPredRegNum()).emit(masm);
                             break;
                         default:
                             throw new GraalInternalError("switch only supported for int, long and object");
                     }
-                    masm.bra(masm.nameOf(target), predRegNum, true);
+                    masm.bra(masm.nameOf(target), getPredRegNum(), true);
                 }
             };
             strategy.run(closure);
         }
     }
 
-    public static class TableSwitchOp extends PTXLIRInstruction implements BlockEndOp {
+    public static class TableSwitchOp extends PTXPredicatedLIRInstruction implements BlockEndOp {
 
         private final int lowKey;
         private final LabelRef defaultTarget;
         private final LabelRef[] targets;
         @Alive protected Value index;
         @Temp protected Value scratch;
-        // Number of predicate register that would be set by this instruction.
-        protected int predRegNum;
 
         public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch, int predReg) {
+            super(predReg);
             this.lowKey = lowKey;
             this.defaultTarget = defaultTarget;
             this.targets = targets;
             this.index = index;
             this.scratch = scratch;
-            predRegNum = predReg;
         }
 
         @Override
@@ -272,14 +277,14 @@
             if (lowKey != 0) {
                 // subtract the low value from the switch value
                 // new Sub(value, value, lowKey).emit(masm);
-                new Setp(GT, index, Constant.forInt(highKey - lowKey), predRegNum).emit(masm);
+                new Setp(GT, index, Constant.forInt(highKey - lowKey), getPredRegNum()).emit(masm);
             } else {
-                new Setp(GT, index, Constant.forInt(highKey), predRegNum).emit(masm);
+                new Setp(GT, index, Constant.forInt(highKey), getPredRegNum()).emit(masm);
             }
 
             // Jump to default target if index is not within the jump table
             if (defaultTarget != null) {
-                masm.bra(masm.nameOf(defaultTarget.label()), predRegNum, true);
+                masm.bra(masm.nameOf(defaultTarget.label()), getPredRegNum(), true);
             }
 
             // address of jump table
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.LoadAddr;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.LoadParam;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.St;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Mov;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.StandardOp.NullCheck;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXTestOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXTestOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,8 +28,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.asm.ptx.PTXAssembler.Setp;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class PTXTestOp extends PTXLIRInstruction {
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Wed Apr 23 15:48:38 2014 +0200
@@ -56,10 +56,10 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Neg;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Not;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Signx;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.lir.gen.*;
 
 public enum SPARCArithmetic {
     // @formatter:off
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -37,10 +37,10 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler.Sub;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.lir.gen.*;
 
 public class SPARCBitManipulationOp extends SPARCLIRInstruction {
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Wed Apr 23 15:48:38 2014 +0200
@@ -48,12 +48,12 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Jmp;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Nop;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Ret;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class SPARCControlFlow {
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Fsqrtd;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Apr 23 15:48:38 2014 +0200
@@ -49,7 +49,7 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setuw;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
 import com.oracle.graal.lir.StandardOp.MoveOp;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.asm.*;
 
 public class SPARCTestOp extends SPARCLIRInstruction {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,7 +25,7 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.CompositeValue.Component;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
@@ -86,7 +86,7 @@
     @Override
     protected void rescanFieldOffsets(CalcOffset calc) {
         ValueFieldScanner scanner = new ValueFieldScanner(calc);
-        scanner.scan(clazz);
+        scanner.scan(getClazz());
 
         OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class);
         copyInto(componentOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
@@ -108,7 +108,7 @@
         }
 
         @Override
-        protected void scan(Class<?> clazz) {
+        public void scan(Class<?> clazz) {
             super.scan(clazz);
         }
 
@@ -127,7 +127,7 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" component[");
+        str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" component[");
         for (int i = 0; i < componentOffsets.length; i++) {
             str.append(i == 0 ? "" : ", ").append(componentOffsets[i]);
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 import java.util.*;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.compiler.common.cfg.*;
 
 /**
  * This class performs basic optimizations on the control flow graph after LIR generation.
@@ -49,7 +49,7 @@
     /**
      * Checks whether a block can be deleted. Only blocks with exactly one successor and an
      * unconditional branch to this successor are eligable.
-     * 
+     *
      * @param block the block checked for deletion
      * @return whether the block can be deleted
      */
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,8 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * This class optimizes moves, particularly those that result from eliminating SSA form.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,9 +25,9 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * This class implements the overall container for the LIR graph and directs its construction,
@@ -105,7 +105,7 @@
 
     /**
      * Gets the linear scan ordering of blocks as a list.
-     * 
+     *
      * @return the blocks in linear scan order
      */
     public List<? extends AbstractBlock<?>> linearScanOrder() {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,8 +30,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
@@ -118,7 +118,7 @@
     @Override
     protected void rescanFieldOffsets(CalcOffset calc) {
         InstructionFieldScanner scanner = new InstructionFieldScanner(calc);
-        scanner.scan(clazz);
+        scanner.scan(getClazz());
 
         OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class);
         copyInto(useOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
@@ -177,7 +177,7 @@
         }
 
         @Override
-        protected void scan(Class<?> clazz) {
+        public void scan(Class<?> clazz) {
             if (clazz.getAnnotation(Opcode.class) != null) {
                 opcodeConstant = clazz.getAnnotation(Opcode.class).value();
             }
@@ -213,7 +213,7 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" use[");
+        str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" use[");
         for (int i = 0; i < useOffsets.length; i++) {
             str.append(i == 0 ? "" : ", ").append(useOffsets[i]);
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,12 +29,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-import com.oracle.graal.nodes.cfg.*;
 
 public final class LIRVerifier {
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,14 +23,14 @@
 package com.oracle.graal.lir;
 
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.StandardOp.BranchOp;
 import com.oracle.graal.lir.StandardOp.JumpOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * LIR instructions such as {@link JumpOp} and {@link BranchOp} need to reference their target
- * {@link Block}. However, direct references are not possible since the control flow graph (and
- * therefore successors lists) can be changed by optimizations - and fixing the instructions is
+ * {@link AbstractBlock}. However, direct references are not possible since the control flow graph
+ * (and therefore successors lists) can be changed by optimizations - and fixing the instructions is
  * error prone. Therefore, we represent an edge to block B from block A via the tuple {@code (A,
  * successor-index-of-B)}. That is, indirectly by storing the index into the successor list of A.
  * Note therefore that the successor list cannot be re-ordered.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,9 +24,9 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
 import com.oracle.graal.lir.StandardOp.NullCheck;
-import com.oracle.graal.nodes.cfg.*;
 
 public final class NullCheckOptimizer {
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,12 +28,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Removes move instructions, where the destination value is already in place.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,9 +29,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * A collection of machine-independent LIR operations, as well as interfaces to be implemented for
@@ -154,7 +154,7 @@
 
         /**
          * Prunes {@code doNotSave} from the registers saved by this operation.
-         * 
+         *
          * @param doNotSave registers that should not be saved by this operation
          * @return the number of registers pruned
          * @throws UnsupportedOperationException if removal is not {@linkplain #supportsRemove()
@@ -165,7 +165,7 @@
         /**
          * Gets a map from the saved registers saved by this operation to the frame slots in which
          * they are saved.
-         * 
+         *
          * @param frameMap used to {@linkplain FrameMap#indexForStackSlot(StackSlot) convert} a
          *            virtual slot to a frame slot index
          */
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,8 +26,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 /**
  * This class encapsulates different strategies on how to generate code for switch instructions.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,10 +30,10 @@
 import com.oracle.graal.api.code.CompilationResult.Data;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Fills in a {@link CompilationResult} as its code is being assembled.
@@ -88,8 +88,8 @@
         assert frameContext != null;
     }
 
-    public void setFrameSize(int frameSize) {
-        compilationResult.setFrameSize(frameSize);
+    public void setTotalFrameSize(int frameSize) {
+        compilationResult.setTotalFrameSize(frameSize);
     }
 
     private static final CompilationResult.Mark[] NO_REFS = {};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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.lir.gen;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.lir.*;
+
+/**
+ * This interface can be used to generate LIR for arithmetic operations.
+ */
+public interface ArithmeticLIRGenerator {
+
+    PlatformKind getPlatformKind(Stamp stamp);
+
+    Value emitNegate(Value input);
+
+    Value emitAdd(Value a, Value b);
+
+    Value emitSub(Value a, Value b);
+
+    Value emitMul(Value a, Value b);
+
+    Value emitDiv(Value a, Value b, LIRFrameState state);
+
+    Value emitRem(Value a, Value b, LIRFrameState state);
+
+    Value emitUDiv(Value a, Value b, LIRFrameState state);
+
+    Value emitURem(Value a, Value b, LIRFrameState state);
+
+    Value emitNot(Value input);
+
+    Value emitAnd(Value a, Value b);
+
+    Value emitOr(Value a, Value b);
+
+    Value emitXor(Value a, Value b);
+
+    Value emitShl(Value a, Value b);
+
+    Value emitShr(Value a, Value b);
+
+    Value emitUShr(Value a, Value b);
+
+    Value emitFloatConvert(FloatConvert op, Value inputVal);
+
+    Value emitReinterpret(PlatformKind to, Value inputVal);
+
+    Value emitNarrow(Value inputVal, int bits);
+
+    Value emitSignExtend(Value inputVal, int fromBits, int toBits);
+
+    Value emitZeroExtend(Value inputVal, int fromBits, int toBits);
+
+    Value emitMathAbs(Value input);
+
+    Value emitMathSqrt(Value input);
+
+    Value emitMathLog(Value input, boolean base10);
+
+    Value emitMathCos(Value input);
+
+    Value emitMathSin(Value input);
+
+    Value emitMathTan(Value input);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.lir.gen;
+
+import com.oracle.graal.lir.*;
+
+public interface LIRGenerationResult {
+    FrameMap getFrameMap();
+
+    LIR getLIR();
+
+    boolean hasForeignCall();
+
+    void setForeignCall(boolean b);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.lir.gen;
+
+import com.oracle.graal.lir.*;
+
+public class LIRGenerationResultBase implements LIRGenerationResult {
+    private final LIR lir;
+    private final FrameMap frameMap;
+    /**
+     * Records whether the code being generated makes at least one foreign call.
+     */
+    private boolean hasForeignCall;
+
+    public LIRGenerationResultBase(LIR lir, FrameMap frameMap) {
+        this.lir = lir;
+        this.frameMap = frameMap;
+    }
+
+    public LIR getLIR() {
+        return lir;
+    }
+
+    /**
+     * Determines whether the code being generated makes at least one foreign call.
+     */
+    public boolean hasForeignCall() {
+        return hasForeignCall;
+    }
+
+    public final void setForeignCall(boolean hasForeignCall) {
+        this.hasForeignCall = hasForeignCall;
+    }
+
+    public final FrameMap getFrameMap() {
+        return frameMap;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,598 @@
+/*
+ * 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.lir.gen;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.api.meta.Value.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.lir.LIR.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.spi.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
+import com.oracle.graal.lir.StandardOp.LabelOp;
+import com.oracle.graal.lir.StandardOp.NoOp;
+import com.oracle.graal.options.*;
+
+/**
+ * This class traverses the HIR instructions and generates LIR instructions from them.
+ */
+public abstract class LIRGenerator implements ArithmeticLIRGenerator, LIRGeneratorTool, PlatformKindTool {
+
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Print HIR along side LIR as the latter is generated")
+        public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false);
+        @Option(help = "The trace level for the LIR generator")
+        public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0);
+        // @formatter:on
+    }
+
+    private final CodeGenProviders providers;
+    private final CallingConvention cc;
+
+    protected AbstractBlock<?> currentBlock;
+    public final int traceLevel;
+    public final boolean printIRWithLIR;
+
+    /**
+     * Handle for an operation that loads a constant into a variable. The operation starts in the
+     * first block where the constant is used but will eventually be
+     * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the
+     * constant.
+     */
+    public static class LoadConstant implements Comparable<LoadConstant> {
+        /**
+         * The index of {@link #op} within {@link #block}'s instruction list or -1 if {@code op} is
+         * to be moved to a dominator block.
+         */
+        int index;
+
+        /**
+         * The operation that loads the constant.
+         */
+        private final LIRInstruction op;
+
+        /**
+         * The block that does or will contain {@link #op}. This is initially the block where the
+         * first usage of the constant is seen during LIR generation.
+         */
+        AbstractBlock<?> block;
+
+        /**
+         * The variable into which the constant is loaded.
+         */
+        final Variable variable;
+
+        public LoadConstant(Variable variable, AbstractBlock<?> block, int index, LIRInstruction op) {
+            this.variable = variable;
+            this.block = block;
+            this.index = index;
+            this.op = op;
+        }
+
+        /**
+         * Sorts {@link LoadConstant} objects according to their enclosing blocks. This is used to
+         * group loads per block in {@link LIRGenerator#insertConstantLoads()}.
+         */
+        public int compareTo(LoadConstant o) {
+            if (block.getId() < o.block.getId()) {
+                return -1;
+            }
+            if (block.getId() > o.block.getId()) {
+                return 1;
+            }
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return block + "#" + op;
+        }
+
+        /**
+         * Removes the {@link #op} from its original location if it is still at that location.
+         */
+        public void unpin(LIR lir) {
+            if (index >= 0) {
+                // Replace the move with a filler op so that the operation
+                // list does not need to be adjusted.
+                List<LIRInstruction> instructions = lir.getLIRforBlock(block);
+                instructions.set(index, new NoOp(null, -1));
+                index = -1;
+            }
+        }
+
+        public AbstractBlock<?> getBlock() {
+            return block;
+        }
+
+        public void setBlock(AbstractBlock<?> block) {
+            this.block = block;
+        }
+
+        public Variable getVariable() {
+            return variable;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public void setIndex(int index) {
+            this.index = index;
+        }
+    }
+
+    private Map<Constant, LoadConstant> constantLoads;
+
+    private LIRGenerationResult res;
+
+    /**
+     * Checks whether the supplied constant can be used without loading it into a register for store
+     * operations, i.e., on the right hand side of a memory access.
+     *
+     * @param c The constant to check.
+     * @return True if the constant can be used directly, false if the constant needs to be in a
+     *         register.
+     */
+    public abstract boolean canStoreConstant(Constant c, boolean isCompressed);
+
+    public LIRGenerator(CodeGenProviders providers, CallingConvention cc, LIRGenerationResult res) {
+        this.res = res;
+        this.providers = providers;
+        this.cc = cc;
+        this.traceLevel = Options.TraceLIRGeneratorLevel.getValue();
+        this.printIRWithLIR = Options.PrintIRWithLIR.getValue();
+    }
+
+    /**
+     * Returns true if the redundant move elimination optimization should be done after register
+     * allocation.
+     */
+    public boolean canEliminateRedundantMoves() {
+        return true;
+    }
+
+    @Override
+    public TargetDescription target() {
+        return getCodeCache().getTarget();
+    }
+
+    public CodeGenProviders getProviders() {
+        return providers;
+    }
+
+    @Override
+    public MetaAccessProvider getMetaAccess() {
+        return providers.getMetaAccess();
+    }
+
+    @Override
+    public CodeCacheProvider getCodeCache() {
+        return providers.getCodeCache();
+    }
+
+    @Override
+    public ForeignCallsProvider getForeignCalls() {
+        return providers.getForeignCalls();
+    }
+
+    /**
+     * Creates a new {@linkplain Variable variable}.
+     *
+     * @param platformKind The kind of the new variable.
+     * @return a new variable
+     */
+    @Override
+    public Variable newVariable(PlatformKind platformKind) {
+        return new Variable(platformKind, res.getLIR().nextVariable());
+    }
+
+    @Override
+    public RegisterAttributes attributes(Register register) {
+        return res.getFrameMap().registerConfig.getAttributesMap()[register.number];
+    }
+
+    @Override
+    public abstract Variable emitMove(Value input);
+
+    public AllocatableValue asAllocatable(Value value) {
+        if (isAllocatableValue(value)) {
+            return asAllocatableValue(value);
+        } else {
+            return emitMove(value);
+        }
+    }
+
+    public Variable load(Value value) {
+        if (!isVariable(value)) {
+            return emitMove(value);
+        }
+        return (Variable) value;
+    }
+
+    public Value loadNonConst(Value value) {
+        if (isConstant(value) && !canInlineConstant((Constant) value)) {
+            return emitMove(value);
+        }
+        return value;
+    }
+
+    /**
+     * Determines if only oop maps are required for the code generated from the LIR.
+     */
+    public boolean needOnlyOopMaps() {
+        return false;
+    }
+
+    /**
+     * Gets the ABI specific operand used to return a value of a given kind from a method.
+     *
+     * @param kind the kind of value being returned
+     * @return the operand representing the ABI defined location used return a value of kind
+     *         {@code kind}
+     */
+    public AllocatableValue resultOperandFor(Kind kind) {
+        if (kind == Kind.Void) {
+            return ILLEGAL;
+        }
+        return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind);
+    }
+
+    public void append(LIRInstruction op) {
+        if (printIRWithLIR && !TTY.isSuppressed()) {
+            TTY.println(op.toStringWithIdPrefix());
+            TTY.println();
+        }
+        assert LIRVerifier.verify(op);
+        res.getLIR().getLIRforBlock(currentBlock).add(op);
+    }
+
+    public boolean hasBlockEnd(AbstractBlock<?> block) {
+        List<LIRInstruction> ops = getResult().getLIR().getLIRforBlock(block);
+        if (ops.size() == 0) {
+            return false;
+        }
+        return ops.get(ops.size() - 1) instanceof BlockEndOp;
+    }
+
+    public final void doBlockStart(AbstractBlock<?> block) {
+        if (printIRWithLIR) {
+            TTY.print(block.toString());
+        }
+
+        currentBlock = block;
+
+        // set up the list of LIR instructions
+        assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block";
+        res.getLIR().setLIRforBlock(block, new ArrayList<LIRInstruction>());
+
+        append(new LabelOp(new Label(block.getId()), block.isAligned()));
+
+        if (traceLevel >= 1) {
+            TTY.println("BEGIN Generating LIR for block B" + block.getId());
+        }
+    }
+
+    public final void doBlockEnd(AbstractBlock<?> block) {
+
+        if (traceLevel >= 1) {
+            TTY.println("END Generating LIR for block B" + block.getId());
+        }
+
+        currentBlock = null;
+
+        if (printIRWithLIR) {
+            TTY.println();
+        }
+    }
+
+    public void emitIncomingValues(Value[] params) {
+        ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params);
+    }
+
+    public abstract void emitJump(LabelRef label);
+
+    public abstract void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
+                    double trueDestinationProbability);
+
+    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
+
+    public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
+
+    public abstract Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
+
+    public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
+
+    protected abstract void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info);
+
+    public static AllocatableValue toStackKind(AllocatableValue value) {
+        if (value.getKind().getStackKind() != value.getKind()) {
+            // We only have stack-kinds in the LIR, so convert the operand kind for values from the
+            // calling convention.
+            if (isRegister(value)) {
+                return asRegister(value).asValue(value.getKind().getStackKind());
+            } else if (isStackSlot(value)) {
+                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState frameState, Value... args) {
+        LIRFrameState state = null;
+        if (linkage.canDeoptimize()) {
+            if (frameState != null) {
+                state = frameState;
+            } else {
+                assert needOnlyOopMaps();
+                state = new LIRFrameState(null, null, null);
+            }
+        }
+
+        // move the arguments into the correct location
+        CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
+        res.getFrameMap().callsMethod(linkageCc);
+        assert linkageCc.getArgumentCount() == args.length : "argument count mismatch";
+        Value[] argLocations = new Value[args.length];
+        for (int i = 0; i < args.length; i++) {
+            Value arg = args[i];
+            AllocatableValue loc = linkageCc.getArgument(i);
+            emitMove(loc, arg);
+            argLocations[i] = loc;
+        }
+        res.setForeignCall(true);
+        emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state);
+
+        if (isLegal(linkageCc.getReturn())) {
+            return emitMove(linkageCc.getReturn());
+        } else {
+            return null;
+        }
+    }
+
+    public void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) {
+        int keyCount = keyConstants.length;
+        SwitchStrategy strategy = SwitchStrategy.getBestStrategy(keyProbabilities, keyConstants, keyTargets);
+        long valueRange = keyConstants[keyCount - 1].asLong() - keyConstants[0].asLong() + 1;
+        double tableSwitchDensity = keyCount / (double) valueRange;
+        /*
+         * This heuristic tries to find a compromise between the effort for the best switch strategy
+         * and the density of a tableswitch. If the effort for the strategy is at least 4, then a
+         * tableswitch is preferred if better than a certain value that starts at 0.5 and lowers
+         * gradually with additional effort.
+         */
+        if (strategy.getAverageEffort() < 4 || tableSwitchDensity < (1 / Math.sqrt(strategy.getAverageEffort()))) {
+            emitStrategySwitch(strategy, value, keyTargets, defaultTarget);
+        } else {
+            int minValue = keyConstants[0].asInt();
+            assert valueRange < Integer.MAX_VALUE;
+            LabelRef[] targets = new LabelRef[(int) valueRange];
+            for (int i = 0; i < valueRange; i++) {
+                targets[i] = defaultTarget;
+            }
+            for (int i = 0; i < keyCount; i++) {
+                targets[keyConstants[i].asInt() - minValue] = keyTargets[i];
+            }
+            emitTableSwitch(minValue, defaultTarget, targets, value);
+        }
+    }
+
+    public abstract void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget);
+
+    protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key);
+
+    public CallingConvention getCallingConvention() {
+        return cc;
+    }
+
+    @Override
+    public void beforeRegisterAllocation() {
+        insertConstantLoads();
+    }
+
+    /**
+     * Moves deferred {@linkplain LoadConstant loads} of constants into blocks dominating all usages
+     * of the constant. Any operations inserted into a block are guaranteed to be immediately prior
+     * to the first control flow instruction near the end of the block.
+     */
+    private void insertConstantLoads() {
+        if (constantLoads != null) {
+            // Remove loads where all usages are in the same block.
+            for (Iterator<Map.Entry<Constant, LoadConstant>> iter = constantLoads.entrySet().iterator(); iter.hasNext();) {
+                LoadConstant lc = iter.next().getValue();
+
+                // Move loads of constant outside of loops
+                if (OptScheduleOutOfLoops.getValue()) {
+                    AbstractBlock<?> outOfLoopDominator = lc.block;
+                    while (outOfLoopDominator.getLoop() != null) {
+                        outOfLoopDominator = outOfLoopDominator.getDominator();
+                    }
+                    if (outOfLoopDominator != lc.block) {
+                        lc.unpin(res.getLIR());
+                        lc.block = outOfLoopDominator;
+                    }
+                }
+
+                if (lc.index != -1) {
+                    assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op;
+                    iter.remove();
+                }
+            }
+            if (constantLoads.isEmpty()) {
+                return;
+            }
+
+            // Sorting groups the loads per block.
+            LoadConstant[] groupedByBlock = constantLoads.values().toArray(new LoadConstant[constantLoads.size()]);
+            Arrays.sort(groupedByBlock);
+
+            int groupBegin = 0;
+            while (true) {
+                int groupEnd = groupBegin + 1;
+                AbstractBlock<?> block = groupedByBlock[groupBegin].block;
+                while (groupEnd < groupedByBlock.length && groupedByBlock[groupEnd].block == block) {
+                    groupEnd++;
+                }
+                int groupSize = groupEnd - groupBegin;
+
+                List<LIRInstruction> ops = res.getLIR().getLIRforBlock(block);
+                int lastIndex = ops.size() - 1;
+                assert ops.get(lastIndex) instanceof BlockEndOp;
+                int insertionIndex = lastIndex;
+                for (int i = Math.max(0, lastIndex - MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END); i < lastIndex; i++) {
+                    if (getExceptionEdge(ops.get(i)) != null) {
+                        insertionIndex = i;
+                        break;
+                    }
+                }
+
+                if (groupSize == 1) {
+                    ops.add(insertionIndex, groupedByBlock[groupBegin].op);
+                } else {
+                    assert groupSize > 1;
+                    List<LIRInstruction> moves = new ArrayList<>(groupSize);
+                    for (int i = groupBegin; i < groupEnd; i++) {
+                        moves.add(groupedByBlock[i].op);
+                    }
+                    ops.addAll(insertionIndex, moves);
+                }
+
+                if (groupEnd == groupedByBlock.length) {
+                    break;
+                }
+                groupBegin = groupEnd;
+            }
+            constantLoads = null;
+        }
+    }
+
+    /**
+     * Gets a garbage value for a given kind.
+     */
+    protected Constant zapValueForKind(PlatformKind kind) {
+        long dead = 0xDEADDEADDEADDEADL;
+        switch ((Kind) kind) {
+            case Boolean:
+                return Constant.FALSE;
+            case Byte:
+                return Constant.forByte((byte) dead);
+            case Char:
+                return Constant.forChar((char) dead);
+            case Short:
+                return Constant.forShort((short) dead);
+            case Int:
+                return Constant.forInt((int) dead);
+            case Double:
+                return Constant.forDouble(Double.longBitsToDouble(dead));
+            case Float:
+                return Constant.forFloat(Float.intBitsToFloat((int) dead));
+            case Long:
+                return Constant.forLong(dead);
+            case Object:
+                return Constant.NULL_OBJECT;
+            default:
+                throw new IllegalArgumentException(kind.toString());
+        }
+    }
+
+    /**
+     * Default implementation: Return the Java stack kind for each stamp.
+     */
+    public PlatformKind getPlatformKind(Stamp stamp) {
+        return stamp.getPlatformKind(this);
+    }
+
+    public PlatformKind getIntegerKind(int bits) {
+        if (bits <= 8) {
+            return Kind.Byte;
+        } else if (bits <= 16) {
+            return Kind.Short;
+        } else if (bits <= 32) {
+            return Kind.Int;
+        } else {
+            assert bits <= 64;
+            return Kind.Long;
+        }
+    }
+
+    public PlatformKind getFloatingKind(int bits) {
+        switch (bits) {
+            case 32:
+                return Kind.Float;
+            case 64:
+                return Kind.Double;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public PlatformKind getObjectKind() {
+        return Kind.Object;
+    }
+
+    public abstract void emitBitCount(Variable result, Value operand);
+
+    public abstract void emitBitScanForward(Variable result, Value operand);
+
+    public abstract void emitBitScanReverse(Variable result, Value operand);
+
+    public abstract void emitByteSwap(Variable result, Value operand);
+
+    public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
+
+    public AbstractBlock<?> getCurrentBlock() {
+        return currentBlock;
+    }
+
+    void setCurrentBlock(AbstractBlock<?> block) {
+        currentBlock = block;
+    }
+
+    public LIRGenerationResult getResult() {
+        return res;
+    }
+
+    public Map<Constant, LoadConstant> getConstantLoads() {
+        return constantLoads;
+    }
+
+    public void setConstantLoads(Map<Constant, LoadConstant> constantLoads) {
+        this.constantLoads = constantLoads;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.gen;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.*;
+
+public interface LIRGeneratorTool extends ArithmeticLIRGenerator {
+
+    TargetDescription target();
+
+    MetaAccessProvider getMetaAccess();
+
+    CodeCacheProvider getCodeCache();
+
+    ForeignCallsProvider getForeignCalls();
+
+    Value emitLoad(PlatformKind kind, Value address, LIRFrameState state);
+
+    void emitStore(PlatformKind kind, Value address, Value input, LIRFrameState state);
+
+    Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue);
+
+    /**
+     * Emit an atomic read-and-add instruction.
+     *
+     * @param address address of the value to be read and written
+     * @param delta the value to be added
+     */
+    default Value emitAtomicReadAndAdd(Value address, Value delta) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    /**
+     * Emit an atomic read-and-write instruction.
+     *
+     * @param address address of the value to be read and written
+     * @param newValue the new value to be written
+     */
+    default Value emitAtomicReadAndWrite(Value address, Value newValue) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state);
+
+    Value emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args);
+
+    /**
+     * Checks whether the supplied constant can be used without loading it into a register for most
+     * operations, i.e., for commonly used arithmetic, logical, and comparison operations.
+     *
+     * @param c The constant to check.
+     * @return True if the constant can be used directly, false if the constant needs to be in a
+     *         register.
+     */
+    boolean canInlineConstant(Constant c);
+
+    boolean canStoreConstant(Constant c, boolean isCompressed);
+
+    RegisterAttributes attributes(Register register);
+
+    AllocatableValue newVariable(PlatformKind kind);
+
+    AllocatableValue emitMove(Value input);
+
+    void emitMove(AllocatableValue dst, Value src);
+
+    /**
+     * Emits an op that loads the address of some raw data.
+     *
+     * @param dst the variable into which the address is loaded
+     * @param data the data to be installed with the generated code
+     */
+    void emitData(AllocatableValue dst, byte[] data);
+
+    Value emitAddress(Value base, long displacement, Value index, int scale);
+
+    Value emitAddress(StackSlot slot);
+
+    void emitMembar(int barriers);
+
+    void emitUnwind(Value operand);
+
+    /**
+     * Called just before register allocation is performed on the LIR owned by this generator.
+     * Overriding implementations of this method must call the overridden method.
+     */
+    void beforeRegisterAllocation();
+
+    void emitIncomingValues(Value[] params);
+
+    /**
+     * Emits a return instruction. Implementations need to insert a move if the input is not in the
+     * correct location.
+     */
+    void emitReturn(Value input);
+}
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.loop;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class BasicInductionVariable extends InductionVariable {
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,11 +25,11 @@
 import static com.oracle.graal.nodes.calc.IntegerArithmeticNode.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.loop.InductionVariable.Direction;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 public class CountedLoopInfo {
 
@@ -37,9 +37,9 @@
     private InductionVariable iv;
     private ValueNode end;
     private boolean oneOff;
-    private AbstractBeginNode body;
+    private BeginNode body;
 
-    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, AbstractBeginNode body) {
+    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, BeginNode body) {
         this.loop = loop;
         this.iv = iv;
         this.end = end;
@@ -117,7 +117,7 @@
         return oneOff;
     }
 
-    public AbstractBeginNode getBody() {
+    public BeginNode getBody() {
         return body;
     }
 
@@ -143,14 +143,14 @@
         CompareNode cond; // we use a negated guard with a < condition to achieve a >=
         ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
         if (iv.direction() == Direction.Up) {
-            IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMaxValue(stamp.getBits(), stamp.isUnsigned()), graph), sub(graph, iv.strideNode(), one));
+            IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMaxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
             if (oneOff) {
                 v1 = sub(graph, v1, one);
             }
             cond = graph.unique(new IntegerLessThanNode(v1, end));
         } else {
             assert iv.direction() == Direction.Down;
-            IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits(), stamp.isUnsigned()), graph), sub(graph, one, iv.strideNode()));
+            IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
             if (oneOff) {
                 v1 = add(graph, v1, one);
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.loop;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class DerivedOffsetInductionVariable extends InductionVariable {
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.loop;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class DerivedScaledInductionVariable extends InductionVariable {
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.loop;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This class describes a value node that is an induction variable in a counted loop.
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,9 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -36,19 +39,19 @@
 
 public class LoopEx {
 
-    private final Loop lirLoop;
+    private final Loop<Block> lirLoop;
     private LoopFragmentInside inside;
     private LoopFragmentWhole whole;
     private CountedLoopInfo counted; // TODO (gd) detect
     private LoopsData data;
     private InductionVariables ivs;
 
-    LoopEx(Loop lirLoop, LoopsData data) {
+    LoopEx(Loop<Block> lirLoop, LoopsData data) {
         this.lirLoop = lirLoop;
         this.data = data;
     }
 
-    public Loop lirLoop() {
+    public Loop<Block> lirLoop() {
         return lirLoop;
     }
 
@@ -88,7 +91,7 @@
     }
 
     public LoopBeginNode loopBegin() {
-        return lirLoop().loopBegin();
+        return (LoopBeginNode) lirLoop().header.getBeginNode();
     }
 
     public FixedNode predecessor() {
@@ -123,7 +126,7 @@
         return (isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + lirLoop().depth + ") " + loopBegin();
     }
 
-    private class InvariantPredicate extends NodePredicate {
+    private class InvariantPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
@@ -222,9 +225,9 @@
         return data;
     }
 
-    public NodeBitMap nodesInLoopFrom(AbstractBeginNode point, AbstractBeginNode until) {
-        Collection<AbstractBeginNode> blocks = new LinkedList<>();
-        Collection<AbstractBeginNode> exits = new LinkedList<>();
+    public NodeBitMap nodesInLoopFrom(BeginNode point, BeginNode until) {
+        Collection<BeginNode> blocks = new LinkedList<>();
+        Collection<LoopExitNode> exits = new LinkedList<>();
         Queue<Block> work = new LinkedList<>();
         ControlFlowGraph cfg = loopsData().controlFlowGraph();
         work.add(cfg.blockFor(point));
@@ -235,7 +238,7 @@
                 continue;
             }
             if (lirLoop().exits.contains(b)) {
-                exits.add(b.getBeginNode());
+                exits.add((LoopExitNode) b.getBeginNode());
             } else if (lirLoop().blocks.contains(b)) {
                 blocks.add(b.getBeginNode());
                 work.addAll(b.getDominated());
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,14 +24,14 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.VirtualState.VirtualClosure;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
 
 public abstract class LoopFragment {
@@ -79,6 +79,15 @@
         duplicationMap.put(oldNode, newNode);
     }
 
+    /**
+     * Gets the corresponding value in this fragment. Should be called on duplicate fragments with a
+     * node from the original fragment as argument.
+     *
+     * @param b original value
+     * @return corresponding value in the peel
+     */
+    protected abstract ValueNode prim(ValueNode b);
+
     public boolean isDuplicate() {
         return original != null;
     }
@@ -141,13 +150,13 @@
         }
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks) {
-        return computeNodes(graph, blocks, Collections.<AbstractBeginNode> emptyList());
+    protected static NodeBitMap computeNodes(Graph graph, Iterable<BeginNode> blocks) {
+        return computeNodes(graph, blocks, Collections.emptyList());
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
+    protected static NodeBitMap computeNodes(Graph graph, Iterable<BeginNode> blocks, Iterable<LoopExitNode> earlyExits) {
         final NodeBitMap nodes = graph.createNodeBitMap(true);
-        for (AbstractBeginNode b : blocks) {
+        for (BeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
             }
@@ -156,30 +165,21 @@
                 if (n instanceof Invoke) {
                     nodes.mark(((Invoke) n).callTarget());
                 }
-                if (n instanceof StateSplit) {
-                    FrameState stateAfter = ((StateSplit) n).stateAfter();
-                    if (stateAfter != null) {
-                        nodes.mark(stateAfter);
-                    }
+                if (n instanceof NodeWithState) {
+                    NodeWithState withState = (NodeWithState) n;
+                    withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node)));
                 }
                 nodes.mark(n);
             }
         }
-        for (AbstractBeginNode earlyExit : earlyExits) {
+        for (LoopExitNode earlyExit : earlyExits) {
             if (earlyExit.isDeleted()) {
                 continue;
             }
 
             FrameState stateAfter = earlyExit.stateAfter();
             if (stateAfter != null) {
-                nodes.mark(stateAfter);
-                stateAfter.applyToVirtual(new VirtualClosure() {
-
-                    @Override
-                    public void apply(VirtualState node) {
-                        nodes.mark(node);
-                    }
-                });
+                stateAfter.applyToVirtual(node -> nodes.mark(node));
             }
             nodes.mark(earlyExit);
             for (ProxyNode proxy : earlyExit.proxies()) {
@@ -188,7 +188,7 @@
         }
 
         final NodeBitMap notloopNodes = graph.createNodeBitMap(true);
-        for (AbstractBeginNode b : blocks) {
+        for (BeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
             }
@@ -245,19 +245,19 @@
         return false;
     }
 
-    public static NodeIterable<AbstractBeginNode> toHirBlocks(final Iterable<Block> blocks) {
-        return new AbstractNodeIterable<AbstractBeginNode>() {
+    public static NodeIterable<BeginNode> toHirBlocks(final Iterable<Block> blocks) {
+        return new NodeIterable<BeginNode>() {
 
-            public Iterator<AbstractBeginNode> iterator() {
+            public Iterator<BeginNode> iterator() {
                 final Iterator<Block> it = blocks.iterator();
-                return new Iterator<AbstractBeginNode>() {
+                return new Iterator<BeginNode>() {
 
                     @Override
                     public void remove() {
                         throw new UnsupportedOperationException();
                     }
 
-                    public AbstractBeginNode next() {
+                    public BeginNode next() {
                         return it.next().getBeginNode();
                     }
 
@@ -270,6 +270,31 @@
         };
     }
 
+    public static NodeIterable<LoopExitNode> toHirExits(final Iterable<Block> blocks) {
+        return new NodeIterable<LoopExitNode>() {
+
+            public Iterator<LoopExitNode> iterator() {
+                final Iterator<Block> it = blocks.iterator();
+                return new Iterator<LoopExitNode>() {
+
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public LoopExitNode next() {
+                        return (LoopExitNode) it.next().getBeginNode();
+                    }
+
+                    public boolean hasNext() {
+                        return it.hasNext();
+                    }
+                };
+            }
+
+        };
+    }
+
     /**
      * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with
      * the original fragment's exits.
@@ -277,59 +302,56 @@
     protected void mergeEarlyExits() {
         assert isDuplicate();
         StructuredGraph graph = graph();
-        for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) {
-            FixedNode next = earlyExit.next();
-            if (earlyExit.isDeleted() || !this.original().contains(earlyExit)) {
+        for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) {
+            LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
+            FixedNode next = loopEarlyExit.next();
+            if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
                 continue;
             }
-            AbstractBeginNode newEarlyExit = getDuplicatedNode(earlyExit);
+            BeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
             if (newEarlyExit == null) {
                 continue;
             }
-            boolean newEarlyExitIsBegin = newEarlyExit instanceof BeginNode;
             MergeNode merge = graph.add(new MergeNode());
             AbstractEndNode originalEnd = graph.add(new EndNode());
             AbstractEndNode newEnd = graph.add(new EndNode());
             merge.addForwardEnd(originalEnd);
             merge.addForwardEnd(newEnd);
-            earlyExit.setNext(originalEnd);
+            loopEarlyExit.setNext(originalEnd);
             newEarlyExit.setNext(newEnd);
             merge.setNext(next);
 
-            FrameState exitState = earlyExit.stateAfter();
+            FrameState exitState = loopEarlyExit.stateAfter();
             FrameState state = null;
             if (exitState != null) {
                 state = exitState;
                 exitState = exitState.duplicateWithVirtualState();
-                earlyExit.setStateAfter(exitState);
+                loopEarlyExit.setStateAfter(exitState);
                 merge.setStateAfter(state);
                 /*
                  * Using the old exit's state as the merge's state is necessary because some of the
                  * VirtualState nodes contained in the old exit's state may be shared by other
                  * dominated VirtualStates. Those dominated virtual states need to see the
                  * proxy->phi update that are applied below.
-                 * 
+                 *
                  * We now update the original fragment's nodes accordingly:
                  */
-                state.applyToVirtual(new VirtualClosure() {
-                    public void apply(VirtualState node) {
-                        original.nodes.clear(node);
-                    }
-                });
-                exitState.applyToVirtual(new VirtualClosure() {
-                    public void apply(VirtualState node) {
-                        original.nodes.mark(node);
-                    }
-                });
+                state.applyToVirtual(node -> original.nodes.clear(node));
+                exitState.applyToVirtual(node -> original.nodes.mark(node));
+            }
+            FrameState finalExitState = exitState;
+
+            for (Node anchored : loopEarlyExit.anchored().snapshot()) {
+                anchored.replaceFirstInput(loopEarlyExit, merge);
             }
 
-            for (Node anchored : earlyExit.anchored().snapshot()) {
-                anchored.replaceFirstInput(earlyExit, merge);
-            }
-
-            for (final ProxyNode vpn : earlyExit.proxies().snapshot()) {
+            boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode;
+            for (final ProxyNode vpn : loopEarlyExit.proxies().snapshot()) {
+                if (vpn.usages().isEmpty()) {
+                    continue;
+                }
                 final ValueNode replaceWith;
-                ProxyNode newVpn = getDuplicatedNode(vpn);
+                ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
                 if (newVpn != null) {
                     PhiNode phi;
                     if (vpn instanceof ValueProxyNode) {
@@ -342,32 +364,23 @@
                         throw GraalInternalError.shouldNotReachHere();
                     }
                     phi.addInput(vpn);
-                    phi.addInput(newEarlyExitIsBegin ? newVpn.value() : newVpn);
+                    phi.addInput(newVpn);
                     replaceWith = phi;
                 } else {
                     replaceWith = vpn.value();
                 }
-                for (Node usage : vpn.usages().snapshot()) {
-                    if (!merge.isPhiAtMerge(usage)) {
-                        if (usage instanceof VirtualState) {
-                            VirtualState stateUsage = (VirtualState) usage;
-                            if (exitState.isPartOfThisState(stateUsage)) {
-                                continue;
-                            }
-                        }
-                        usage.replaceFirstInput(vpn, replaceWith);
+                vpn.replaceAtMatchingUsages(replaceWith, usage -> {
+                    if (merge.isPhiAtMerge(usage)) {
+                        return false;
                     }
-                }
-            }
-            if (newEarlyExitIsBegin) {
-                FrameState stateAtNewEarlyExit = newEarlyExit.stateAfter();
-                if (stateAtNewEarlyExit != null) {
-                    newEarlyExit.setStateAfter(null);
-                    GraphUtil.killWithUnusedFloatingInputs(stateAtNewEarlyExit);
-                }
-                for (ProxyNode proxy : newEarlyExit.proxies().snapshot()) {
-                    GraphUtil.killWithUnusedFloatingInputs(proxy);
-                }
+                    if (usage instanceof VirtualState) {
+                        VirtualState stateUsage = (VirtualState) usage;
+                        if (finalExitState.isPartOfThisState(stateUsage)) {
+                            return false;
+                        }
+                    }
+                    return true;
+                });
             }
         }
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,12 +24,12 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
-import com.oracle.graal.nodes.util.*;
 
 public class LoopFragmentInside extends LoopFragment {
 
@@ -88,18 +88,13 @@
 
         patchNodes(dataFixBefore);
 
-        AbstractBeginNode end = mergeEnds();
-
-        original().patchPeeling(this);
+        BeginNode end = mergeEnds();
 
         mergeEarlyExits();
 
-        AbstractBeginNode entry = getDuplicatedNode(loop.loopBegin());
-        FrameState state = entry.stateAfter();
-        if (state != null) {
-            entry.setStateAfter(null);
-            GraphUtil.killWithUnusedFloatingInputs(state);
-        }
+        original().patchPeeling(this);
+
+        BeginNode entry = getDuplicatedNode(loop.loopBegin());
         loop.entryPoint().replaceAtPredecessor(entry);
         end.setNext(loop.entryPoint());
     }
@@ -111,13 +106,31 @@
             whole.nodes(); // init nodes bitmap in whole
             nodes = whole.nodes.copy();
             // remove the phis
-            for (PhiNode phi : loop().loopBegin().phis()) {
+            LoopBeginNode loopBegin = loop().loopBegin();
+            for (PhiNode phi : loopBegin.phis()) {
                 nodes.clear(phi);
             }
+            for (LoopExitNode exit : exits()) {
+                FrameState exitState = exit.stateAfter();
+                if (exitState != null) {
+                    exitState.applyToVirtual(v -> {
+                        if (v.usages().filter(n -> nodes.isMarked(n) && !(n instanceof VirtualState && exitState.isPartOfThisState((VirtualState) n))).isEmpty()) {
+                            nodes.clear(v);
+                        }
+                    });
+                }
+                for (ProxyNode proxy : exit.proxies()) {
+                    nodes.clear(proxy);
+                }
+            }
         }
         return nodes;
     }
 
+    public NodeIterable<LoopExitNode> exits() {
+        return loop().loopBegin().loopExits();
+    }
+
     @Override
     protected DuplicationReplacement getDuplicationReplacement() {
         final LoopBeginNode loopBegin = loop().loopBegin();
@@ -183,7 +196,22 @@
         LoopBeginNode loopBegin = loop().loopBegin();
         StructuredGraph graph = loopBegin.graph();
         List<PhiNode> newPhis = new LinkedList<>();
+
+        NodeBitMap usagesToPatch = nodes.copy();
+        for (LoopExitNode exit : exits()) {
+            FrameState exitState = exit.stateAfter();
+            if (exitState != null) {
+                exitState.applyToVirtual(v -> usagesToPatch.mark(v));
+            }
+            for (ProxyNode proxy : exit.proxies()) {
+                usagesToPatch.mark(proxy);
+            }
+        }
+
         for (PhiNode phi : loopBegin.phis().snapshot()) {
+            if (phi.usages().isEmpty()) {
+                continue;
+            }
             ValueNode first;
             if (loopBegin.loopEnds().count() == 1) {
                 ValueNode b = phi.valueAt(loopBegin.loopEnds().first()); // back edge value
@@ -201,9 +229,8 @@
             peel.putDuplicatedNode(phi, newPhi);
             newPhis.add(newPhi);
             for (Node usage : phi.usages().snapshot()) {
-                if (peel.getDuplicatedNode(usage) != null) { // patch only usages that should use
-                                                             // the new phi ie usages that were
-                                                             // peeled
+                // patch only usages that should use the new phi ie usages that were peeled
+                if (usagesToPatch.isMarked(usage)) {
                     usage.replaceFirstInput(phi, newPhi);
                 }
             }
@@ -229,7 +256,8 @@
      * @param b original value
      * @return corresponding value in the peel
      */
-    private ValueNode prim(ValueNode b) {
+    @Override
+    protected ValueNode prim(ValueNode b) {
         assert isDuplicate();
         LoopBeginNode loopBegin = original().loop().loopBegin();
         if (loopBegin.isPhiAtMerge(b)) {
@@ -246,7 +274,7 @@
         }
     }
 
-    private AbstractBeginNode mergeEnds() {
+    private BeginNode mergeEnds() {
         assert isDuplicate();
         List<AbstractEndNode> endsToMerge = new LinkedList<>();
         Map<AbstractEndNode, LoopEndNode> reverseEnds = new HashMap<>(); // map peel's exit to the
@@ -260,7 +288,7 @@
             }
         }
         mergedInitializers = new IdentityHashMap<>();
-        AbstractBeginNode newExit;
+        BeginNode newExit;
         StructuredGraph graph = graph();
         if (endsToMerge.size() == 1) {
             AbstractEndNode end = endsToMerge.get(0);
@@ -283,6 +311,9 @@
             }
 
             for (final PhiNode phi : loopBegin.phis().snapshot()) {
+                if (phi.usages().isEmpty()) {
+                    continue;
+                }
                 final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge);
                 for (AbstractEndNode end : newExitMerge.forwardEnds()) {
                     LoopEndNode loopEnd = reverseEnds.get(end);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.loop;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
@@ -56,13 +57,18 @@
     @Override
     public NodeIterable<Node> nodes() {
         if (nodes == null) {
-            Loop lirLoop = loop().lirLoop();
-            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(lirLoop.blocks), LoopFragment.toHirBlocks(lirLoop.exits));
+            Loop<Block> lirLoop = loop().lirLoop();
+            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(lirLoop.blocks), LoopFragment.toHirExits(lirLoop.exits));
         }
         return nodes;
     }
 
     @Override
+    protected ValueNode prim(ValueNode b) {
+        return getDuplicatedNode(b);
+    }
+
+    @Override
     protected DuplicationReplacement getDuplicationReplacement() {
         final FixedNode entry = loop().entryPoint();
         final Graph graph = this.graph();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.loop;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -64,12 +64,12 @@
 
     public static boolean shouldUnswitch(LoopEx loop, ControlSplitNode controlSplit) {
         Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator();
-        AbstractBeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
+        BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
         int loopTotal = loop.size();
         int inBranchTotal = 0;
         double maxProbability = 0;
         for (Node successor : controlSplit.successors()) {
-            AbstractBeginNode branch = (AbstractBeginNode) successor;
+            BeginNode branch = (BeginNode) successor;
             inBranchTotal += loop.nodesInLoopFrom(branch, postDom).cardinality(); // this may count
                                                                                   // twice because
                                                                                   // of fall-through
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.loop;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.Graph.Mark;
@@ -63,6 +63,7 @@
             Mark mark = graph.getMark();
             peel(loop);
             canonicalizer.applyIncremental(graph, context, mark);
+            loopBegin.removeDeadPhis();
             loop.invalidateFragments();
             if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > MaximumDesiredSize.getValue() * 3) {
                 throw new BailoutException("FullUnroll : Graph seems to grow out of proportion");
@@ -81,19 +82,19 @@
         // original loop is used as first successor
         Position firstPosition = successors.nextPosition();
         NodeClass controlSplitClass = controlSplitNode.getNodeClass();
-        controlSplitClass.set(newControlSplit, firstPosition, AbstractBeginNode.begin(originalLoop.entryPoint()));
+        controlSplitClass.set(newControlSplit, firstPosition, BeginNode.begin(originalLoop.entryPoint()));
 
         StructuredGraph graph = controlSplitNode.graph();
         while (successors.hasNext()) {
             Position position = successors.nextPosition();
             // create a new loop duplicate, connect it and simplify it
             LoopFragmentWhole duplicateLoop = originalLoop.duplicate();
-            controlSplitClass.set(newControlSplit, position, AbstractBeginNode.begin(duplicateLoop.entryPoint()));
+            controlSplitClass.set(newControlSplit, position, BeginNode.begin(duplicateLoop.entryPoint()));
             ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode);
-            graph.removeSplitPropagate(duplicatedControlSplit, (AbstractBeginNode) controlSplitClass.get(duplicatedControlSplit, position));
+            graph.removeSplitPropagate(duplicatedControlSplit, (BeginNode) controlSplitClass.get(duplicatedControlSplit, position));
         }
         // original loop is simplified last to avoid deleting controlSplitNode too early
-        graph.removeSplitPropagate(controlSplitNode, (AbstractBeginNode) controlSplitClass.get(controlSplitNode, firstPosition));
+        graph.removeSplitPropagate(controlSplitNode, (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition));
         // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms)
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
@@ -31,7 +32,7 @@
 
 public class LoopsData {
 
-    private Map<Loop, LoopEx> lirLoopToEx = new IdentityHashMap<>();
+    private Map<Loop<Block>, LoopEx> lirLoopToEx = new IdentityHashMap<>();
     private Map<LoopBeginNode, LoopEx> loopBeginToEx = new IdentityHashMap<>();
     private ControlFlowGraph cfg;
 
@@ -42,14 +43,14 @@
             throw Debug.handle(e);
         }
 
-        for (Loop lirLoop : cfg.getLoops()) {
+        for (Loop<Block> lirLoop : cfg.getLoops()) {
             LoopEx ex = new LoopEx(lirLoop, this);
             lirLoopToEx.put(lirLoop, ex);
             loopBeginToEx.put(ex.loopBegin(), ex);
         }
     }
 
-    public LoopEx loop(Loop lirLoop) {
+    public LoopEx loop(Loop<?> lirLoop) {
         return lirLoopToEx.get(lirLoop);
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.loop.phases;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.loop.phases;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -78,7 +78,7 @@
         sb.append(loop).append(" at ").append(controlSplit).append(" [");
         NodeClassIterator it = controlSplit.successors().iterator();
         while (it.hasNext()) {
-            sb.append(controlSplit.probability((AbstractBeginNode) it.next()));
+            sb.append(controlSplit.probability((BeginNode) it.next()));
             if (it.hasNext()) {
                 sb.append(", ");
             }
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -44,83 +45,83 @@
 
     @Test
     public void testBooleanConstant() {
-        assertEquals(new IntegerStamp(32, false, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
+        assertEquals(new IntegerStamp(32, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
     }
 
     @Test
     public void testByteConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
+        assertEquals(new IntegerStamp(32, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp());
+        assertEquals(new IntegerStamp(32, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp());
     }
 
     @Test
     public void testShortConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
+        assertEquals(new IntegerStamp(32, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp());
     }
 
     @Test
     public void testCharConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
     }
 
     @Test
     public void testIntConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
+        assertEquals(new IntegerStamp(32, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testLongConstant() {
-        assertEquals(new IntegerStamp(64, false, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(64, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp());
+        assertEquals(new IntegerStamp(64, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp());
+        assertEquals(new IntegerStamp(64, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
+        assertEquals(new IntegerStamp(64, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(64, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testPositiveRanges() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0, 0), StampFactory.forInteger(Kind.Int, 0, 0));
-        assertEquals(new IntegerStamp(32, false, 0, 1, 0, 1), StampFactory.forInteger(Kind.Int, 0, 1));
-        assertEquals(new IntegerStamp(32, false, 0, 0x123, 0, 0x1ff), StampFactory.forInteger(Kind.Int, 0, 0x123));
-        assertEquals(new IntegerStamp(32, false, 0x120, 0x123, 0x120, 0x123), StampFactory.forInteger(Kind.Int, 0x120, 0x123));
-        assertEquals(new IntegerStamp(32, false, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Int, 10000, 15000));
-        assertEquals(new IntegerStamp(64, false, 0, 1, 0, 1), StampFactory.forInteger(Kind.Long, 0, 1));
-        assertEquals(new IntegerStamp(64, false, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Long, 10000, 15000));
-        assertEquals(new IntegerStamp(64, false, 140000000000L, 150000000000L, 0x2000000000L, 0x23ffffffffL), StampFactory.forInteger(Kind.Long, 140000000000L, 150000000000L));
+        assertEquals(new IntegerStamp(32, 0, 0, 0, 0), StampFactory.forInteger(Kind.Int, 0, 0));
+        assertEquals(new IntegerStamp(32, 0, 1, 0, 1), StampFactory.forInteger(Kind.Int, 0, 1));
+        assertEquals(new IntegerStamp(32, 0, 0x123, 0, 0x1ff), StampFactory.forInteger(Kind.Int, 0, 0x123));
+        assertEquals(new IntegerStamp(32, 0x120, 0x123, 0x120, 0x123), StampFactory.forInteger(Kind.Int, 0x120, 0x123));
+        assertEquals(new IntegerStamp(32, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Int, 10000, 15000));
+        assertEquals(new IntegerStamp(64, 0, 1, 0, 1), StampFactory.forInteger(Kind.Long, 0, 1));
+        assertEquals(new IntegerStamp(64, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Long, 10000, 15000));
+        assertEquals(new IntegerStamp(64, 140000000000L, 150000000000L, 0x2000000000L, 0x23ffffffffL), StampFactory.forInteger(Kind.Long, 140000000000L, 150000000000L));
     }
 
     @Test
     public void testNegativeRanges() {
-        assertEquals(new IntegerStamp(32, false, -2, -1, 0xfffffffeL, 0xffffffffL), StampFactory.forInteger(Kind.Int, -2, -1));
-        assertEquals(new IntegerStamp(32, false, -20, -10, 0xffffffe0L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -20, -10));
-        assertEquals(new IntegerStamp(32, false, -10000, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 0));
-        assertEquals(new IntegerStamp(32, false, -10000, -1, 0xffffc000L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, -1));
-        assertEquals(new IntegerStamp(32, false, -10010, -10000, 0xffffd8e0L, 0xffffd8ffL), StampFactory.forInteger(Kind.Int, -10010, -10000));
-        assertEquals(new IntegerStamp(64, false, -2, -1, 0xfffffffffffffffeL, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -2, -1));
-        assertEquals(new IntegerStamp(64, false, -10010, -10000, 0xffffffffffffd8e0L, 0xffffffffffffd8ffL), StampFactory.forInteger(Kind.Long, -10010, -10000));
-        assertEquals(new IntegerStamp(64, false, -150000000000L, -140000000000L, 0xffffffdc00000000L, 0xffffffdfffffffffL), StampFactory.forInteger(Kind.Long, -150000000000L, -140000000000L));
+        assertEquals(new IntegerStamp(32, -2, -1, 0xfffffffeL, 0xffffffffL), StampFactory.forInteger(Kind.Int, -2, -1));
+        assertEquals(new IntegerStamp(32, -20, -10, 0xffffffe0L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -20, -10));
+        assertEquals(new IntegerStamp(32, -10000, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 0));
+        assertEquals(new IntegerStamp(32, -10000, -1, 0xffffc000L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, -1));
+        assertEquals(new IntegerStamp(32, -10010, -10000, 0xffffd8e0L, 0xffffd8ffL), StampFactory.forInteger(Kind.Int, -10010, -10000));
+        assertEquals(new IntegerStamp(64, -2, -1, 0xfffffffffffffffeL, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -2, -1));
+        assertEquals(new IntegerStamp(64, -10010, -10000, 0xffffffffffffd8e0L, 0xffffffffffffd8ffL), StampFactory.forInteger(Kind.Long, -10010, -10000));
+        assertEquals(new IntegerStamp(64, -150000000000L, -140000000000L, 0xffffffdc00000000L, 0xffffffdfffffffffL), StampFactory.forInteger(Kind.Long, -150000000000L, -140000000000L));
     }
 
     @Test
     public void testMixedRanges() {
-        assertEquals(new IntegerStamp(32, false, -1, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -1, 0));
-        assertEquals(new IntegerStamp(32, false, -10000, 1000, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 1000));
-        assertEquals(new IntegerStamp(64, false, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000));
+        assertEquals(new IntegerStamp(32, -1, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -1, 0));
+        assertEquals(new IntegerStamp(32, -10000, 1000, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 1000));
+        assertEquals(new IntegerStamp(64, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000));
     }
 
     @Test
@@ -159,15 +160,15 @@
 
     @Test
     public void testXor() {
-        assertEquals(new IntegerStamp(32, false, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, false, 0, 0, 0, 0), new IntegerStamp(32, false, 0, 0xff, 0, 0xff)));
-        assertEquals(new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, false, 0, 0, 0, 0), new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(32, false, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, false, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, false, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, false, 0x0, 0xf, 0x0, 0xf)));
+        assertEquals(new IntegerStamp(32, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0, 0xff, 0, 0xff)));
+        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf)));
     }
 
     @Test
     public void testNot() {
-        assertEquals(new IntegerStamp(32, false, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, false, 0, 10, 0, 0xf)));
+        assertEquals(new IntegerStamp(32, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, 0, 10, 0, 0xf)));
     }
 
     @Test
@@ -258,13 +259,13 @@
 
     @Test
     public void testAnd() {
-        assertEquals(new IntegerStamp(32, false, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
+        assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
     }
 
     private static void testSignExtendShort(long lower, long upper) {
-        Stamp shortStamp = StampFactory.forInteger(16, false, lower, upper);
+        Stamp shortStamp = StampFactory.forInteger(16, lower, upper);
         Stamp intStamp = StampTool.signExtend(shortStamp, 32);
-        assertEquals(StampFactory.forInteger(32, false, lower, upper), intStamp);
+        assertEquals(StampFactory.forInteger(32, lower, upper), intStamp);
     }
 
     @Test
@@ -278,9 +279,9 @@
     }
 
     private static void testZeroExtendShort(long lower, long upper, long newLower, long newUpper) {
-        Stamp shortStamp = StampFactory.forInteger(16, false, lower, upper);
+        Stamp shortStamp = StampFactory.forInteger(16, lower, upper);
         Stamp intStamp = StampTool.zeroExtend(shortStamp, 32);
-        assertEquals(StampFactory.forInteger(32, false, newLower, newUpper), intStamp);
+        assertEquals(StampFactory.forInteger(32, newLower, newUpper), intStamp);
     }
 
     @Test
@@ -292,36 +293,4 @@
         testZeroExtendShort(-1, 1, 0, 0xFFFF);
         testZeroExtendShort(Short.MIN_VALUE, Short.MAX_VALUE, 0, 0xFFFF);
     }
-
-    private static void testSignExtendChar(long lower, long upper, long newLower, long newUpper) {
-        Stamp charStamp = StampFactory.forInteger(16, true, lower, upper);
-        Stamp uintStamp = StampTool.signExtend(charStamp, 32);
-        assertEquals(StampFactory.forInteger(32, true, newLower, newUpper), uintStamp);
-    }
-
-    @Test
-    public void testSignExtendUnsigned() {
-        testSignExtendChar(5, 7, 5, 7);
-        testSignExtendChar(0, 42, 0, 42);
-        testSignExtendChar(5, 0xF000, 5, 0xFFFFF000L);
-        testSignExtendChar(0, 0xF000, 0, 0xFFFFF000L);
-        testSignExtendChar(0xF000, Character.MAX_VALUE, 0xFFFFF000L, 0xFFFFFFFFL);
-        testSignExtendChar(Character.MIN_VALUE, Character.MAX_VALUE, 0, 0xFFFFFFFFL);
-    }
-
-    private static void testZeroExtendChar(long lower, long upper) {
-        Stamp charStamp = StampFactory.forInteger(16, true, lower, upper);
-        Stamp uintStamp = StampTool.zeroExtend(charStamp, 32);
-        assertEquals(StampFactory.forInteger(32, true, lower, upper), uintStamp);
-    }
-
-    @Test
-    public void testZeroExtendUnsigned() {
-        testZeroExtendChar(5, 7);
-        testZeroExtendChar(0, 42);
-        testZeroExtendChar(5, 0xF000);
-        testZeroExtendChar(0, 0xF000);
-        testZeroExtendChar(0xF000, Character.MAX_VALUE);
-        testZeroExtendChar(Character.MIN_VALUE, Character.MAX_VALUE);
-    }
 }
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/ObjectStampJoinTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/ObjectStampJoinTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -80,7 +81,7 @@
     public void testJoin3() {
         Stamp d = StampFactory.declared(getType(D.class));
         Stamp c = StampFactory.declared(getType(C.class));
-        Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join(c, d)));
+        Assert.assertTrue(StampTool.isObjectAlwaysNull(join(c, d)));
     }
 
     @Test
@@ -95,9 +96,9 @@
         Stamp dExact = StampFactory.exact(getType(D.class));
         Stamp c = StampFactory.declared(getType(C.class));
         Stamp join = join(c, dExact);
-        Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join));
-        Assert.assertNull(ObjectStamp.typeOrNull(join));
-        Assert.assertFalse(ObjectStamp.isExactType(join));
+        Assert.assertTrue(StampTool.isObjectAlwaysNull(join));
+        Assert.assertNull(StampTool.typeOrNull(join));
+        Assert.assertFalse(StampTool.isExactType(join));
     }
 
     @Test
@@ -106,8 +107,8 @@
         Stamp alwaysNull = StampFactory.alwaysNull();
         Stamp join = join(alwaysNull, dExactNonNull);
         Assert.assertFalse(join.isLegal());
-        Assert.assertFalse(ObjectStamp.isObjectNonNull(join));
-        Assert.assertFalse(ObjectStamp.isObjectAlwaysNull(join));
+        Assert.assertFalse(StampTool.isObjectNonNull(join));
+        Assert.assertFalse(StampTool.isObjectAlwaysNull(join));
     }
 
     @Test
@@ -115,9 +116,9 @@
         Stamp aExact = StampFactory.exact(getType(A.class));
         Stamp e = StampFactory.declared(getType(E.class));
         Stamp join = join(aExact, e);
-        Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join));
-        Assert.assertNull(ObjectStamp.typeOrNull(join));
-        Assert.assertFalse(ObjectStamp.isExactType(join));
+        Assert.assertTrue(StampTool.isObjectAlwaysNull(join));
+        Assert.assertNull(StampTool.typeOrNull(join));
+        Assert.assertFalse(StampTool.isExactType(join));
     }
 
     @Test
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
-public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
-
-    @Input(InputType.State) private FrameState stateAfter;
-
-    public FrameState stateAfter() {
-        return stateAfter;
-    }
-
-    public void setStateAfter(FrameState x) {
-        assert x == null || x.isAlive() : "frame state must be in a graph";
-        updateUsages(stateAfter, x);
-        stateAfter = x;
-    }
-
-    public boolean hasSideEffect() {
-        return false;
-    }
-
-    protected AbstractBeginNode() {
-        super(StampFactory.forVoid());
-    }
-
-    protected AbstractBeginNode(Stamp stamp) {
-        super(stamp);
-    }
-
-    public static AbstractBeginNode begin(FixedNode with) {
-        if (with instanceof AbstractBeginNode) {
-            return (AbstractBeginNode) with;
-        }
-        AbstractBeginNode begin = with.graph().add(new BeginNode());
-        begin.setNext(with);
-        return begin;
-    }
-
-    @Override
-    public void simplify(SimplifierTool tool) {
-        FixedNode prev = (FixedNode) this.predecessor();
-        if (prev == null) {
-            // This is the start node.
-        } else if (prev instanceof ControlSplitNode) {
-            // This begin node is necessary.
-        } else {
-            // This begin node can be removed and all guards moved up to the preceding begin node.
-            prepareDelete();
-            tool.addToWorkList(next());
-            graph().removeFixed(this);
-        }
-    }
-
-    public static AbstractBeginNode prevBegin(FixedNode from) {
-        Node prevBegin = from;
-        while (prevBegin != null) {
-            if (prevBegin instanceof AbstractBeginNode) {
-                return (AbstractBeginNode) prevBegin;
-            }
-            prevBegin = prevBegin.predecessor();
-        }
-        return null;
-    }
-
-    private void evacuateGuards(FixedNode evacuateFrom) {
-        if (!usages().isEmpty()) {
-            AbstractBeginNode prevBegin = prevBegin(evacuateFrom);
-            assert prevBegin != null;
-            for (Node anchored : anchored().snapshot()) {
-                anchored.replaceFirstInput(this, prevBegin);
-            }
-        }
-    }
-
-    public void prepareDelete() {
-        prepareDelete((FixedNode) predecessor());
-    }
-
-    public void prepareDelete(FixedNode evacuateFrom) {
-        removeProxies();
-        evacuateGuards(evacuateFrom);
-    }
-
-    public void removeProxies() {
-        for (ProxyNode vpn : proxies().snapshot()) {
-            // can not use graph.replaceFloating because vpn.value may be null during killCFG
-            vpn.replaceAtUsages(vpn.value());
-            vpn.safeDelete();
-        }
-    }
-
-    @Override
-    public boolean verify() {
-        assertTrue(predecessor() != null || this == graph().start() || this instanceof MergeNode, "begin nodes must be connected");
-        return super.verify();
-    }
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        // nop
-    }
-
-    public NodeIterable<GuardNode> guards() {
-        return usages().filter(GuardNode.class);
-    }
-
-    public NodeIterable<Node> anchored() {
-        return usages().filter(isNotA(ProxyNode.class));
-    }
-
-    public NodeIterable<ProxyNode> proxies() {
-        return usages().filter(ProxyNode.class);
-    }
-
-    public NodeIterable<FixedNode> getBlockNodes() {
-        return new AbstractNodeIterable<FixedNode>() {
-
-            @Override
-            public Iterator<FixedNode> iterator() {
-                return new BlockNodeIterator(AbstractBeginNode.this);
-            }
-        };
-    }
-
-    private class BlockNodeIterator implements Iterator<FixedNode> {
-
-        private FixedNode current;
-
-        public BlockNodeIterator(FixedNode next) {
-            this.current = next;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return current != null;
-        }
-
-        @Override
-        public FixedNode next() {
-            FixedNode ret = current;
-            if (ret == null) {
-                throw new NoSuchElementException();
-            }
-            if (!(current instanceof FixedWithNextNode) || (current instanceof AbstractBeginNode && current != AbstractBeginNode.this)) {
-                current = null;
-            } else {
-                current = ((FixedWithNextNode) current).next();
-            }
-            return ret;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    public FrameState getState() {
-        return stateAfter();
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node represents an unconditional explicit request for immediate deoptimization.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,9 +24,9 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode {
@@ -89,7 +89,7 @@
         DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
         deopt.setStateBefore(stateBefore());
         IfNode ifNode;
-        AbstractBeginNode noDeoptSuccessor;
+        BeginNode noDeoptSuccessor;
         if (negated) {
             ifNode = graph().add(new IfNode(condition, deopt, next, 0));
             noDeoptSuccessor = ifNode.falseSuccessor();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class AbstractLocalNode extends FloatingNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Provides an implementation of {@link StateSplit}.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Provides an implementation of {@link StateSplit}.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,11 +22,153 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
+import java.util.*;
 
-public final class BeginNode extends AbstractBeginNode {
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
+public class BeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
 
     public BeginNode() {
         super(StampFactory.forVoid());
     }
+
+    public BeginNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    public static BeginNode begin(FixedNode with) {
+        if (with instanceof BeginNode) {
+            return (BeginNode) with;
+        }
+        BeginNode begin = with.graph().add(new BeginNode());
+        begin.setNext(with);
+        return begin;
+    }
+
+    @Override
+    public void simplify(SimplifierTool tool) {
+        FixedNode prev = (FixedNode) this.predecessor();
+        if (prev == null) {
+            // This is the start node.
+        } else if (prev instanceof ControlSplitNode) {
+            // This begin node is necessary.
+        } else {
+            // This begin node can be removed and all guards moved up to the preceding begin node.
+            prepareDelete();
+            tool.addToWorkList(next());
+            graph().removeFixed(this);
+        }
+    }
+
+    public static BeginNode prevBegin(FixedNode from) {
+        Node prevBegin = from;
+        while (prevBegin != null) {
+            if (prevBegin instanceof BeginNode) {
+                return (BeginNode) prevBegin;
+            }
+            prevBegin = prevBegin.predecessor();
+        }
+        return null;
+    }
+
+    private void evacuateGuards(FixedNode evacuateFrom) {
+        if (!usages().isEmpty()) {
+            BeginNode prevBegin = prevBegin(evacuateFrom);
+            assert prevBegin != null;
+            for (Node anchored : anchored().snapshot()) {
+                anchored.replaceFirstInput(this, prevBegin);
+            }
+        }
+    }
+
+    public void prepareDelete() {
+        prepareDelete((FixedNode) predecessor());
+    }
+
+    public void prepareDelete(FixedNode evacuateFrom) {
+        removeProxies();
+        evacuateGuards(evacuateFrom);
+    }
+
+    public void removeProxies() {
+        for (ProxyNode vpn : proxies().snapshot()) {
+            // can not use graph.replaceFloating because vpn.value may be null during killCFG
+            vpn.replaceAtUsages(vpn.value());
+            vpn.safeDelete();
+        }
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(predecessor() != null || this == graph().start() || this instanceof MergeNode, "begin nodes must be connected");
+        return super.verify();
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        // nop
+    }
+
+    public NodeIterable<GuardNode> guards() {
+        return usages().filter(GuardNode.class);
+    }
+
+    public NodeIterable<Node> anchored() {
+        return usages().filter(isNotA(ProxyNode.class));
+    }
+
+    public NodeIterable<ProxyNode> proxies() {
+        return usages().filter(ProxyNode.class);
+    }
+
+    public NodeIterable<FixedNode> getBlockNodes() {
+        return new NodeIterable<FixedNode>() {
+
+            @Override
+            public Iterator<FixedNode> iterator() {
+                return new BlockNodeIterator(BeginNode.this);
+            }
+        };
+    }
+
+    private class BlockNodeIterator implements Iterator<FixedNode> {
+
+        private FixedNode current;
+
+        public BlockNodeIterator(FixedNode next) {
+            this.current = next;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return current != null;
+        }
+
+        @Override
+        public FixedNode next() {
+            FixedNode ret = current;
+            if (ret == null) {
+                throw new NoSuchElementException();
+            }
+            if (!(current instanceof FixedWithNextNode) || (current instanceof BeginNode && current != BeginNode.this)) {
+                current = null;
+            } else {
+                current = ((FixedWithNextNode) current).next();
+            }
+            return ret;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,16 +22,19 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
 
 /**
- * Base class for {@link AbstractBeginNode}s that are associated with a frame state.
- * 
- * TODO (dnsimon) this not needed until {@link AbstractBeginNode} no longer implements
- * {@link StateSplit} which is not possible until loop peeling works without requiring begin nodes
- * to have frames states.
+ * Base class for {@link BeginNode}s that are associated with a frame state.
+ *
+ * TODO (dnsimon) this not needed until {@link BeginNode} no longer implements {@link StateSplit}
+ * which is not possible until loop peeling works without requiring begin nodes to have frames
+ * states.
  */
-public abstract class BeginStateSplitNode extends AbstractBeginNode implements StateSplit {
+public abstract class BeginStateSplitNode extends BeginNode implements StateSplit {
+
+    @Input(InputType.State) private FrameState stateAfter;
 
     public BeginStateSplitNode() {
     }
@@ -40,6 +43,16 @@
         super(stamp);
     }
 
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    public void setStateAfter(FrameState x) {
+        assert x == null || x.isAlive() : "frame state must be in a graph";
+        updateUsages(stateAfter, x);
+        stateAfter = x;
+    }
+
     /**
      * A begin node has no side effect.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryLogicNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011, 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;
+
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+public abstract class BinaryLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable {
+
+    @Input private ValueNode x;
+    @Input private ValueNode y;
+
+    public ValueNode x() {
+        return x;
+    }
+
+    public ValueNode y() {
+        return y;
+    }
+
+    protected void setX(ValueNode x) {
+        updateUsages(this.x, x);
+        this.x = x;
+    }
+
+    protected void setY(ValueNode y) {
+        updateUsages(this.y, y);
+        this.y = y;
+    }
+
+    public BinaryLogicNode(ValueNode x, ValueNode y) {
+        assert x != null && y != null && x.getKind() == y.getKind();
+        this.x = x;
+        this.y = y;
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
+        return super.verify();
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+    }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        return false;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A node that results in a platform dependent breakpoint instruction being emitted. A number of
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,11 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
-@NodeInfo(allowedUsageTypes = {InputType.Association})
+@NodeInfo(allowedUsageTypes = {InputType.Extension})
 public abstract class CallTargetNode extends ValueNode implements LIRLowerable {
 
     @Input private final NodeInputList<ValueNode> arguments;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
-@NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})")
+@NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard})
 public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable, Lowerable, GuardingNode {
 
     @Input(InputType.Condition) private LogicNode condition;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,12 +25,13 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ConstantNode} represents a {@link Constant constant}.
@@ -175,7 +176,8 @@
     public static ConstantNode forPrimitive(Stamp stamp, Constant constant, StructuredGraph graph) {
         if (stamp instanceof IntegerStamp) {
             assert constant.getKind().isNumericInteger() && stamp.getStackKind() == constant.getKind().getStackKind();
-            return forIntegerStamp(stamp, constant.asLong(), graph);
+            IntegerStamp istamp = (IntegerStamp) stamp;
+            return forIntegerBits(istamp.getBits(), constant, graph);
         } else {
             assert constant.getKind().isNumericFloat() && stamp.getStackKind() == constant.getKind();
             return forPrimitive(constant, graph);
@@ -262,35 +264,22 @@
         return unique(graph, createPrimitive(Constant.forInt(i)));
     }
 
-    /**
-     * Returns a node for an object constant.
-     *
-     * @param o the object value for which to create the instruction
-     * @return a node representing the object
-     */
-    public static ConstantNode forObject(Object o, MetaAccessProvider metaAccess, StructuredGraph graph) {
-        assert !(o instanceof Constant) : "wrapping a Constant into a Constant";
-        Constant constant = Constant.forObject(o);
-        return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess)));
+    private static ConstantNode unique(StructuredGraph graph, ConstantNode node) {
+        return graph.unique(node);
     }
 
-    private static ConstantNode unique(StructuredGraph graph, ConstantNode node) {
-        return graph.unique(node);
+    private static ConstantNode forIntegerBits(int bits, Constant constant, StructuredGraph graph) {
+        long value = constant.asLong();
+        long bounds = SignExtendNode.signExtend(value, bits);
+        return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)));
     }
 
     /**
      * Returns a node for a constant integer that's not directly representable as Java primitive
      * (e.g. short).
      */
-    public static ConstantNode forIntegerBits(int bits, boolean unsigned, long value, StructuredGraph graph) {
-        Constant constant = Constant.forPrimitiveInt(bits, value);
-        long bounds;
-        if (unsigned) {
-            bounds = ZeroExtendNode.zeroExtend(value, bits);
-        } else {
-            bounds = SignExtendNode.signExtend(value, bits);
-        }
-        return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, unsigned, bounds, bounds)));
+    public static ConstantNode forIntegerBits(int bits, long value, StructuredGraph graph) {
+        return forIntegerBits(bits, Constant.forPrimitiveInt(bits, value), graph);
     }
 
     /**
@@ -299,7 +288,7 @@
     public static ConstantNode forIntegerStamp(Stamp stamp, long value, StructuredGraph graph) {
         if (stamp instanceof IntegerStamp) {
             IntegerStamp intStamp = (IntegerStamp) stamp;
-            return forIntegerBits(intStamp.getBits(), intStamp.isUnsigned(), value, graph);
+            return forIntegerBits(intStamp.getBits(), value, graph);
         } else {
             return forIntegerKind(stamp.getStackKind(), value, graph);
         }
@@ -351,7 +340,7 @@
             case Long:
                 return ConstantNode.forLong(0L, graph);
             case Object:
-                return ConstantNode.forObject(null, null, graph);
+                return ConstantNode.forConstant(Constant.NULL_OBJECT, null, graph);
             default:
                 return null;
         }
@@ -360,14 +349,14 @@
     @Override
     public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
         Map<Object, Object> properties = super.getDebugProperties(map);
-        properties.put("rawvalue", value.getKind() == Kind.Object ? value.getKind().format(value.asBoxedValue()) : value.asBoxedValue());
+        properties.put("rawvalue", value.toValueString());
         return properties;
     }
 
     @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
-            return super.toString(Verbosity.Name) + "(" + value.getKind().format(value.asBoxedValue()) + ")";
+            return super.toString(Verbosity.Name) + "(" + value.toValueString() + ")";
         } else {
             return super.toString(verbosity);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public abstract class ControlSinkNode extends FixedNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ControlSplitNode} is a base class for all instructions that split the control flow
@@ -35,7 +35,7 @@
         super(stamp);
     }
 
-    public abstract double probability(AbstractBeginNode successor);
+    public abstract double probability(BeginNode successor);
 
-    public abstract void setProbability(AbstractBeginNode successor, double value);
+    public abstract void setProbability(BeginNode successor, double value);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -63,7 +63,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, this);
+        gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, gen.state(this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode.DeoptBefore {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public class DirectCallTargetNode extends LoweredCallTargetNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 /**
  * The entry node of an exception dispatcher block.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -55,7 +55,7 @@
     }
 
     public void generate(NodeLIRBuilderTool generator) {
-        generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), this);
+        generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), generator.state(this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.spi.*;
@@ -31,7 +32,7 @@
  * by the graph builder.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Association})
-public class EntryMarkerNode extends AbstractBeginNode implements IterableNodeType, Simplifiable, LIRLowerable {
+public class EntryMarkerNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable, LIRLowerable {
 
     @Override
     public void simplify(SimplifierTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public abstract class FixedNode extends ValueNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 /**
  * Base class of all nodes that are fixed within the control flow graph and have an immediate
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingAnchoredNode extends FloatingNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingGuardedNode extends FloatingNode implements GuardedNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Wed Apr 23 15:48:38 2014 +0200
@@ -51,35 +51,6 @@
 
     private boolean duringCall;
 
-    /**
-     * This BCI should be used for frame states that are built for code with no meaningful BCI.
-     */
-    public static final int UNKNOWN_BCI = -4;
-
-    /**
-     * When a node whose frame state has this BCI value is inlined, its frame state will be replaced
-     * with the frame state before the inlined invoke node.
-     */
-    public static final int BEFORE_BCI = -1;
-
-    /**
-     * When a node whose frame state has this BCI value is inlined, its frame state will be replaced
-     * with the frame state {@linkplain Invoke#stateAfter() after} the inlined invoke node.
-     */
-    public static final int AFTER_BCI = -2;
-
-    /**
-     * When a node whose frame state has this BCI value is inlined, its frame state will be replaced
-     * with the frame state at the exception edge of the inlined invoke node.
-     */
-    public static final int AFTER_EXCEPTION_BCI = -3;
-
-    /**
-     * This BCI should be used for frame states that cannot be the target of a deoptimization, like
-     * snippet frame states.
-     */
-    public static final int INVALID_FRAMESTATE_BCI = -5;
-
     @Input(InputType.State) private FrameState outerFrameState;
 
     /**
@@ -135,7 +106,8 @@
      */
     public FrameState(int bci) {
         this(null, bci, Collections.<ValueNode> emptyList(), 0, 0, false, false, Collections.<MonitorIdNode> emptyList(), Collections.<EscapeObjectState> emptyList());
-        assert bci == BEFORE_BCI || bci == AFTER_BCI || bci == AFTER_EXCEPTION_BCI || bci == UNKNOWN_BCI || bci == INVALID_FRAMESTATE_BCI;
+        assert bci == BytecodeFrame.BEFORE_BCI || bci == BytecodeFrame.AFTER_BCI || bci == BytecodeFrame.AFTER_EXCEPTION_BCI || bci == BytecodeFrame.UNKNOWN_BCI ||
+                        bci == BytecodeFrame.INVALID_FRAMESTATE_BCI;
     }
 
     public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List<ValueNode> stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, boolean duringCall) {
@@ -395,6 +367,19 @@
                 properties.put("sourceLine", ste.getLineNumber());
             }
         }
+        if (bci == BytecodeFrame.AFTER_BCI) {
+            properties.put("bci", "AFTER_BCI");
+        } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
+            properties.put("bci", "AFTER_EXCEPTION_BCI");
+        } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+            properties.put("bci", "INVALID_FRAMESTATE_BCI");
+        } else if (bci == BytecodeFrame.BEFORE_BCI) {
+            properties.put("bci", "BEFORE_BCI");
+        } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
+            properties.put("bci", "UNKNOWN_BCI");
+        } else if (bci == BytecodeFrame.UNWIND_BCI) {
+            properties.put("bci", "UNWIND_BCI");
+        }
         properties.put("locksSize", values.size() - stackSize - localsSize);
         return properties;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A guard is a node that deoptimizes based on a conditional expression. Guards are not attached to
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "GuardPhi({i#values})", allowedUsageTypes = {InputType.Guard})
 public class GuardPhiNode extends PhiNode implements GuardingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,22 +22,26 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Guard})
-public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy {
+public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy, LIRLowerable {
 
     @Input(InputType.Guard) private GuardingNode value;
 
-    public GuardProxyNode(GuardingNode value, AbstractBeginNode proxyPoint) {
+    public GuardProxyNode(GuardingNode value, BeginNode proxyPoint) {
         super(StampFactory.forVoid(), proxyPoint);
         this.value = value;
     }
 
     @Override
+    public void generate(NodeLIRBuilderTool generator) {
+    }
+
+    @Override
     public ValueNode value() {
         return value.asNode();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A node that changes the type of its input, usually narrowing it. For example, a GuardedValueNode
@@ -77,7 +77,7 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (getGuard() == graph().start()) {
+        if (getGuard() == graph().start() || getGuard() == null) {
             if (stamp().equals(object().stamp())) {
                 return object();
             } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.calc.*;
@@ -87,7 +88,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
-        if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
+        if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
             tool.replaceWithVirtual(state.getVirtualObject());
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -35,7 +37,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -44,8 +45,8 @@
  */
 public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, MemoryArithmeticLIRLowerable {
 
-    @Successor private AbstractBeginNode trueSuccessor;
-    @Successor private AbstractBeginNode falseSuccessor;
+    @Successor private BeginNode trueSuccessor;
+    @Successor private BeginNode falseSuccessor;
     @Input(InputType.Condition) private LogicNode condition;
     private double trueSuccessorProbability;
 
@@ -59,10 +60,10 @@
     }
 
     public IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) {
-        this(condition, AbstractBeginNode.begin(trueSuccessor), AbstractBeginNode.begin(falseSuccessor), trueSuccessorProbability);
+        this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), trueSuccessorProbability);
     }
 
-    public IfNode(LogicNode condition, AbstractBeginNode trueSuccessor, AbstractBeginNode falseSuccessor, double trueSuccessorProbability) {
+    public IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
         super(StampFactory.forVoid());
         this.condition = condition;
         this.falseSuccessor = falseSuccessor;
@@ -76,7 +77,7 @@
      *
      * @return the true successor
      */
-    public AbstractBeginNode trueSuccessor() {
+    public BeginNode trueSuccessor() {
         return trueSuccessor;
     }
 
@@ -85,16 +86,16 @@
      *
      * @return the false successor
      */
-    public AbstractBeginNode falseSuccessor() {
+    public BeginNode falseSuccessor() {
         return falseSuccessor;
     }
 
-    public void setTrueSuccessor(AbstractBeginNode node) {
+    public void setTrueSuccessor(BeginNode node) {
         updatePredecessor(trueSuccessor, node);
         trueSuccessor = node;
     }
 
-    public void setFalseSuccessor(AbstractBeginNode node) {
+    public void setFalseSuccessor(BeginNode node) {
         updatePredecessor(falseSuccessor, node);
         falseSuccessor = node;
     }
@@ -105,7 +106,7 @@
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
      * @return the corresponding successor
      */
-    public AbstractBeginNode successor(boolean istrue) {
+    public BeginNode successor(boolean istrue) {
         return istrue ? trueSuccessor : falseSuccessor;
     }
 
@@ -115,12 +116,12 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         return successor == trueSuccessor ? trueSuccessorProbability : 1 - trueSuccessorProbability;
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         assert successor == trueSuccessor || successor == falseSuccessor;
         setTrueSuccessorProbability(successor == trueSuccessor ? value : 1 - value);
     }
@@ -146,8 +147,8 @@
     @Override
     public void simplify(SimplifierTool tool) {
         if (condition() instanceof LogicNegationNode) {
-            AbstractBeginNode trueSucc = trueSuccessor();
-            AbstractBeginNode falseSucc = falseSuccessor();
+            BeginNode trueSucc = trueSuccessor();
+            BeginNode falseSucc = falseSuccessor();
             setTrueSuccessor(null);
             setFalseSuccessor(null);
             LogicNegationNode negation = (LogicNegationNode) condition();
@@ -156,6 +157,41 @@
             this.safeDelete();
             return;
         }
+        if (trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty()) {
+            // push similar nodes upwards through the if, thereby deduplicating them
+            do {
+                BeginNode trueSucc = trueSuccessor();
+                BeginNode falseSucc = falseSuccessor();
+                if (trueSucc.getClass() == BeginNode.class && falseSucc.getClass() == BeginNode.class && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) {
+                    FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next();
+                    FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next();
+                    NodeClass nodeClass = trueNext.getNodeClass();
+                    if (trueNext.getClass() == falseNext.getClass()) {
+                        if (nodeClass.inputsEqual(trueNext, falseNext) && nodeClass.valueEqual(trueNext, falseNext)) {
+                            falseNext.replaceAtUsages(trueNext);
+                            graph().removeFixed(falseNext);
+                            FixedNode next = trueNext.next();
+                            trueNext.setNext(null);
+                            trueNext.replaceAtPredecessor(next);
+                            graph().addBeforeFixed(this, trueNext);
+                            for (Node usage : trueNext.usages().snapshot()) {
+                                if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) {
+                                    Node newNode = graph().findDuplicate(usage);
+                                    if (newNode != null) {
+                                        usage.replaceAtUsages(newNode);
+                                        usage.safeDelete();
+                                    }
+                                }
+                                if (usage.isAlive()) {
+                                    tool.addToWorkList(usage);
+                                }
+                            }
+                            continue;
+                        }
+                    }
+                }
+            } while (false);
+        }
 
         if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
@@ -182,7 +218,7 @@
         }
 
         if (falseSuccessor().usages().isEmpty() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) {
-            AbstractBeginNode intermediateBegin = falseSuccessor();
+            BeginNode intermediateBegin = falseSuccessor();
             IfNode nextIf = (IfNode) intermediateBegin.next();
             double probabilityB = (1.0 - this.trueSuccessorProbability) * nextIf.trueSuccessorProbability;
             if (this.trueSuccessorProbability < probabilityB) {
@@ -191,7 +227,7 @@
                 if (prepareForSwap(tool.getConstantReflection(), condition(), nextIf.condition(), this.trueSuccessorProbability, probabilityB)) {
                     // Reording is allowed from (if1 => begin => if2) to (if2 => begin => if1).
                     assert intermediateBegin.next() == nextIf;
-                    AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor();
+                    BeginNode bothFalseBegin = nextIf.falseSuccessor();
                     nextIf.setFalseSuccessor(null);
                     intermediateBegin.setNext(null);
                     this.setFalseSuccessor(null);
@@ -547,8 +583,8 @@
         List<AbstractEndNode> trueEnds = new ArrayList<>(mergePredecessors.size());
         Map<AbstractEndNode, ValueNode> phiValues = new HashMap<>(mergePredecessors.size());
 
-        AbstractBeginNode oldFalseSuccessor = falseSuccessor();
-        AbstractBeginNode oldTrueSuccessor = trueSuccessor();
+        BeginNode oldFalseSuccessor = falseSuccessor();
+        BeginNode oldTrueSuccessor = trueSuccessor();
 
         setFalseSuccessor(null);
         setTrueSuccessor(null);
@@ -637,7 +673,7 @@
      * @param oldMerge the merge being removed
      * @param phiValues the values of the phi at the merge, keyed by the merge ends
      */
-    private void connectEnds(List<AbstractEndNode> ends, Map<AbstractEndNode, ValueNode> phiValues, AbstractBeginNode successor, MergeNode oldMerge, SimplifierTool tool) {
+    private void connectEnds(List<AbstractEndNode> ends, Map<AbstractEndNode, ValueNode> phiValues, BeginNode successor, MergeNode oldMerge, SimplifierTool tool) {
         if (!ends.isEmpty()) {
             if (ends.size() == 1) {
                 AbstractEndNode end = ends.get(0);
@@ -703,8 +739,8 @@
     }
 
     private void removeEmptyIf(SimplifierTool tool) {
-        AbstractBeginNode originalTrueSuccessor = trueSuccessor();
-        AbstractBeginNode originalFalseSuccessor = falseSuccessor();
+        BeginNode originalTrueSuccessor = trueSuccessor();
+        BeginNode originalFalseSuccessor = falseSuccessor();
         assert originalTrueSuccessor.next() instanceof AbstractEndNode && originalFalseSuccessor.next() instanceof AbstractEndNode;
 
         AbstractEndNode trueEnd = (AbstractEndNode) originalTrueSuccessor.next();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public class IndirectCallTargetNode extends LoweredCallTargetNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Nodes of this type are inserted into the graph to denote points of interest to debugging.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -52,4 +53,36 @@
     boolean isPolymorphic();
 
     void setPolymorphic(boolean value);
+
+    /**
+     * Returns the {@linkplain ResolvedJavaMethod method} from which this invoke is executed. This
+     * is the caller method and in the case of inlining may be different from the method of the
+     * graph this node is in.
+     *
+     * @return the method from which this invoke is executed.
+     */
+    default ResolvedJavaMethod getContextMethod() {
+        FrameState state = stateAfter();
+        if (state == null) {
+            state = stateDuring();
+        }
+        return state.method();
+    }
+
+    /**
+     * Returns the {@linkplain ResolvedJavaType type} from which this invoke is executed. This is
+     * the declaring type of the caller method.
+     *
+     * @return the type from which this invoke is executed.
+     */
+    default ResolvedJavaType getContextType() {
+        return getContextMethod().getDeclaringClass();
+    }
+
+    @Override
+    default void computeStateDuring(FrameState stateAfter) {
+        FrameState newStateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), asNode().getKind());
+        newStateDuring.setDuringCall(true);
+        setStateDuring(newStateDuring);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,11 +25,11 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -38,7 +38,7 @@
 @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}", allowedUsageTypes = {InputType.Memory})
 public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single {
 
-    @Input(InputType.Association) private CallTargetNode callTarget;
+    @Input(InputType.Extension) private CallTargetNode callTarget;
     @Input(InputType.State) private FrameState stateDuring;
     @Input(InputType.Guard) private GuardingNode guard;
     private final int bci;
@@ -185,13 +185,6 @@
     }
 
     @Override
-    public void computeStateDuring(FrameState stateAfter) {
-        FrameState newStateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), getKind());
-        newStateDuring.setDuringCall(true);
-        setStateDuring(newStateDuring);
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -36,9 +36,9 @@
 
     private static final double EXCEPTION_PROBA = 1e-5;
 
-    @Successor private AbstractBeginNode next;
+    @Successor private BeginNode next;
     @Successor private DispatchBeginNode exceptionEdge;
-    @Input(InputType.Association) private CallTargetNode callTarget;
+    @Input(InputType.Extension) private CallTargetNode callTarget;
     @Input(InputType.State) private FrameState stateDuring;
     @Input(InputType.State) private FrameState stateAfter;
     @Input(InputType.Guard) private GuardingNode guard;
@@ -66,11 +66,11 @@
         exceptionEdge = x;
     }
 
-    public AbstractBeginNode next() {
+    public BeginNode next() {
         return next;
     }
 
-    public void setNext(AbstractBeginNode x) {
+    public void setNext(BeginNode x) {
         updatePredecessor(next, x);
         next = x;
     }
@@ -163,7 +163,7 @@
     }
 
     public void killExceptionEdge() {
-        AbstractBeginNode edge = exceptionEdge();
+        BeginNode edge = exceptionEdge();
         setExceptionEdge(null);
         GraphUtil.killCFG(edge);
     }
@@ -196,12 +196,12 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         return successor == next ? 1 - exceptionProbability : exceptionProbability;
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         assert successor == next || successor == exceptionEdge;
         this.exceptionProbability = successor == next ? 1 - value : value;
     }
@@ -223,13 +223,6 @@
     }
 
     @Override
-    public void computeStateDuring(FrameState tempStateAfter) {
-        FrameState newStateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), getKind());
-        newStateDuring.setDuringCall(true);
-        setStateDuring(newStateDuring);
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class KillingBeginNode extends AbstractBeginNode implements MemoryCheckpoint.Single {
+public class KillingBeginNode extends BeginNode implements MemoryCheckpoint.Single {
 
     private LocationIdentity locationIdentity;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,9 +24,9 @@
 
 import static com.oracle.graal.graph.InputType.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {Condition})
 public abstract class LogicNode extends FloatingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -178,7 +178,7 @@
         // nothing yet
     }
 
-    public boolean isLoopExit(AbstractBeginNode begin) {
+    public boolean isLoopExit(BeginNode begin) {
         return begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == this;
     }
 
@@ -201,4 +201,27 @@
         updateUsagesInterface(this.overflowGuard, overflowGuard);
         this.overflowGuard = overflowGuard;
     }
+
+    /**
+     * Removes dead {@linkplain PhiNode phi nodes} hanging from this node.
+     *
+     * This method uses the heuristic that any node which not a phi node of this LoopBeginNode is
+     * alive. This allows the removal of dead phi loops.
+     */
+    public void removeDeadPhis() {
+        Set<PhiNode> alive = new HashSet<>();
+        for (PhiNode phi : phis()) {
+            NodePredicate isAlive = u -> !isPhiAtMerge(u) || alive.contains(u);
+            if (phi.usages().filter(isAlive).isNotEmpty()) {
+                alive.add(phi);
+                for (PhiNode keptAlive : phi.values().filter(PhiNode.class).filter(isAlive.negate())) {
+                    alive.add(keptAlive);
+                }
+            }
+        }
+        for (PhiNode phi : phis().filter(((NodePredicate) alive::contains).negate()).snapshot()) {
+            phi.replaceAtUsages(null);
+            phi.safeDelete();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public abstract class LoweredCallTargetNode extends CallTargetNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,12 +25,12 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
-@NodeInfo(allowedUsageTypes = {InputType.Association})
+@NodeInfo(allowedUsageTypes = {InputType.Extension})
 public abstract class MemoryMapNode extends FloatingNode {
 
     public MemoryMapNode() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code PhiNode} represents the merging of dataflow in the memory graph.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class MemoryProxyNode extends ProxyNode implements MemoryProxy, LIRLowerable {
@@ -34,7 +34,7 @@
     @Input(InputType.Memory) private MemoryNode value;
     private final LocationIdentity identity;
 
-    public MemoryProxyNode(MemoryNode value, AbstractBeginNode exit, LocationIdentity identity) {
+    public MemoryProxyNode(MemoryNode value, BeginNode exit, LocationIdentity identity) {
         super(StampFactory.forVoid(), exit);
         this.value = value;
         this.identity = identity;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -124,26 +124,18 @@
     }
 
     public NodeIterable<PhiNode> phis() {
-        return this.usages().filter(PhiNode.class).filter(new NodePredicate() {
-
-            @Override
-            public boolean apply(Node n) {
-                return ((PhiNode) n).merge() == MergeNode.this;
-            }
-        });
+        return this.usages().filter(PhiNode.class).filter(this::isPhiAtMerge);
     }
 
     @Override
     public NodeIterable<Node> anchored() {
-        return super.anchored().filter(isNotA(PhiNode.class).or(new NodePredicate() {
-
-            @Override
-            public boolean apply(Node n) {
-                return ((PhiNode) n).merge() != MergeNode.this;
-            }
-        }));
+        return super.anchored().filter(n -> !isPhiAtMerge(n));
     }
 
+    /**
+     * This simplify method can deal with a null value for tool, so that it can be used outside of
+     * canonicalization.
+     */
     @Override
     public void simplify(SimplifierTool tool) {
         FixedNode next = next();
@@ -163,10 +155,8 @@
                 return;
             }
             for (PhiNode phi : phis()) {
-                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
-                    if (!merge.isPhiAtMerge(usage)) {
-                        return;
-                    }
+                if (phi.usages().filter(isNotA(FrameState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) {
+                    return;
                 }
             }
             Debug.log("Split %s into ends for %s.", this, merge);
@@ -194,7 +184,9 @@
                 this.removeEnd(end);
                 end.replaceAtPredecessor(newEnd);
                 end.safeDelete();
-                tool.addToWorkList(newEnd.predecessor()); // ?
+                if (tool != null) {
+                    tool.addToWorkList(newEnd.predecessor());
+                }
             }
             graph().reduceTrivialMerge(this);
         } else if (next instanceof ReturnNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class PhiNode extends FloatingNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A {@link PiNode} that also provides an array length in addition to a more refined stamp. A usage
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 //JaCoCo Exclude
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
@@ -58,7 +59,7 @@
     }
 
     public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
-        this(object, StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp())));
+        this(object, StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp())));
     }
 
     @Override
@@ -79,7 +80,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
-        if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
+        if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
             tool.replaceWithVirtual(state.getVirtualObject());
         }
     }
@@ -108,6 +109,10 @@
         return piCast(object, toType, true, true);
     }
 
+    public static <T> T piCastExact(Object object, @ConstantNodeParameter Class<T> toType) {
+        return piCast(object, toType, true, false);
+    }
+
     public static <T> T piCast(Object object, @ConstantNodeParameter Class<T> toType) {
         return piCast(object, toType, false, false);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A proxy is inserted at loop exits for any value that is created inside the loop (i.e. was not
@@ -35,9 +35,9 @@
  */
 public abstract class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable {
 
-    @Input(InputType.Association) private AbstractBeginNode proxyPoint;
+    @Input(InputType.Association) private BeginNode proxyPoint;
 
-    public ProxyNode(Stamp stamp, AbstractBeginNode proxyPoint) {
+    public ProxyNode(Stamp stamp, BeginNode proxyPoint) {
         super(stamp);
         assert proxyPoint != null;
         this.proxyPoint = proxyPoint;
@@ -45,7 +45,7 @@
 
     public abstract ValueNode value();
 
-    public AbstractBeginNode proxyPoint() {
+    public BeginNode proxyPoint() {
         return proxyPoint;
     }
 
@@ -57,15 +57,15 @@
         return super.verify();
     }
 
-    public static MemoryProxyNode forMemory(MemoryNode value, AbstractBeginNode exit, LocationIdentity location, StructuredGraph graph) {
+    public static MemoryProxyNode forMemory(MemoryNode value, BeginNode exit, LocationIdentity location, StructuredGraph graph) {
         return graph.unique(new MemoryProxyNode(value, exit, location));
     }
 
-    public static ValueProxyNode forValue(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) {
+    public static ValueProxyNode forValue(ValueNode value, BeginNode exit, StructuredGraph graph) {
         return graph.unique(new ValueProxyNode(value, exit));
     }
 
-    public static GuardProxyNode forGuard(GuardingNode value, AbstractBeginNode exit, StructuredGraph graph) {
+    public static GuardProxyNode forGuard(GuardingNode value, BeginNode exit, StructuredGraph graph) {
         return graph.unique(new GuardProxyNode(value, exit));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
 
     @Input private ValueNode result;
-    @Input(InputType.Association) private MemoryMapNode memoryMap;
+    @Input(InputType.Extension) private MemoryMapNode memoryMap;
 
     public ValueNode result() {
         return result;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Marks a position in the graph where a safepoint should be emitted.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,6 +29,8 @@
  */
 public interface StateSplit extends NodeWithState {
 
+    FixedNode asNode();
+
     /**
      * Gets the {@link FrameState} corresponding to the state of the JVM after execution of this
      * node.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Apr 23 15:48:38 2014 +0200
@@ -79,16 +79,14 @@
     private boolean isAfterFloatingReadPhase = false;
 
     /**
-     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
-     * start} node.
+     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
      */
     public StructuredGraph() {
         this(null, null);
     }
 
     /**
-     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
-     * start} node.
+     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
      */
     public StructuredGraph(String name, ResolvedJavaMethod method) {
         this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI);
@@ -255,8 +253,8 @@
      */
     public void removeFixed(FixedWithNextNode node) {
         assert node != null;
-        if (node instanceof AbstractBeginNode) {
-            ((AbstractBeginNode) node).prepareDelete();
+        if (node instanceof BeginNode) {
+            ((BeginNode) node).prepareDelete();
         }
         assert node.usages().isEmpty() : node + " " + node.usages();
         FixedNode next = node.next();
@@ -295,7 +293,7 @@
         node.safeDelete();
     }
 
-    public void removeSplit(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
+    public void removeSplit(ControlSplitNode node, BeginNode survivingSuccessor) {
         assert node != null;
         assert node.usages().isEmpty();
         assert survivingSuccessor != null;
@@ -304,7 +302,7 @@
         node.safeDelete();
     }
 
-    public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
+    public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) {
         assert node != null;
         assert node.usages().isEmpty();
         assert survivingSuccessor != null;
@@ -321,7 +319,7 @@
         }
     }
 
-    public void replaceSplit(ControlSplitNode node, Node replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplit(ControlSplitNode node, Node replacement, BeginNode survivingSuccessor) {
         if (replacement instanceof FixedWithNextNode) {
             replaceSplitWithFixed(node, (FixedWithNextNode) replacement, survivingSuccessor);
         } else {
@@ -331,7 +329,7 @@
         }
     }
 
-    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, BeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor != null;
         node.clearSuccessors();
@@ -339,7 +337,7 @@
         node.replaceAndDelete(replacement);
     }
 
-    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, BeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor != null;
         node.clearSuccessors();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -75,7 +75,7 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (ObjectStamp.isExactType(object)) {
+        if (StampTool.isExactType(object)) {
             // The profile is useless - we know the type!
             return object;
         } else if (object instanceof TypeProfileProxyNode) {
@@ -96,8 +96,8 @@
                 Debug.log("Improved profile via other profile.");
                 return TypeProfileProxyNode.create(object, newProfile);
             }
-        } else if (ObjectStamp.typeOrNull(object) != null) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(object);
+        } else if (StampTool.typeOrNull(object) != null) {
+            ResolvedJavaType type = StampTool.typeOrNull(object);
             ResolvedJavaType uniqueConcrete = type.findUniqueConcreteSubtype();
             if (uniqueConcrete != null) {
                 // Profile is useless => remove.
@@ -109,7 +109,7 @@
                 return this;
             }
             lastCheckedType = type;
-            JavaTypeProfile newProfile = this.profile.restrict(type, ObjectStamp.isObjectNonNull(object));
+            JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(object));
             if (newProfile != this.profile) {
                 Debug.log("Improved profile via static type information.");
                 if (newProfile.getTypes().length == 0) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Unwinds the current frame to an exception handler in the caller frame.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This class represents a value within the graph, including local variables, phis, and all other
@@ -92,13 +92,7 @@
         return this instanceof ConstantNode;
     }
 
-    private static final NodePredicate IS_CONSTANT = new NodePredicate() {
-
-        @Override
-        public boolean apply(Node n) {
-            return n instanceof ValueNode && ((ValueNode) n).isConstant();
-        }
-    };
+    private static final NodePredicate IS_CONSTANT = node -> node instanceof ConstantNode;
 
     public static NodePredicate isConstantPredicate() {
         return IS_CONSTANT;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,7 +30,7 @@
 
     @Input private ValueNode value;
 
-    public ValueProxyNode(ValueNode value, AbstractBeginNode proxyPoint) {
+    public ValueProxyNode(ValueNode value, BeginNode proxyPoint) {
         super(value.stamp(), proxyPoint);
         this.value = value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -67,6 +69,13 @@
             if ((rawY & mask) == 0) {
                 return ConstantNode.forIntegerStamp(stamp(), 0, graph());
             }
+            if (x() instanceof SignExtendNode) {
+                SignExtendNode ext = (SignExtendNode) x();
+                if (rawY == ((1L << ext.getInputBits()) - 1)) {
+                    ValueNode result = graph().unique(new ZeroExtendNode(ext.getInput(), ext.getResultBits()));
+                    return result;
+                }
+            }
             if (x().stamp() instanceof IntegerStamp) {
                 IntegerStamp xStamp = (IntegerStamp) x().stamp();
                 if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) {
@@ -81,8 +90,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAnd(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitAnd(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code BinaryNode} class is the base of arithmetic and logic operations with two inputs.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
 
 /* TODO (thomaswue/gdub) For high-level optimization purpose the compare node should be a boolean *value* (it is currently only a helper node)
  * But in the back-end the comparison should not always be materialized (for example in x86 the comparison result will not be in a register but in a flag)
@@ -35,49 +35,32 @@
  * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed
  * into variants that do not materialize the value (CompareIf, CompareGuard...)
  */
-public abstract class CompareNode extends LogicNode implements Canonicalizable, LIRLowerable, MemoryArithmeticLIRLowerable {
-
-    @Input private ValueNode x;
-    @Input private ValueNode y;
-
-    public ValueNode x() {
-        return x;
-    }
-
-    public ValueNode y() {
-        return y;
-    }
+public abstract class CompareNode extends BinaryLogicNode implements Canonicalizable {
 
     /**
      * Constructs a new Compare instruction.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
     public CompareNode(ValueNode x, ValueNode y) {
-        assert x != null && y != null && x.getKind() == y.getKind();
-        this.x = x;
-        this.y = y;
+        super(x, y);
     }
 
     /**
      * Gets the condition (comparison operation) for this instruction.
-     * 
+     *
      * @return the condition
      */
     public abstract Condition condition();
 
     /**
      * Checks whether unordered inputs mean true or false (only applies to float operations).
-     * 
+     *
      * @return {@code true} if unordered inputs produce true
      */
     public abstract boolean unorderedIsTrue();
 
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-    }
-
     private LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) {
         Constant trueConstant = conditionalNode.trueValue().asConstant();
         Constant falseConstant = conditionalNode.falseValue().asConstant();
@@ -102,16 +85,6 @@
         return this;
     }
 
-    protected void setX(ValueNode x) {
-        updateUsages(this.x, x);
-        this.x = x;
-    }
-
-    protected void setY(ValueNode y) {
-        updateUsages(this.y, y);
-        this.y = y;
-    }
-
     protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         throw new GraalInternalError("NormalizeCompareNode connected to %s (%s %s %s)", this, constant, normalizeNode, mirrored);
     }
@@ -193,14 +166,4 @@
 
         return graph.unique(comparison);
     }
-
-    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        return false;
-    }
-
-    @Override
-    public boolean verify() {
-        assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
-        return super.verify();
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,634 +0,0 @@
-/*
- * 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.nodes.calc;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-
-/**
- * Condition codes used in conditionals.
- */
-public enum Condition {
-    /**
-     * Equal.
-     */
-    EQ("=="),
-
-    /**
-     * Not equal.
-     */
-    NE("!="),
-
-    /**
-     * Signed less than.
-     */
-    LT("<"),
-
-    /**
-     * Signed less than or equal.
-     */
-    LE("<="),
-
-    /**
-     * Signed greater than.
-     */
-    GT(">"),
-
-    /**
-     * Signed greater than or equal.
-     */
-    GE(">="),
-
-    /**
-     * Unsigned greater than or equal ("above than or equal").
-     */
-    AE("|>=|"),
-
-    /**
-     * Unsigned less than or equal ("below than or equal").
-     */
-    BE("|<=|"),
-
-    /**
-     * Unsigned greater than ("above than").
-     */
-    AT("|>|"),
-
-    /**
-     * Unsigned less than ("below than").
-     */
-    BT("|<|");
-
-    public final String operator;
-
-    private Condition(String operator) {
-        this.operator = operator;
-    }
-
-    public boolean check(int left, int right) {
-        switch (this) {
-            case EQ:
-                return left == right;
-            case NE:
-                return left != right;
-            case LT:
-                return left < right;
-            case LE:
-                return left <= right;
-            case GT:
-                return left > right;
-            case GE:
-                return left >= right;
-            case AE:
-                return UnsignedMath.aboveOrEqual(left, right);
-            case BE:
-                return UnsignedMath.belowOrEqual(left, right);
-            case AT:
-                return UnsignedMath.aboveThan(left, right);
-            case BT:
-                return UnsignedMath.belowThan(left, right);
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Given a condition and its negation, this method returns true for one of the two and false for
-     * the other one. This can be used to keep comparisons in a canonical form.
-     * 
-     * @return true if this condition is considered to be the canonical form, false otherwise.
-     */
-    public boolean isCanonical() {
-        switch (this) {
-            case EQ:
-                return true;
-            case NE:
-                return false;
-            case LT:
-                return true;
-            case LE:
-                return false;
-            case GT:
-                return false;
-            case GE:
-                return false;
-            case BT:
-                return true;
-            case BE:
-                return false;
-            case AT:
-                return false;
-            case AE:
-                return false;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Returns true if the condition needs to be mirrored to get to a canonical condition. The
-     * result of the mirroring operation might still need to be negated to achieve a canonical form.
-     */
-    public boolean canonicalMirror() {
-        switch (this) {
-            case EQ:
-                return false;
-            case NE:
-                return false;
-            case LT:
-                return false;
-            case LE:
-                return true;
-            case GT:
-                return true;
-            case GE:
-                return false;
-            case BT:
-                return false;
-            case BE:
-                return true;
-            case AT:
-                return true;
-            case AE:
-                return false;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Returns true if the condition needs to be negated to get to a canonical condition. The result
-     * of the negation might still need to be mirrored to achieve a canonical form.
-     */
-    public boolean canonicalNegate() {
-        switch (this) {
-            case EQ:
-                return false;
-            case NE:
-                return true;
-            case LT:
-                return false;
-            case LE:
-                return true;
-            case GT:
-                return false;
-            case GE:
-                return true;
-            case BT:
-                return false;
-            case BE:
-                return true;
-            case AT:
-                return false;
-            case AE:
-                return true;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Negate this conditional.
-     * 
-     * @return the condition that represents the negation
-     */
-    public final Condition negate() {
-        switch (this) {
-            case EQ:
-                return NE;
-            case NE:
-                return EQ;
-            case LT:
-                return GE;
-            case LE:
-                return GT;
-            case GT:
-                return LE;
-            case GE:
-                return LT;
-            case BT:
-                return AE;
-            case BE:
-                return AT;
-            case AT:
-                return BE;
-            case AE:
-                return BT;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    public boolean implies(Condition other) {
-        if (other == this) {
-            return true;
-        }
-        switch (this) {
-            case EQ:
-                return other == LE || other == GE || other == BE || other == AE;
-            case NE:
-                return false;
-            case LT:
-                return other == LE || other == NE;
-            case LE:
-                return false;
-            case GT:
-                return other == GE || other == NE;
-            case GE:
-                return false;
-            case BT:
-                return other == BE || other == NE;
-            case BE:
-                return false;
-            case AT:
-                return other == AE || other == NE;
-            case AE:
-                return false;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Mirror this conditional (i.e. commute "a op b" to "b op' a")
-     * 
-     * @return the condition representing the equivalent commuted operation
-     */
-    public final Condition mirror() {
-        switch (this) {
-            case EQ:
-                return EQ;
-            case NE:
-                return NE;
-            case LT:
-                return GT;
-            case LE:
-                return GE;
-            case GT:
-                return LT;
-            case GE:
-                return LE;
-            case BT:
-                return AT;
-            case BE:
-                return AE;
-            case AT:
-                return BT;
-            case AE:
-                return BE;
-        }
-        throw new IllegalArgumentException();
-    }
-
-    /**
-     * Returns true if this condition represents an unsigned comparison. EQ and NE are not
-     * considered to be unsigned.
-     */
-    public final boolean isUnsigned() {
-        return this == Condition.BT || this == Condition.BE || this == Condition.AT || this == Condition.AE;
-    }
-
-    /**
-     * Checks if this conditional operation is commutative.
-     * 
-     * @return {@code true} if this operation is commutative
-     */
-    public final boolean isCommutative() {
-        return this == EQ || this == NE;
-    }
-
-    /**
-     * Attempts to fold a comparison between two constants and return the result.
-     * 
-     * @param lt the constant on the left side of the comparison
-     * @param rt the constant on the right side of the comparison
-     * @param constantReflection needed to compare constants
-     * @return {@link Boolean#TRUE} if the comparison is known to be true, {@link Boolean#FALSE} if
-     *         the comparison is known to be false
-     */
-    public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection) {
-        assert !lt.getKind().isNumericFloat() && !rt.getKind().isNumericFloat();
-        return foldCondition(lt, rt, constantReflection, false);
-    }
-
-    /**
-     * Attempts to fold a comparison between two constants and return the result.
-     * 
-     * @param lt the constant on the left side of the comparison
-     * @param rt the constant on the right side of the comparison
-     * @param constantReflection needed to compare constants
-     * @param unorderedIsTrue true if an undecided float comparison should result in "true"
-     * @return true if the comparison is known to be true, false if the comparison is known to be
-     *         false
-     */
-    public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
-        switch (lt.getKind()) {
-            case Boolean:
-            case Byte:
-            case Char:
-            case Short:
-            case Int: {
-                int x = lt.asInt();
-                int y = rt.asInt();
-                switch (this) {
-                    case EQ:
-                        return x == y;
-                    case NE:
-                        return x != y;
-                    case LT:
-                        return x < y;
-                    case LE:
-                        return x <= y;
-                    case GT:
-                        return x > y;
-                    case GE:
-                        return x >= y;
-                    case AE:
-                        return UnsignedMath.aboveOrEqual(x, y);
-                    case BE:
-                        return UnsignedMath.belowOrEqual(x, y);
-                    case AT:
-                        return UnsignedMath.aboveThan(x, y);
-                    case BT:
-                        return UnsignedMath.belowThan(x, y);
-                    default:
-                        throw new GraalInternalError("expected condition: %s", this);
-                }
-            }
-            case Long: {
-                long x = lt.asLong();
-                long y = rt.asLong();
-                switch (this) {
-                    case EQ:
-                        return x == y;
-                    case NE:
-                        return x != y;
-                    case LT:
-                        return x < y;
-                    case LE:
-                        return x <= y;
-                    case GT:
-                        return x > y;
-                    case GE:
-                        return x >= y;
-                    case AE:
-                        return UnsignedMath.aboveOrEqual(x, y);
-                    case BE:
-                        return UnsignedMath.belowOrEqual(x, y);
-                    case AT:
-                        return UnsignedMath.aboveThan(x, y);
-                    case BT:
-                        return UnsignedMath.belowThan(x, y);
-                    default:
-                        throw new GraalInternalError("expected condition: %s", this);
-                }
-            }
-            case Object: {
-                Boolean equal = constantReflection.constantEquals(lt, rt);
-                if (equal != null) {
-                    switch (this) {
-                        case EQ:
-                            return equal.booleanValue();
-                        case NE:
-                            return !equal.booleanValue();
-                        default:
-                            throw new GraalInternalError("expected condition: %s", this);
-                    }
-                }
-            }
-            case Float: {
-                float x = lt.asFloat();
-                float y = rt.asFloat();
-                if (Float.isNaN(x) || Float.isNaN(y)) {
-                    return unorderedIsTrue;
-                }
-                switch (this) {
-                    case EQ:
-                        return x == y;
-                    case NE:
-                        return x != y;
-                    case LT:
-                        return x < y;
-                    case LE:
-                        return x <= y;
-                    case GT:
-                        return x > y;
-                    case GE:
-                        return x >= y;
-                    default:
-                        throw new GraalInternalError("expected condition: %s", this);
-                }
-            }
-            case Double: {
-                double x = lt.asDouble();
-                double y = rt.asDouble();
-                if (Double.isNaN(x) || Double.isNaN(y)) {
-                    return unorderedIsTrue;
-                }
-                switch (this) {
-                    case EQ:
-                        return x == y;
-                    case NE:
-                        return x != y;
-                    case LT:
-                        return x < y;
-                    case LE:
-                        return x <= y;
-                    case GT:
-                        return x > y;
-                    case GE:
-                        return x >= y;
-                    default:
-                        throw new GraalInternalError("expected condition: %s", this);
-                }
-            }
-            default:
-                throw new GraalInternalError("expected value kind %s while folding condition: %s", lt.getKind(), this);
-        }
-    }
-
-    public Condition join(Condition other) {
-        if (other == this) {
-            return this;
-        }
-        switch (this) {
-            case EQ:
-                if (other == LE || other == GE || other == BE || other == AE) {
-                    return EQ;
-                } else {
-                    return null;
-                }
-            case NE:
-                if (other == LT || other == GT || other == BT || other == AT) {
-                    return other;
-                } else if (other == LE) {
-                    return LT;
-                } else if (other == GE) {
-                    return GT;
-                } else if (other == BE) {
-                    return BT;
-                } else if (other == AE) {
-                    return AT;
-                } else {
-                    return null;
-                }
-            case LE:
-                if (other == GE || other == EQ) {
-                    return EQ;
-                } else if (other == NE || other == LT) {
-                    return LT;
-                } else {
-                    return null;
-                }
-            case LT:
-                if (other == NE || other == LE) {
-                    return LT;
-                } else {
-                    return null;
-                }
-            case GE:
-                if (other == LE || other == EQ) {
-                    return EQ;
-                } else if (other == NE || other == GT) {
-                    return GT;
-                } else {
-                    return null;
-                }
-            case GT:
-                if (other == NE || other == GE) {
-                    return GT;
-                } else {
-                    return null;
-                }
-            case BE:
-                if (other == AE || other == EQ) {
-                    return EQ;
-                } else if (other == NE || other == BT) {
-                    return BT;
-                } else {
-                    return null;
-                }
-            case BT:
-                if (other == NE || other == BE) {
-                    return BT;
-                } else {
-                    return null;
-                }
-            case AE:
-                if (other == BE || other == EQ) {
-                    return EQ;
-                } else if (other == NE || other == AT) {
-                    return AT;
-                } else {
-                    return null;
-                }
-            case AT:
-                if (other == NE || other == AE) {
-                    return AT;
-                } else {
-                    return null;
-                }
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    public Condition meet(Condition other) {
-        if (other == this) {
-            return this;
-        }
-        switch (this) {
-            case EQ:
-                if (other == LE || other == GE || other == BE || other == AE) {
-                    return other;
-                } else if (other == LT) {
-                    return LE;
-                } else if (other == GT) {
-                    return GE;
-                } else if (other == BT) {
-                    return BE;
-                } else if (other == AT) {
-                    return AE;
-                } else {
-                    return null;
-                }
-            case NE:
-                if (other == LT || other == GT || other == BT || other == AT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-            case LE:
-                if (other == EQ || other == LT) {
-                    return LE;
-                } else {
-                    return null;
-                }
-            case LT:
-                if (other == EQ || other == LE) {
-                    return LE;
-                } else if (other == NE || other == GT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-            case GE:
-                if (other == EQ || other == GT) {
-                    return GE;
-                } else {
-                    return null;
-                }
-            case GT:
-                if (other == EQ || other == GE) {
-                    return GE;
-                } else if (other == NE || other == LT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-            case BE:
-                if (other == EQ || other == BT) {
-                    return BE;
-                } else {
-                    return null;
-                }
-            case BT:
-                if (other == EQ || other == BE) {
-                    return BE;
-                } else if (other == NE || other == AT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-            case AE:
-                if (other == EQ || other == AT) {
-                    return AE;
-                } else {
-                    return null;
-                }
-            case AT:
-                if (other == EQ || other == AE) {
-                    return AE;
-                } else if (other == NE || other == BT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,12 +25,13 @@
 import static com.oracle.graal.nodes.calc.CompareNode.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note
@@ -128,7 +129,7 @@
     public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, long x, long y);
 
     @NodeIntrinsic
-    public static boolean materializeIsInstance(Class mirror, Object object) {
+    public static boolean materializeIsInstance(Class<?> mirror, Object object) {
         return mirror.isInstance(object);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,8 +24,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Represents a conversion between primitive types.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "+")
 public final class FloatAddNode extends FloatArithmeticNode implements Canonicalizable {
@@ -65,20 +66,20 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
+        builder.setResult(this, gen.emitAdd(op1, op2));
     }
 
-    public static boolean livesLonger(ValueNode after, ValueNode value, NodeLIRBuilderTool gen) {
+    public static boolean livesLonger(ValueNode after, ValueNode value, NodeMappableLIRBuilder builder) {
         for (Node usage : value.usages()) {
-            if (usage != after && usage instanceof ValueNode && gen.hasOperand(((ValueNode) usage))) {
+            if (usage != after && usage instanceof ValueNode && builder.hasOperand(((ValueNode) usage))) {
                 return true;
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,15 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A {@code FloatConvert} converts between integers and floating point numbers according to Java
@@ -36,46 +39,6 @@
  */
 public class FloatConvertNode extends ConvertNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
 
-    public enum FloatConvert {
-        F2I,
-        D2I,
-        F2L,
-        D2L,
-        I2F,
-        L2F,
-        D2F,
-        I2D,
-        L2D,
-        F2D;
-
-        public FloatConvert reverse() {
-            switch (this) {
-                case D2F:
-                    return F2D;
-                case D2I:
-                    return I2D;
-                case D2L:
-                    return L2D;
-                case F2D:
-                    return D2F;
-                case F2I:
-                    return I2F;
-                case F2L:
-                    return L2F;
-                case I2D:
-                    return D2I;
-                case I2F:
-                    return F2I;
-                case L2D:
-                    return D2L;
-                case L2F:
-                    return F2L;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
-        }
-    }
-
     private final FloatConvert op;
 
     public FloatConvertNode(FloatConvert op, ValueNode input) {
@@ -201,17 +164,11 @@
         tool.getLowerer().lower(this, tool);
     }
 
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(getInput())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getInput())));
     }
 
     public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        Kind kind = access.accessLocation().getValueKind();
-        if (kind != kind.getStackKind()) {
-            // Doesn't work for subword operations
-            return false;
-        }
-
         Value result = gen.emitFloatConvertMemory(getOp(), access);
         if (result != null) {
             gen.setResult(this, result);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "/")
 public final class FloatDivNode extends FloatArithmeticNode implements Canonicalizable {
@@ -57,8 +58,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), null));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitDiv(builder.operand(x()), builder.operand(y()), null));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,10 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "==")
 public final class FloatEqualsNode extends CompareNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "<")
 public final class FloatLessThanNode extends CompareNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "*")
 public final class FloatMulNode extends FloatArithmeticNode implements Canonicalizable {
@@ -60,15 +61,15 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
+        builder.setResult(this, gen.emitMul(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "%")
 public final class FloatRemNode extends FloatArithmeticNode implements Canonicalizable {
@@ -57,8 +58,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), null));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitRem(builder.operand(x()), builder.operand(y()), null));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "-")
 public final class FloatSubNode extends FloatArithmeticNode implements Canonicalizable {
@@ -76,8 +77,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingNode extends ValueNode implements Node.ValueNumberable {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -89,16 +91,16 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
         assert op1 != null : x() + ", this=" + this;
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
+        builder.setResult(this, gen.emitAdd(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,11 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "|<|")
 public final class IntegerBelowThanNode extends CompareNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * An {@code IntegerConvert} converts an integer to an integer of different width.
@@ -67,7 +67,7 @@
                 return getInput();
             } else if (getInput().isConstant()) {
                 Constant ret = evalConst(getInput().asConstant());
-                return ConstantNode.forIntegerBits(resultBits, false, ret.asLong(), graph());
+                return ConstantNode.forIntegerBits(resultBits, ret.asLong(), graph());
             }
         }
 
@@ -86,19 +86,11 @@
             result = graph.unique(new NarrowNode(input, toStamp.getBits()));
         } else {
             // toStamp.getBits() > fromStamp.getBits()
-            if (fromStamp.isUnsigned()) {
-                result = graph.unique(new ZeroExtendNode(input, toStamp.getBits()));
-            } else {
-                result = graph.unique(new SignExtendNode(input, toStamp.getBits()));
-            }
+            result = graph.unique(new SignExtendNode(input, toStamp.getBits()));
         }
 
         IntegerStamp resultStamp = (IntegerStamp) result.stamp();
         assert toStamp.getBits() == resultStamp.getBits();
-        if (toStamp.isUnsigned() == resultStamp.isUnsigned()) {
-            return result;
-        } else {
-            return graph.unique(new ReinterpretNode(toStamp, result));
-        }
+        return result;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -107,7 +108,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), gen.state(this)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,11 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,11 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "<")
 public final class IntegerLessThanNode extends CompareNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,12 +24,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "*")
 public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode {
@@ -75,15 +76,15 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
+        builder.setResult(this, gen.emitMul(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "%")
 public class IntegerRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -62,7 +62,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), gen.state(this)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -117,8 +119,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,45 +22,26 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node will perform a "test" operation on its arguments. Its result is equivalent to the
  * expression "(x &amp; y) == 0", meaning that it will return true if (and only if) no bit is set in
  * both x and y.
  */
-public class IntegerTestNode extends LogicNode implements Canonicalizable, LIRLowerable, MemoryArithmeticLIRLowerable {
-
-    @Input private ValueNode x;
-    @Input private ValueNode y;
-
-    public ValueNode x() {
-        return x;
-    }
-
-    public ValueNode y() {
-        return y;
-    }
+public class IntegerTestNode extends BinaryLogicNode implements Canonicalizable {
 
     /**
      * Constructs a new Test instruction.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
     public IntegerTestNode(ValueNode x, ValueNode y) {
-        assert x != null && y != null && x.stamp().isCompatible(y.stamp());
-        this.x = x;
-        this.y = y;
-    }
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
+        super(x, y);
     }
 
     @Override
@@ -73,13 +54,10 @@
             IntegerStamp yStamp = (IntegerStamp) y().stamp();
             if ((xStamp.upMask() & yStamp.upMask()) == 0) {
                 return LogicConstantNode.tautology(graph());
+            } else if ((xStamp.downMask() & yStamp.downMask()) != 0) {
+                return LogicConstantNode.contradiction(graph());
             }
         }
         return this;
     }
-
-    @Override
-    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        return false;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -68,7 +69,7 @@
             assert constant.getKind() == Kind.Object;
             return LogicConstantNode.forBoolean(constant.isNull(), graph());
         }
-        if (ObjectStamp.isObjectNonNull(object.stamp())) {
+        if (StampTool.isObjectNonNull(object.stamp())) {
             return LogicConstantNode.contradiction(graph());
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -92,7 +94,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitShl(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitShl(builder.operand(x()), builder.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -50,13 +52,7 @@
 
     @Override
     public Constant reverse(Constant input) {
-        IntegerStamp stamp = (IntegerStamp) stamp();
-        long result;
-        if (stamp.isUnsigned()) {
-            result = ZeroExtendNode.zeroExtend(input.asLong(), getResultBits());
-        } else {
-            result = SignExtendNode.signExtend(input.asLong(), getResultBits());
-        }
+        long result = SignExtendNode.signExtend(input.asLong(), getResultBits());
         return Constant.forPrimitiveInt(getInputBits(), result);
     }
 
@@ -110,8 +106,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNarrow(gen.operand(getInput()), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNarrow(builder.operand(getInput()), getResultBits()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -88,7 +90,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNegate(gen.operand(x())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNegate(builder.operand(x())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Returns -1, 0, or 1 if either x &lt; y, x == y, or x &gt; y. If the comparison is undecided (one
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -73,7 +75,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNot(gen.operand(x())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNot(builder.operand(x())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -60,9 +61,9 @@
             return LogicConstantNode.tautology(graph());
         }
 
-        if (ObjectStamp.isObjectAlwaysNull(x())) {
+        if (StampTool.isObjectAlwaysNull(x())) {
             return graph().unique(new IsNullNode(y()));
-        } else if (ObjectStamp.isObjectAlwaysNull(y())) {
+        } else if (StampTool.isObjectAlwaysNull(y())) {
             return graph().unique(new IsNullNode(x()));
         }
         if (x().stamp().alwaysDistinct(y().stamp())) {
@@ -75,9 +76,9 @@
     private void virtualizeNonVirtualComparison(State state, ValueNode other, VirtualizerTool tool) {
         if (!state.getVirtualObject().hasIdentity() && state.getVirtualObject().entryKind(0) == Kind.Boolean) {
             if (other.isConstant()) {
-                Object otherValue = other.asConstant().asObject();
-                if (otherValue == Boolean.TRUE || otherValue == Boolean.FALSE) {
-                    int expectedValue = (otherValue == Boolean.TRUE) ? 1 : 0;
+                Constant otherUnboxed = tool.getConstantReflectionProvider().unboxPrimitive(other.asConstant());
+                if (otherUnboxed != null && otherUnboxed.getKind() == Kind.Boolean) {
+                    int expectedValue = otherUnboxed.asBoolean() ? 1 : 0;
                     IntegerEqualsNode equals = new IntegerEqualsNode(state.getEntry(0), ConstantNode.forInt(expectedValue, graph()));
                     tool.addNode(equals);
                     tool.replaceWithValue(equals);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -73,8 +75,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitOr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitOr(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,14 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ReinterpretNode} class represents a reinterpreting conversion that changes the stamp
@@ -102,9 +104,9 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitReinterpret(kind, gen.operand(value())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        PlatformKind kind = gen.getPlatformKind(stamp());
+        builder.setResult(this, gen.emitReinterpret(kind, builder.operand(value())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = ">>")
 public final class RightShiftNode extends ShiftNode implements Canonicalizable {
@@ -98,7 +99,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitShr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitShr(builder.operand(x()), builder.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ShiftOp} class represents shift operations.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -105,13 +107,13 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSignExtend(builder.operand(getInput()), getInputBits(), getResultBits()));
     }
 
     @Override
     public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        Value result = gen.emitSignExtendMemory(access, access.accessLocation().getValueKind().getBitCount(), getResultBits());
+        Value result = gen.emitSignExtendMemory(access, getInputBits(), getResultBits());
         if (result != null) {
             gen.setResult(this, result);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "|/|")
 public class UnsignedDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -72,7 +72,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), gen.state(this)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "|%|")
 public class UnsignedRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -71,7 +71,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), gen.state(this)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -92,7 +94,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitUShr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitUShr(builder.operand(x()), builder.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -72,8 +74,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitXor(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitXor(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -75,6 +77,19 @@
             ZeroExtendNode other = (ZeroExtendNode) getInput();
             return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits()));
         }
+        if (getInput() instanceof NarrowNode) {
+            NarrowNode narrow = (NarrowNode) getInput();
+            Stamp inputStamp = narrow.getInput().stamp();
+            if (inputStamp instanceof IntegerStamp && inputStamp.isCompatible(stamp())) {
+                IntegerStamp istamp = (IntegerStamp) inputStamp;
+                long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(narrow.stamp()));
+                if (((istamp.upMask() | istamp.downMask()) & ~mask) == 0) {
+                    // The original value is in the range of the masked zero extended result so
+                    // simply return the original input.
+                    return narrow.getInput();
+                }
+            }
+        }
 
         return this;
     }
@@ -85,8 +100,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitZeroExtend(builder.operand(getInput()), getInputBits(), getResultBits()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * 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.cfg;
-
-import java.util.*;
-
-public interface AbstractBlock<T extends AbstractBlock<?>> {
-
-    int getId();
-
-    Loop getLoop();
-
-    int getLoopDepth();
-
-    boolean isLoopHeader();
-
-    boolean isLoopEnd();
-
-    boolean isExceptionEntry();
-
-    List<T> getPredecessors();
-
-    int getPredecessorCount();
-
-    List<T> getSuccessors();
-
-    int getSuccessorCount();
-
-    int getLinearScanNumber();
-
-    void setLinearScanNumber(int linearScanNumber);
-
-    boolean isAligned();
-
-    void setAlign(boolean align);
-
-    T getDominator();
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlockBase.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * 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.nodes.cfg;
-
-import java.util.*;
-
-public abstract class AbstractBlockBase<T extends AbstractBlock<T>> implements AbstractBlock<T> {
-
-    protected int id;
-
-    protected List<T> predecessors;
-    protected List<T> successors;
-
-    protected T dominator;
-
-    private boolean align;
-    private int linearScanNumber;
-
-    protected AbstractBlockBase() {
-        this.id = ControlFlowGraph.BLOCK_ID_INITIAL;
-        this.linearScanNumber = -1;
-    }
-
-    public int getId() {
-        return id;
-    }
-
-    public void setId(int id) {
-        this.id = id;
-    }
-
-    public List<T> getPredecessors() {
-        return predecessors;
-    }
-
-    public List<T> getSuccessors() {
-        return successors;
-    }
-
-    public T getDominator() {
-        return dominator;
-    }
-
-    @Override
-    public String toString() {
-        return "B" + id;
-    }
-
-    public int getPredecessorCount() {
-        return getPredecessors().size();
-    }
-
-    public int getSuccessorCount() {
-        return getSuccessors().size();
-    }
-
-    public int getLinearScanNumber() {
-        return linearScanNumber;
-    }
-
-    public void setLinearScanNumber(int linearScanNumber) {
-        this.linearScanNumber = linearScanNumber;
-    }
-
-    public boolean isAligned() {
-        return align;
-    }
-
-    public void setAlign(boolean align) {
-        this.align = align;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * 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.cfg;
-
-public interface AbstractControlFlowGraph<T extends AbstractBlock<T>> {
-
-    T[] getBlocks();
-
-    Loop[] getLoops();
-
-    T getStartBlock();
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,24 +24,25 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 
 public final class Block extends AbstractBlockBase<Block> {
 
-    protected final AbstractBeginNode beginNode;
+    protected final BeginNode beginNode;
 
     protected FixedNode endNode;
-    protected Loop loop;
+    protected Loop<Block> loop;
 
     protected List<Block> dominated;
     protected Block postdominator;
 
-    protected Block(AbstractBeginNode node) {
+    protected Block(BeginNode node) {
         this.beginNode = node;
     }
 
-    public AbstractBeginNode getBeginNode() {
+    public BeginNode getBeginNode() {
         return beginNode;
     }
 
@@ -49,7 +50,7 @@
         return endNode;
     }
 
-    public Loop getLoop() {
+    public Loop<Block> getLoop() {
         return loop;
     }
 
@@ -70,11 +71,11 @@
     }
 
     public Block getFirstPredecessor() {
-        return predecessors.get(0);
+        return getPredecessors().get(0);
     }
 
     public Block getFirstSuccessor() {
-        return successors.get(0);
+        return getSuccessors().get(0);
     }
 
     public Block getEarliestPostDominated() {
@@ -122,7 +123,7 @@
             } else {
                 cur = ((FixedWithNextNode) cur).next();
             }
-            assert !(cur instanceof AbstractBeginNode);
+            assert !(cur instanceof BeginNode);
             return result;
         }
 
@@ -167,10 +168,10 @@
         if (block == this) {
             return true;
         }
-        if (dominator == null) {
+        if (getDominator() == null) {
             return false;
         }
-        return dominator.isDominatedBy(block);
+        return getDominator().isDominatedBy(block);
     }
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-public class BlockMap<T> {
-
-    private final T[] data;
-
-    @SuppressWarnings("unchecked")
-    public BlockMap(AbstractControlFlowGraph<?> cfg) {
-        data = (T[]) new Object[cfg.getBlocks().length];
-    }
-
-    public T get(AbstractBlock<?> block) {
-        return data[block.getId()];
-    }
-
-    public void put(AbstractBlock<?> block, T value) {
-        data[block.getId()] = value;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
+
 public class CFGVerifier {
 
     public static boolean verify(ControlFlowGraph cfg) {
@@ -84,13 +86,13 @@
         }
 
         if (cfg.getLoops() != null) {
-            for (Loop loop : cfg.getLoops()) {
+            for (Loop<Block> loop : cfg.getLoops()) {
                 assert loop.header.isLoopHeader();
 
                 for (Block block : loop.blocks) {
                     assert block.getId() >= loop.header.getId();
 
-                    Loop blockLoop = block.getLoop();
+                    Loop<?> blockLoop = block.getLoop();
                     while (blockLoop != loop) {
                         assert blockLoop != null;
                         blockLoop = blockLoop.parent;
@@ -109,7 +111,7 @@
                 for (Block block : loop.exits) {
                     assert block.getId() >= loop.header.getId();
 
-                    Loop blockLoop = block.getLoop();
+                    Loop<?> blockLoop = block.getLoop();
                     while (blockLoop != null) {
                         blockLoop = blockLoop.parent;
                         assert blockLoop != loop;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -34,7 +36,7 @@
 
     private final NodeMap<Block> nodeToBlock;
     private Block[] reversePostOrder;
-    private Loop[] loops;
+    private List<Loop<Block>> loops;
 
     public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
         ControlFlowGraph cfg = new ControlFlowGraph(graph);
@@ -106,7 +108,7 @@
         return nodeToBlock.get(node);
     }
 
-    public Loop[] getLoops() {
+    public List<Loop<Block>> getLoops() {
         return loops;
     }
 
@@ -117,15 +119,12 @@
         }
     }
 
-    protected static final int BLOCK_ID_INITIAL = -1;
-    protected static final int BLOCK_ID_VISITED = -2;
-
     private void identifyBlock(Block block) {
         Node cur = block.getBeginNode();
         Node last;
 
         // assign proxies of a loop exit to this block
-        if (cur instanceof AbstractBeginNode) {
+        if (cur instanceof BeginNode) {
             for (Node usage : cur.usages()) {
                 if (usage instanceof ProxyNode) {
                     nodeToBlock.set(usage, block);
@@ -146,7 +145,7 @@
 
             last = cur;
             cur = cur.successors().first();
-        } while (cur != null && !(cur instanceof AbstractBeginNode));
+        } while (cur != null && !(cur instanceof BeginNode));
 
         block.endNode = (FixedNode) last;
     }
@@ -154,7 +153,7 @@
     private void identifyBlocks() {
         // Find all block headers
         int numBlocks = 0;
-        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
+        for (BeginNode begin : graph.getNodes(BeginNode.class)) {
             Block block = new Block(begin);
             numBlocks++;
             identifyBlock(block);
@@ -167,16 +166,16 @@
 
         do {
             Block block = stack.get(stack.size() - 1);
-            if (block.id == BLOCK_ID_INITIAL) {
+            if (block.getId() == BLOCK_ID_INITIAL) {
                 // First time we see this block: push all successors.
                 for (Node suxNode : block.getEndNode().cfgSuccessors()) {
                     Block suxBlock = blockFor(suxNode);
-                    if (suxBlock.id == BLOCK_ID_INITIAL) {
+                    if (suxBlock.getId() == BLOCK_ID_INITIAL) {
                         stack.add(suxBlock);
                     }
                 }
-                block.id = BLOCK_ID_VISITED;
-            } else if (block.id == BLOCK_ID_VISITED) {
+                block.setId(BLOCK_ID_VISITED);
+            } else if (block.getId() == BLOCK_ID_VISITED) {
                 // Second time we see this block: All successors have been processed, so add block
                 // to postorder list.
                 stack.remove(stack.size() - 1);
@@ -192,7 +191,7 @@
         reversePostOrder = new Block[numBlocks];
         for (int i = 0; i < numBlocks; i++) {
             Block block = postOrder.get(numBlocks - i - 1);
-            block.id = i;
+            block.setId(i);
             reversePostOrder[i] = block;
         }
     }
@@ -203,42 +202,42 @@
             List<Block> predecessors = new ArrayList<>(4);
             for (Node predNode : block.getBeginNode().cfgPredecessors()) {
                 Block predBlock = nodeToBlock.get(predNode);
-                if (predBlock.id >= 0) {
+                if (predBlock.getId() >= 0) {
                     predecessors.add(predBlock);
                 }
             }
             if (block.getBeginNode() instanceof LoopBeginNode) {
                 for (LoopEndNode predNode : ((LoopBeginNode) block.getBeginNode()).orderedLoopEnds()) {
                     Block predBlock = nodeToBlock.get(predNode);
-                    if (predBlock.id >= 0) {
+                    if (predBlock.getId() >= 0) {
                         predecessors.add(predBlock);
                     }
                 }
             }
-            block.predecessors = predecessors;
+            block.setPredecessors(predecessors);
 
             List<Block> successors = new ArrayList<>(4);
             for (Node suxNode : block.getEndNode().cfgSuccessors()) {
                 Block suxBlock = nodeToBlock.get(suxNode);
-                assert suxBlock.id >= 0;
+                assert suxBlock.getId() >= 0;
                 successors.add(suxBlock);
             }
             if (block.getEndNode() instanceof LoopEndNode) {
                 Block suxBlock = nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin());
-                assert suxBlock.id >= 0;
+                assert suxBlock.getId() >= 0;
                 successors.add(suxBlock);
             }
-            block.successors = successors;
+            block.setSuccessors(successors);
         }
     }
 
     private void computeLoopInformation() {
-        ArrayList<Loop> loopsList = new ArrayList<>();
+        loops = new ArrayList<>();
         for (Block block : reversePostOrder) {
             Node beginNode = block.getBeginNode();
             if (beginNode instanceof LoopBeginNode) {
-                Loop loop = new Loop(block.getLoop(), loopsList.size(), block);
-                loopsList.add(loop);
+                Loop<Block> loop = new HIRLoop(block.getLoop(), loops.size(), block);
+                loops.add(loop);
 
                 LoopBeginNode loopBegin = (LoopBeginNode) beginNode;
                 for (LoopEndNode end : loopBegin.loopEnds()) {
@@ -256,7 +255,7 @@
                 for (Block b : loop.blocks) {
                     for (Block sux : b.getSuccessors()) {
                         if (sux.loop != loop) {
-                            AbstractBeginNode begin = sux.getBeginNode();
+                            BeginNode begin = sux.getBeginNode();
                             if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) {
                                 Debug.log("Unexpected loop exit with %s, including whole branch in the loop", sux);
                                 unexpected.add(sux);
@@ -269,10 +268,9 @@
                 }
             }
         }
-        loops = loopsList.toArray(new Loop[loopsList.size()]);
     }
 
-    private static void addBranchToLoop(Loop l, Block b) {
+    private static void addBranchToLoop(Loop<Block> l, Block b) {
         if (l.blocks.contains(b)) {
             return;
         }
@@ -283,7 +281,7 @@
         }
     }
 
-    private static void computeLoopBlocks(Block block, Loop loop) {
+    private static void computeLoopBlocks(Block block, Loop<Block> loop) {
         if (block.getLoop() == loop) {
             return;
         }
@@ -316,22 +314,22 @@
     }
 
     private static void setDominator(Block block, Block dominator) {
-        block.dominator = dominator;
+        block.setDominator(dominator);
         if (dominator.dominated == null) {
             dominator.dominated = new ArrayList<>();
         }
         dominator.dominated.add(block);
     }
 
-    public static Block commonDominator(Block a, Block b) {
+    public static <T extends AbstractBlock<T>> T commonDominator(T a, T b) {
         if (a == null) {
             return b;
         }
         if (b == null) {
             return a;
         }
-        Block iterA = a;
-        Block iterB = b;
+        T iterA = a;
+        T iterB = b;
         while (iterA != iterB) {
             if (iterA.getId() > iterB.getId()) {
                 iterA = iterA.getDominator();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/HIRLoop.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.cfg;
+
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.nodes.*;
+
+public class HIRLoop extends Loop<Block> {
+
+    protected HIRLoop(Loop<Block> parent, int index, Block header) {
+        super(parent, index, header);
+    }
+
+    @Override
+    public long numBackedges() {
+        return ((LoopBeginNode) header.getBeginNode()).loopEnds().count();
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Loop.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-import java.util.*;
-
-import com.oracle.graal.nodes.*;
-
-public class Loop {
-
-    public final Loop parent;
-    public final List<Loop> children;
-
-    public final int depth;
-    public final int index;
-    public final Block header;
-    public final List<Block> blocks;
-    public final List<Block> exits;
-
-    protected Loop(Loop parent, int index, Block header) {
-        this.parent = parent;
-        if (parent != null) {
-            this.depth = parent.depth + 1;
-            parent.children.add(this);
-        } else {
-            this.depth = 1;
-        }
-        this.index = index;
-        this.header = header;
-        this.blocks = new ArrayList<>();
-        this.children = new ArrayList<>();
-        this.exits = new ArrayList<>();
-    }
-
-    @Override
-    public String toString() {
-        return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
-    }
-
-    public LoopBeginNode loopBegin() {
-        return (LoopBeginNode) header.getBeginNode();
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.debug;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node can be used to add a counter to the code that will estimate the dynamic number of calls
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that is the sum of two other location nodes. Can represent locations in the form of
@@ -107,9 +108,9 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        Value xAddr = getX().generateAddress(gen, base);
-        return getY().generateAddress(gen, xAddr);
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        Value xAddr = getX().generateAddress(builder, gen, base);
+        return getY().generateAddress(builder, gen, xAddr);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Base class for nodes that modify a range of an array.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -77,7 +78,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         ValueNode v = tool.getReplacedValue(getValue());
-        ResolvedJavaType type = ObjectStamp.typeOrNull(stamp());
+        ResolvedJavaType type = StampTool.typeOrNull(stamp());
 
         VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind);
         assert newVirtual.getFields().length == 1;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * A node that represents an exception thrown implicitly by a Java bytecode. It can be lowered to
+ * either a {@linkplain ForeignCallDescriptor foreign} call or a pre-allocated exception object.
+ */
+public class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+
+    private final Class<? extends Throwable> exceptionClass;
+    @Input private final NodeInputList<ValueNode> arguments;
+    @Input private FrameState deoptState;
+
+    public BytecodeExceptionNode(MetaAccessProvider metaAccess, Class<? extends Throwable> exceptionClass, ValueNode... arguments) {
+        super(StampFactory.exactNonNull(metaAccess.lookupJavaType(exceptionClass)));
+        this.exceptionClass = exceptionClass;
+        this.arguments = new NodeInputList<>(this, arguments);
+    }
+
+    public Class<? extends Throwable> getExceptionClass() {
+        return exceptionClass;
+    }
+
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name) {
+            return super.toString(verbosity) + "#" + exceptionClass.getSimpleName();
+        }
+        return super.toString(verbosity);
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return LocationIdentity.ANY_LOCATION;
+    }
+
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
+    public NodeInputList<ValueNode> getArguments() {
+        return arguments;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class ComputeAddressNode extends FloatingNode implements LIRLowerable {
 
@@ -50,7 +50,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value addr = getLocation().generateAddress(gen, gen.operand(getObject()));
+        Value addr = getLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(getObject()));
         gen.setResult(this, addr);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,10 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that has a constant displacement. Can represent addresses of the form [base + disp]
@@ -65,7 +66,7 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        return gen.getLIRGeneratorTool().emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        return gen.emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/DeferredForeignCallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-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.*;
-
-/**
- * A node that will be lowered to a {@linkplain ForeignCallDescriptor foreign} call.
- */
-@NodeInfo(nameTemplate = "DeferredForeignCall#{p#descriptor/s}")
-public class DeferredForeignCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
-
-    @Input private final NodeInputList<ValueNode> arguments;
-    @Input(InputType.State) private FrameState deoptState;
-
-    private final ForeignCallDescriptor descriptor;
-
-    public DeferredForeignCallNode(ForeignCallDescriptor descriptor, ValueNode... arguments) {
-        super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())));
-        this.arguments = new NodeInputList<>(this, arguments);
-        this.descriptor = descriptor;
-    }
-
-    public ForeignCallDescriptor getDescriptor() {
-        return descriptor;
-    }
-
-    @Override
-    public String toString(Verbosity verbosity) {
-        if (verbosity == Verbosity.Name) {
-            return super.toString(verbosity) + "#" + descriptor;
-        }
-        return super.toString(verbosity);
-    }
-
-    public LocationIdentity getLocationIdentity() {
-        return LocationIdentity.ANY_LOCATION;
-    }
-
-    public void lower(LoweringTool tool) {
-        tool.getLowerer().lower(this, tool);
-    }
-
-    public NodeInputList<ValueNode> getArguments() {
-        return arguments;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Accesses a value at an memory address specified by an {@linkplain #object object} and a
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * An {@link FixedAccessNode} that can be converted to a {@link FloatingAccessNode}.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A floating read of a value from memory specified in terms of an object base and an object
@@ -61,9 +61,9 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, null));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,10 +26,10 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Node for a {@linkplain ForeignCallDescriptor foreign} call.
@@ -94,7 +94,7 @@
     public void generate(NodeLIRBuilderTool gen) {
         ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor);
         Value[] operands = operands(gen);
-        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, operands);
+        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), operands);
         if (result != null) {
             gen.setResult(this, result);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that has a displacement and a scaled index. Can represent locations in the form of
@@ -96,7 +97,7 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        return gen.getLIRGeneratorTool().emitAddress(base, displacement, gen.operand(getIndex()), getIndexScaling());
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        return gen.emitAddress(base, displacement, builder.operand(getIndex()), getIndexScaling());
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,10 +25,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -49,7 +49,7 @@
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public IntegerSwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert keySuccessors.length == keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -76,7 +76,7 @@
      * @param keySuccessors the successor index for each key
      */
     public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
-        this(value, new AbstractBeginNode[successorCount], keys, keyProbabilities, keySuccessors);
+        this(value, new BeginNode[successorCount], keys, keyProbabilities, keySuccessors);
     }
 
     @Override
@@ -139,7 +139,7 @@
                     tool.addToWorkList(defaultSuccessor());
                     graph().removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
-                    ArrayList<AbstractBeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
                     int[] newKeys = new int[validKeys];
                     int[] newKeySuccessors = new int[validKeys + 1];
                     double[] newKeyProbabilities = new double[validKeys + 1];
@@ -172,14 +172,14 @@
                     }
 
                     for (int i = 0; i < blockSuccessorCount(); i++) {
-                        AbstractBeginNode successor = blockSuccessor(i);
+                        BeginNode successor = blockSuccessor(i);
                         if (!newSuccessors.contains(successor)) {
                             tool.deleteBranch(successor);
                         }
                         setBlockSuccessor(i, null);
                     }
 
-                    AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]);
+                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
                     IntegerSwitchNode newSwitch = graph().add(new IntegerSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Read a raw memory location according to Java field or array read semantics. It will perform read
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Loads an object's {@linkplain Representation#ObjectHub hub}. The object is not null-checked by
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,12 +22,10 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Loads a method from the virtual method table of a given hub.
@@ -45,8 +43,8 @@
         super(kind == Kind.Object ? StampFactory.objectNonNull() : StampFactory.forKind(kind));
         this.hub = hub;
         this.method = method;
-        assert !Modifier.isAbstract(method.getModifiers()) : "Cannot load abstract method from a hub";
-        assert !Modifier.isStatic(method.getModifiers()) : "Cannot load a static method from a hub";
+        assert !method.isAbstract() : "Cannot load abstract method from a hub";
+        assert !method.isStatic() : "Cannot load a static method from a hub";
         assert method.isInVirtualMethodTable();
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A location for a memory access in terms of the kind of value accessed and how to access it. All
@@ -62,5 +63,5 @@
         // nothing to do...
     }
 
-    public abstract Value generateAddress(NodeLIRBuilderTool gen, Value base);
+    public abstract Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.lang.reflect.*;
 
@@ -30,10 +30,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Creates a memory barrier.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "OSRLocal({p#index})")
 public class OSRLocalNode extends AbstractLocalNode implements IterableNodeType {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -54,15 +55,18 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, gen.state(this)));
     }
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
-            return graph().add(new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), isCompressible()));
+            ReadNode readNode = graph().add(new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), isCompressible()));
+            readNode.setNullCheck(getNullCheck());
+            readNode.setStateBefore(stateBefore());
+            return readNode;
         }
         return canonicalizeRead(this, location(), object(), tool, isCompressible());
     }
@@ -90,26 +94,22 @@
             }
         }
         if (tool.canonicalizeReads()) {
-            if (metaAccess != null && object != null && object.isConstant()) {
+            if (metaAccess != null && object != null && object.isConstant() && !compressible) {
                 if ((location.getLocationIdentity() == LocationIdentity.FINAL_LOCATION || location.getLocationIdentity() == LocationIdentity.ARRAY_LENGTH_LOCATION) &&
                                 location instanceof ConstantLocationNode) {
                     long displacement = ((ConstantLocationNode) location).getDisplacement();
-                    Kind kind = location.getValueKind();
-                    if (object.getKind() == Kind.Object) {
-                        Object base = object.asConstant().asObject();
-                        if (base != null) {
-                            Constant constant = tool.getConstantReflection().readUnsafeConstant(kind, base, displacement, compressible);
-                            if (constant != null) {
-                                return ConstantNode.forConstant(constant, metaAccess, read.graph());
-                            }
+                    Constant base = object.asConstant();
+                    if (base != null) {
+                        Constant constant;
+                        if (read.stamp() instanceof PrimitiveStamp) {
+                            PrimitiveStamp stamp = (PrimitiveStamp) read.stamp();
+                            constant = tool.getConstantReflection().readRawConstant(stamp.getStackKind(), base, displacement, stamp.getBits());
+                        } else {
+                            assert read.stamp() instanceof ObjectStamp;
+                            constant = tool.getConstantReflection().readUnsafeConstant(Kind.Object, base, displacement);
                         }
-                    } else if (object.getKind().isNumericInteger()) {
-                        long base = object.asConstant().asLong();
-                        if (base != 0L) {
-                            Constant constant = tool.getConstantReflection().readUnsafeConstant(kind, null, base + displacement, compressible);
-                            if (constant != null) {
-                                return ConstantNode.forConstant(constant, metaAccess, read.graph());
-                            }
+                        if (constant != null) {
+                            return ConstantNode.forConstant(read.stamp(), constant, metaAccess, read.graph());
                         }
                     }
                 }
@@ -144,7 +144,7 @@
         }
 
         ObjectStamp valueStamp = (ObjectStamp) parent.object().stamp();
-        ResolvedJavaType valueType = ObjectStamp.typeOrNull(valueStamp);
+        ResolvedJavaType valueType = StampTool.typeOrNull(valueStamp);
         if (valueType != null && field.getDeclaringClass().isAssignableFrom(valueType)) {
             if (piStamp.nonNull() == valueStamp.nonNull() && piStamp.alwaysNull() == valueStamp.alwaysNull()) {
                 replaceFirstInput(parent, parent.object());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2013, 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.nodes.extended;
-
-import static com.oracle.graal.api.meta.LocationIdentity.*;
-
-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.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * Location node that can be used inside a snippet without having the elements (including the
- * location identity and kind) as a snippet constant. Can represent locations in the form of [base +
- * index * scale + disp]. When the location is created, all elements (base, index, scale, disp) are
- * nodes. Both scale and disp must eventually canonicalize to {@link ConstantNode constants} so that
- * this node can be canonicalized to a {@link IndexedLocationNode} or {@link ConstantLocationNode}.
- */
-public final class SnippetLocationNode extends LocationNode implements Canonicalizable {
-
-    @Input private ValueNode valueKind;
-    @Input(InputType.Association) private ValueNode locationIdentity;
-    @Input private ValueNode displacement;
-    @Input private ValueNode index;
-    @Input private ValueNode indexScaling;
-
-    public static SnippetLocationNode create(ValueNode identity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling, Graph graph) {
-        return graph.unique(new SnippetLocationNode(identity, kind, displacement, index, indexScaling));
-    }
-
-    private SnippetLocationNode(ValueNode locationIdentity, ValueNode kind, ValueNode displacement) {
-        this(locationIdentity, kind, displacement, null, null);
-    }
-
-    private SnippetLocationNode(ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling) {
-        super(StampFactory.object());
-        this.valueKind = kind;
-        this.locationIdentity = locationIdentity;
-        this.displacement = displacement;
-        this.index = index;
-        this.indexScaling = indexScaling;
-    }
-
-    @Override
-    public Kind getValueKind() {
-        if (valueKind.isConstant()) {
-            return (Kind) valueKind.asConstant().asObject();
-        }
-        throw new GraalInternalError("Cannot access kind yet because it is not constant: " + valueKind);
-    }
-
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        if (locationIdentity.isConstant()) {
-            return (LocationIdentity) locationIdentity.asConstant().asObject();
-        }
-        // We do not know our actual location identity yet, so be conservative.
-        return ANY_LOCATION;
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (valueKind.isConstant() && locationIdentity.isConstant() && displacement.isConstant() && (indexScaling == null || indexScaling.isConstant())) {
-            Kind constKind = (Kind) valueKind.asConstant().asObject();
-            LocationIdentity constLocation = (LocationIdentity) locationIdentity.asConstant().asObject();
-            long constDisplacement = displacement.asConstant().asLong();
-            int constIndexScaling = indexScaling == null ? 0 : indexScaling.asConstant().asInt();
-
-            if (index == null || constIndexScaling == 0) {
-                return ConstantLocationNode.create(constLocation, constKind, constDisplacement, graph());
-            } else if (index.isConstant()) {
-                return ConstantLocationNode.create(constLocation, constKind, index.asConstant().asLong() * constIndexScaling + constDisplacement, graph());
-            } else {
-                return IndexedLocationNode.create(constLocation, constKind, constDisplacement, index, graph(), constIndexScaling);
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        throw new GraalInternalError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity);
-    }
-
-    @NodeIntrinsic
-    public static native Location constantLocation(LocationIdentity identity, Kind kind, long displacement);
-
-    @NodeIntrinsic
-    public static native Location indexedLocation(LocationIdentity identity, Kind kind, long displacement, int index, int indexScaling);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public final class StoreHubNode extends FixedWithNextNode implements Lowerable {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,16 +25,17 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code SwitchNode} class is the base of both lookup and table switches.
  */
 public abstract class SwitchNode extends ControlSplitNode {
 
-    @Successor private final NodeSuccessorList<AbstractBeginNode> successors;
+    @Successor private final NodeSuccessorList<BeginNode> successors;
     @Input private ValueNode value;
     private double[] keyProbabilities;
     private int[] keySuccessors;
@@ -45,7 +46,7 @@
      * @param value the instruction that provides the value to be switched over
      * @param successors the list of successors of this switch
      */
-    public SwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
+    public SwitchNode(ValueNode value, BeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
         super(StampFactory.forVoid());
         assert value.getKind() == Kind.Int || value.getKind() == Kind.Long || value.getKind() == Kind.Object : value.getKind() + " key not supported by SwitchNode";
         assert keySuccessors.length == keyProbabilities.length;
@@ -76,7 +77,7 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         double sum = 0;
         for (int i = 0; i < keySuccessors.length; i++) {
             if (successors.get(keySuccessors[i]) == successor) {
@@ -87,7 +88,7 @@
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         double changeInProbability = 0;
         int nonZeroProbabilityCases = 0;
         for (int i = 0; i < keySuccessors.length; i++) {
@@ -139,7 +140,7 @@
     /**
      * Returns the successor for the key at the given index.
      */
-    public AbstractBeginNode keySuccessor(int i) {
+    public BeginNode keySuccessor(int i) {
         return successors.get(keySuccessors[i]);
     }
 
@@ -157,11 +158,11 @@
         return keySuccessors[keySuccessors.length - 1];
     }
 
-    public AbstractBeginNode blockSuccessor(int i) {
+    public BeginNode blockSuccessor(int i) {
         return successors.get(i);
     }
 
-    public void setBlockSuccessor(int i, AbstractBeginNode s) {
+    public void setBlockSuccessor(int i, BeginNode s) {
         successors.set(i, s);
     }
 
@@ -174,7 +175,7 @@
      * 
      * @return the default successor
      */
-    public AbstractBeginNode defaultSuccessor() {
+    public BeginNode defaultSuccessor() {
         if (defaultSuccessorIndex() == -1) {
             throw new GraalInternalError("unexpected");
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,12 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 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.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class UnboxNode extends FloatingNode implements Virtualizable, Lowerable, Canonicalizable {
 
@@ -70,28 +70,9 @@
     public Node canonical(CanonicalizerTool tool) {
         if (value.isConstant()) {
             Constant constant = value.asConstant();
-            Object o = constant.asObject();
-            if (o != null) {
-                switch (boxingKind) {
-                    case Boolean:
-                        return ConstantNode.forBoolean((Boolean) o, graph());
-                    case Byte:
-                        return ConstantNode.forByte((Byte) o, graph());
-                    case Char:
-                        return ConstantNode.forChar((Character) o, graph());
-                    case Short:
-                        return ConstantNode.forShort((Short) o, graph());
-                    case Int:
-                        return ConstantNode.forInt((Integer) o, graph());
-                    case Long:
-                        return ConstantNode.forLong((Long) o, graph());
-                    case Float:
-                        return ConstantNode.forFloat((Float) o, graph());
-                    case Double:
-                        return ConstantNode.forDouble((Double) o, graph());
-                    default:
-                        ValueNodeUtil.shouldNotReachHere();
-                }
+            Constant unboxed = tool.getConstantReflection().unboxPrimitive(constant);
+            if (unboxed != null && unboxed.getKind() == boxingKind) {
+                return ConstantNode.forConstant(unboxed, tool.getMetaAccess(), graph());
             }
         } else if (value instanceof BoxNode) {
             BoxNode box = (BoxNode) value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -66,7 +67,7 @@
             long constantOffset = offset().asConstant().asLong();
 
             // Try to canonicalize to a field access.
-            ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object());
+            ResolvedJavaType receiverType = StampTool.typeOrNull(object());
             if (receiverType != null) {
                 ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(constantOffset);
                 // No need for checking that the receiver is non-null. The field access includes
@@ -78,8 +79,20 @@
                 }
             }
         }
+        if (this.getLocationIdentity() == LocationIdentity.ANY_LOCATION) {
+            ResolvedJavaType receiverType = StampTool.typeOrNull(object());
+            // Try to build a better location identity.
+            if (receiverType != null && receiverType.isArray()) {
+                LocationIdentity identity = NamedLocationIdentity.getArrayLocation(receiverType.getComponentType().getKind());
+                assert !graph().isAfterFloatingReadPhase() : "cannot add more precise memory location after floating read phase";
+                return cloneAsArrayAccess(offset(), identity);
+            }
+        }
+
         return this;
     }
 
     protected abstract ValueNode cloneAsFieldAccess(ResolvedJavaField field);
+
+    protected abstract ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -50,7 +51,7 @@
     }
 
     public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
-        this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind()));
+        this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind()));
     }
 
     @Override
@@ -59,36 +60,27 @@
     }
 
     @Override
+    public boolean inferStamp() {
+        if (stamp() instanceof ObjectStamp && object.stamp() instanceof ObjectStamp) {
+            return updateStamp(((ObjectStamp) object.stamp()).castTo((ObjectStamp) stamp()));
+        }
+        return updateStamp(object.stamp().join(stamp()));
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
         assert getKind() == Kind.Object && object.getKind() == Kind.Object;
-
-        ObjectStamp my = (ObjectStamp) stamp();
-        ObjectStamp other = (ObjectStamp) object.stamp();
-
-        if (my.type() == null || other.type() == null) {
-            return this;
-        }
-        if (my.isExactType() && !other.isExactType()) {
+        if (stamp().equals(object.stamp())) {
+            return object;
+        } else {
             return this;
         }
-        if (my.nonNull() && !other.nonNull()) {
-            return this;
-        }
-        if (!my.type().isAssignableFrom(other.type())) {
-            return this;
-        }
-        /*
-         * The unsafe cast does not add any new type information, so it can be removed. Note that
-         * this means that the unsafe cast cannot be used to "drop" type information (in which case
-         * it must not be canonicalized in any case).
-         */
-        return object;
     }
 
     @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
-        if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
+        if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
             tool.replaceWithVirtual(state.getVirtualObject());
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Load of a value from a location specified as an offset relative to an object. No null check is
@@ -79,6 +79,11 @@
         return this.graph().add(new LoadFieldNode(object(), field));
     }
 
+    @Override
+    protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) {
+        return this.graph().add(new UnsafeLoadNode(object(), location, accessKind(), identity));
+    }
+
     @SuppressWarnings({"unchecked", "unused"})
     @NodeIntrinsic
     public static <T> T load(Object object, long offset, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Store of a value at a location specified as an offset relative to an object. No null check is
@@ -108,6 +108,11 @@
         return storeFieldNode;
     }
 
+    @Override
+    protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) {
+        return this.graph().add(new UnsafeStoreNode(object(), location, value, accessKind(), identity));
+    }
+
     public FrameState getState() {
         return stateAfter;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -22,19 +22,19 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 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.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
  * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph.
  */
-@NodeInfo(allowedUsageTypes = {InputType.Anchor})
-public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode {
+@NodeInfo(allowedUsageTypes = {InputType.Anchor, InputType.Guard})
+public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode {
 
     @Input(InputType.Guard) private ValueNode anchored;
 
@@ -91,7 +91,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        if (anchored != null && !(anchored instanceof AbstractBeginNode)) {
+        if (anchored != null && !(anchored instanceof BeginNode)) {
             State state = tool.getObjectState(anchored);
             if (state == null || state.getState() != EscapeState.Virtual) {
                 return;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -44,7 +44,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         // It's possible a constant was forced for other usages so inspect the value directly and
         // use a constant if it can be directly stored.
         Value v;
@@ -54,7 +54,7 @@
             v = gen.operand(value());
         }
         PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(value().stamp());
-        gen.getLIRGeneratorTool().emitStore(writeKind, address, v, this);
+        gen.getLIRGeneratorTool().emitStore(writeKind, address, v, gen.state(this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,12 +24,12 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code AbstractNewObjectNode} is the base class for the new instance and new array nodes.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This the base class of all array operations.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,12 +22,10 @@
  */
 package com.oracle.graal.nodes.java;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The base class of all instructions that access fields.
@@ -70,7 +68,7 @@
      * @return {@code true} if this field access is to a static field
      */
     public boolean isStatic() {
-        return Modifier.isStatic(field.getModifiers());
+        return field.isStatic();
     }
 
     /**
@@ -79,7 +77,7 @@
      * @return {@code true} if the field is resolved and declared volatile
      */
     public boolean isVolatile() {
-        return Modifier.isVolatile(field.getModifiers());
+        return field.isVolatile();
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code AccessIndexedNode} class is the base class of instructions that read or write elements
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code AccessMonitorNode} is the base class of both monitor acquisition and release.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 /**
  * The {@code ArrayLength} instruction gets the length of an array.
@@ -57,22 +58,34 @@
     /**
      * Gets the length of an array if possible.
      *
-     * @param graph TODO
-     * @param array an array
-     *
      * @return a node representing the length of {@code array} or null if it is not available
      */
-    public static ValueNode readArrayLength(StructuredGraph graph, ValueNode array, ConstantReflectionProvider constantReflection) {
-        if (array instanceof ArrayLengthProvider) {
-            ValueNode length = ((ArrayLengthProvider) array).length();
+    public static ValueNode readArrayLength(StructuredGraph graph, ValueNode originalArray, ConstantReflectionProvider constantReflection) {
+        ArrayLengthProvider foundArrayLengthProvider = null;
+        ValueNode result = originalArray;
+        while (true) {
+            if (result instanceof ArrayLengthProvider) {
+                foundArrayLengthProvider = (ArrayLengthProvider) result;
+                break;
+            }
+            if (result instanceof ValueProxy) {
+                result = ((ValueProxy) result).getOriginalNode();
+            } else {
+                break;
+            }
+        }
+
+        if (foundArrayLengthProvider != null) {
+            ValueNode length = foundArrayLengthProvider.length();
             if (length != null) {
                 return length;
             }
         }
+        ValueNode array = GraphUtil.unproxify(originalArray);
         if (constantReflection != null && array.isConstant() && !array.isNullConstant()) {
             Constant constantValue = array.asConstant();
             if (constantValue != null && constantValue.isNonNull()) {
-                Integer constantLength = constantReflection.lookupArrayLength(constantValue);
+                Integer constantLength = constantReflection.readArrayLength(constantValue);
                 if (constantLength != null) {
                     return ConstantNode.forInt(constantLength, graph);
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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.nodes.java;
+
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+import sun.misc.*;
+
+/**
+ * Represents an atomic read-and-add operation like {@link Unsafe#getAndAddInt(Object, long, int)}.
+ */
+@NodeInfo(allowedUsageTypes = {InputType.Memory})
+public class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single {
+
+    @Input private ValueNode object;
+    @Input private ValueNode offset;
+    @Input private ValueNode delta;
+
+    private final LocationIdentity locationIdentity;
+
+    public AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) {
+        super(StampFactory.forKind(delta.getKind()));
+        this.object = object;
+        this.offset = offset;
+        this.delta = delta;
+        this.locationIdentity = locationIdentity;
+    }
+
+    public ValueNode object() {
+        return object;
+    }
+
+    public ValueNode offset() {
+        return offset;
+    }
+
+    public ValueNode delta() {
+        return delta;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return locationIdentity;
+    }
+
+    public void generate(NodeLIRBuilderTool gen) {
+        LocationNode location = IndexedLocationNode.create(getLocationIdentity(), delta.getKind(), 0, offset, graph(), 1);
+        Value address = location.generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
+        Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(address, gen.operand(delta));
+        gen.setResult(this, result);
+    }
+
+    @NodeIntrinsic
+    public static int getAndAddInt(Object object, long offset, int delta, @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndAddInt(object, offset, delta);
+    }
+
+    @NodeIntrinsic
+    public static long getAndAddLong(Object object, long offset, long delta, @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndAddLong(object, offset, delta);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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.nodes.java;
+
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+import sun.misc.*;
+
+/**
+ * Represents an atomic read-and-write operation like {@link Unsafe#getAndSetInt(Object, long, int)}
+ * .
+ */
+public class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+
+    @Input private ValueNode object;
+    @Input private ValueNode offset;
+    @Input private ValueNode newValue;
+
+    private final Kind valueKind;
+    private final LocationIdentity locationIdentity;
+
+    public AtomicReadAndWriteNode(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
+        super(StampFactory.forKind(newValue.getKind()));
+        this.object = object;
+        this.offset = offset;
+        this.newValue = newValue;
+        this.valueKind = valueKind;
+        this.locationIdentity = locationIdentity;
+    }
+
+    public ValueNode object() {
+        return object;
+    }
+
+    public ValueNode offset() {
+        return offset;
+    }
+
+    public ValueNode newValue() {
+        return newValue;
+    }
+
+    public Kind getValueKind() {
+        return valueKind;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return locationIdentity;
+    }
+
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
+    @NodeIntrinsic
+    public static int getAndSetInt(Object object, long offset, int newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind,
+                    @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndSetInt(object, offset, newValue);
+    }
+
+    @NodeIntrinsic
+    public static long getAndSetLong(Object object, long offset, long newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind,
+                    @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndSetLong(object, offset, newValue);
+    }
+
+    @NodeIntrinsic
+    public static Object getAndSetObject(Object object, long offset, Object newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind,
+                    @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndSetObject(object, offset, newValue);
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -73,13 +73,14 @@
     public Node canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        if (ObjectStamp.isObjectAlwaysNull(object())) {
+        if (StampTool.isObjectAlwaysNull(object())) {
             return object();
         }
-        if (hub.isConstant() && hub.asConstant().getKind() == Kind.Object && hub.asConstant().asObject() instanceof Class) {
-            Class clazz = (Class) hub.asConstant().asObject();
-            ResolvedJavaType t = tool.getMetaAccess().lookupJavaType(clazz);
-            return graph().add(new CheckCastNode(t, object(), null, forStoreCheck));
+        if (hub.isConstant()) {
+            ResolvedJavaType t = tool.getConstantReflection().asJavaType(hub.asConstant());
+            if (t != null) {
+                return graph().add(new CheckCastNode(t, object(), null, forStoreCheck));
+            }
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -106,7 +107,7 @@
             // This is a check cast that will always fail
             condition = LogicConstantNode.contradiction(graph());
             stamp = StampFactory.declared(type);
-        } else if (ObjectStamp.isObjectNonNull(object)) {
+        } else if (StampTool.isObjectNonNull(object)) {
             condition = graph().addWithoutUnique(new InstanceOfNode(type, object, profile));
         } else {
             if (profile != null && profile.getNullSeen() == TriState.FALSE) {
@@ -141,7 +142,7 @@
     public Node canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        ResolvedJavaType objectType = ObjectStamp.typeOrNull(object());
+        ResolvedJavaType objectType = StampTool.typeOrNull(object());
         if (objectType != null && type.isAssignableFrom(objectType)) {
             // we don't have to check for null types here because they will also pass the
             // checkcast.
@@ -160,7 +161,7 @@
             }
         }
 
-        if (ObjectStamp.isObjectAlwaysNull(object())) {
+        if (StampTool.isObjectAlwaysNull(object())) {
             return object();
         }
         if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.nodes.java;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
@@ -42,7 +42,22 @@
     @Input private ValueNode offset;
     @Input private ValueNode expected;
     @Input private ValueNode newValue;
+
+    private final Kind valueKind;
     private final int displacement;
+    private final LocationIdentity locationIdentity;
+
+    public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
+        super(StampFactory.forKind(Kind.Boolean.getStackKind()));
+        assert expected.stamp().isCompatible(newValue.stamp());
+        this.object = object;
+        this.offset = offset;
+        this.expected = expected;
+        this.newValue = newValue;
+        this.displacement = displacement;
+        this.valueKind = valueKind;
+        this.locationIdentity = locationIdentity;
+    }
 
     public ValueNode object() {
         return object;
@@ -64,19 +79,13 @@
         return displacement;
     }
 
-    public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
-        super(StampFactory.forKind(Kind.Boolean.getStackKind()));
-        assert expected.stamp().isCompatible(newValue.stamp());
-        this.object = object;
-        this.offset = offset;
-        this.expected = expected;
-        this.newValue = newValue;
-        this.displacement = displacement;
+    public Kind getValueKind() {
+        return valueKind;
     }
 
     @Override
     public LocationIdentity getLocationIdentity() {
-        return LocationIdentity.ANY_LOCATION;
+        return locationIdentity;
     }
 
     @Override
@@ -86,17 +95,20 @@
 
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
     @NodeIntrinsic
-    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, Object expected, Object newValue) {
+    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, Object expected, Object newValue,
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) {
         return unsafe.compareAndSwapObject(object, displacement + offset, expected, newValue);
     }
 
     @NodeIntrinsic
-    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, long expected, long newValue) {
+    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, long expected, long newValue,
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) {
         return unsafe.compareAndSwapLong(object, displacement + offset, expected, newValue);
     }
 
     @NodeIntrinsic
-    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, int expected, int newValue) {
+    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, int expected, int newValue,
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) {
         return unsafe.compareAndSwapInt(object, displacement + offset, expected, newValue);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,10 +26,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code DynamicNewArrayNode} is used for allocation of arrays when the type is not a
@@ -55,9 +55,8 @@
     @Override
     public void simplify(SimplifierTool tool) {
         if (isAlive() && elementType.isConstant()) {
-            Class<?> elementClass = (Class<?>) elementType.asConstant().asObject();
-            if (elementClass != null && !(elementClass.equals(void.class))) {
-                ResolvedJavaType javaType = tool.getMetaAccess().lookupJavaType(elementClass);
+            ResolvedJavaType javaType = tool.getConstantReflection().asJavaType(elementType.asConstant());
+            if (javaType != null && !javaType.equals(tool.getMetaAccess().lookupJavaType(void.class))) {
                 NewArrayNode newArray = graph().add(new NewArrayNode(javaType, length(), fillContents()));
                 List<Node> snapshot = inputs().snapshot();
                 graph().replaceFixedWithFixed(this, newArray);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable {
 
@@ -40,13 +40,9 @@
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (clazz.isConstant()) {
-            Constant clazzConstant = clazz.asConstant();
-            if (clazzConstant.getKind() == Kind.Object && clazzConstant.asObject() instanceof Class) {
-                Class staticClass = (Class) clazzConstant.asObject();
-                ResolvedJavaType type = tool.getMetaAccess().lookupJavaType(staticClass);
-                if (type.isInitialized()) {
-                    return graph().add(new NewInstanceNode(type, fillContents()));
-                }
+            ResolvedJavaType type = tool.getConstantReflection().asJavaType(clazz.asConstant());
+            if (type != null && type.isInitialized()) {
+                return graph().add(new NewInstanceNode(type, fillContents()));
             }
         }
         return this;
@@ -57,5 +53,5 @@
     }
 
     @NodeIntrinsic
-    public static native Object allocateInstance(Class clazz, @ConstantNodeParameter boolean fillContents);
+    public static native Object allocateInstance(Class<?> clazz, @ConstantNodeParameter boolean fillContents);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,12 +26,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The entry to an exception handler with the exception coming from a call (as opposed to a local
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -47,8 +47,8 @@
         this.mirror = mirror;
         this.object = object;
         assert mirror.getKind() == Kind.Object : mirror.getKind();
-        assert ObjectStamp.isExactType(mirror);
-        assert ObjectStamp.typeOrNull(mirror).getName().equals("Ljava/lang/Class;");
+        assert StampTool.isExactType(mirror);
+        assert StampTool.typeOrNull(mirror).getName().equals("Ljava/lang/Class;");
     }
 
     @Override
@@ -60,12 +60,13 @@
     public Node canonical(CanonicalizerTool tool) {
         assert object() != null : this;
         if (mirror().isConstant()) {
-            Class clazz = (Class) mirror().asConstant().asObject();
-            ResolvedJavaType t = tool.getMetaAccess().lookupJavaType(clazz);
-            if (t.isPrimitive()) {
-                return LogicConstantNode.contradiction(graph());
-            } else {
-                return graph().unique(new InstanceOfNode(t, object(), null));
+            ResolvedJavaType t = tool.getConstantReflection().asJavaType(mirror().asConstant());
+            if (t != null) {
+                if (t.isPrimitive()) {
+                    return LogicConstantNode.contradiction(graph());
+                } else {
+                    return graph().unique(new InstanceOfNode(t, object(), null));
+                }
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,12 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 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.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code InstanceOfNode} represents an instanceof test.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Loads an exception object passed by the runtime from a callee to an exception handler in a
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.nodes.java;
 
-import java.lang.reflect.*;
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -60,7 +60,7 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (usages().isEmpty() && !isVolatile() && (isStatic() || ObjectStamp.isObjectNonNull(object().stamp()))) {
+        if (usages().isEmpty() && !isVolatile() && (isStatic() || StampTool.isObjectNonNull(object().stamp()))) {
             return null;
         }
         MetaAccessProvider metaAccess = tool.getMetaAccess();
@@ -97,7 +97,7 @@
     }
 
     private PhiNode asPhi(MetaAccessProvider metaAccess) {
-        if (!isStatic() && Modifier.isFinal(field.getModifiers()) && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(NodePredicates.isNotA(ConstantNode.class)).isEmpty()) {
+        if (!isStatic() && field.isFinal() && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(isNotA(ConstantNode.class)).isEmpty()) {
             PhiNode phi = (PhiNode) object();
             Constant[] constants = new Constant[phi.valueCount()];
             for (int i = 0; i < phi.valueCount(); i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -44,7 +45,7 @@
     }
 
     private static Stamp createStamp(ValueNode array, Kind kind) {
-        ResolvedJavaType type = ObjectStamp.typeOrNull(array);
+        ResolvedJavaType type = StampTool.typeOrNull(array);
         if (kind == Kind.Object && type != null) {
             return StampFactory.declared(type.getComponentType());
         } else {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -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.nodes.java;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+import sun.misc.*;
+
+/**
+ * Represents the lowered version of an atomic read-and-write operation like
+ * {@link Unsafe#getAndSetInt(Object, long, int)} .
+ */
+@NodeInfo(allowedUsageTypes = {InputType.Memory})
+public class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single {
+
+    @Input private ValueNode newValue;
+    @Input(InputType.State) private FrameState stateAfter;
+
+    public LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType, boolean compressible) {
+        super(object, location, newValue.stamp(), barrierType, compressible);
+        this.newValue = newValue;
+    }
+
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    public void setStateAfter(FrameState x) {
+        assert x == null || x.isAlive() : "frame state must be in a graph";
+        updateUsages(stateAfter, x);
+        stateAfter = x;
+    }
+
+    public boolean hasSideEffect() {
+        return true;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return location().getLocationIdentity();
+    }
+
+    public void generate(NodeLIRBuilderTool gen) {
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
+        Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(address, gen.operand(newValue));
+        gen.setResult(this, result);
+    }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
+
+    public boolean canNullCheck() {
+        return false;
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Represents the lowered version of an atomic compare-and-swap operation{@code CompareAndSwapNode}.
@@ -79,7 +79,10 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.visitCompareAndSwap(this, location().generateAddress(gen, gen.operand(object())));
+        assert getNewValue().stamp().isCompatible(getExpectedValue().stamp());
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
+        Value result = gen.getLIRGeneratorTool().emitCompareAndSwap(address, gen.operand(getExpectedValue()), gen.operand(getNewValue()), Constant.INT_1, Constant.INT_0);
+        gen.setResult(this, result);
     }
 
     public MemoryCheckpoint asMemoryCheckpoint() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,8 @@
  */
 package com.oracle.graal.nodes.java;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -55,7 +54,7 @@
 
     /**
      * Gets the target method for this invocation instruction.
-     * 
+     *
      * @return the target method
      */
     public ResolvedJavaMethod targetMethod() {
@@ -76,7 +75,7 @@
 
     /**
      * Gets the instruction that produces the receiver object for this invocation, if any.
-     * 
+     *
      * @return the instruction that produces the receiver object for this invocation if any,
      *         {@code null} if this invocation does not take a receiver object
      */
@@ -86,7 +85,7 @@
 
     /**
      * Checks whether this is an invocation of a static method.
-     * 
+     *
      * @return {@code true} if the invocation is a static invocation
      */
     public boolean isStatic() {
@@ -108,12 +107,12 @@
             assertTrue(n instanceof Invoke, "call target can only be used from an invoke (%s)", n);
         }
         if (invokeKind == InvokeKind.Special || invokeKind == InvokeKind.Static) {
-            assertFalse(Modifier.isAbstract(targetMethod.getModifiers()), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod);
+            assertFalse(targetMethod.isAbstract(), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod);
         }
         if (invokeKind == InvokeKind.Static) {
-            assertTrue(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for static methods (%s)", targetMethod);
+            assertTrue(targetMethod.isStatic(), "static calls are only allowed for static methods (%s)", targetMethod);
         } else {
-            assertFalse(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for non-static methods (%s)", targetMethod);
+            assertFalse(targetMethod.isStatic(), "static calls are only allowed for non-static methods (%s)", targetMethod);
         }
         return super.verify();
     }
@@ -138,18 +137,17 @@
                 return this;
             }
 
-            // check if the exact type of the receiver can be determined
+            assert targetMethod.getDeclaringClass().asExactType() == null : "should have been handled by canBeStaticallyBound";
+
+            // check if the type of the receiver can narrow the result
             ValueNode receiver = receiver();
-            ResolvedJavaType exact = targetMethod.getDeclaringClass().asExactType();
-            if (exact == null && ObjectStamp.isExactType(receiver)) {
-                exact = ObjectStamp.typeOrNull(receiver);
-            }
-            if (exact != null) {
+            ResolvedJavaType type = StampTool.typeOrNull(receiver);
+            if (type != null) {
                 // either the holder class is exact, or the receiver object has an exact type
-                ResolvedJavaMethod exactMethod = exact.resolveMethod(targetMethod);
-                if (exactMethod != null) {
+                ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod);
+                if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver))) {
                     invokeKind = InvokeKind.Special;
-                    targetMethod = exactMethod;
+                    targetMethod = resolvedMethod;
                     return this;
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -58,7 +59,7 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        if (escapedReturnValue != null && stateAfter() != null && stateAfter().bci != FrameState.AFTER_BCI) {
+        if (escapedReturnValue != null && stateAfter() != null && stateAfter().bci != BytecodeFrame.AFTER_BCI) {
             ValueNode returnValue = escapedReturnValue;
             setEscapedReturnValue(null);
             tool.removeIfUnused(returnValue);
@@ -74,7 +75,7 @@
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object());
         // the monitor exit for a synchronized method should never be virtualized
-        assert stateAfter().bci != FrameState.AFTER_BCI || state == null;
+        assert stateAfter().bci != BytecodeFrame.AFTER_BCI || state == null;
         if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) {
             MonitorIdNode removedLock = state.removeLock();
             assert removedLock == getMonitorId() : "mismatch at " + this + ": " + removedLock + " vs. " + getMonitorId();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node describes one locking scope; it ties the monitor enter, monitor exit and the frame
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -54,7 +55,7 @@
      * @return the element type of the array
      */
     public ResolvedJavaType elementType() {
-        return ObjectStamp.typeOrNull(this).getComponentType();
+        return StampTool.typeOrNull(this).getComponentType();
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,10 +26,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 
 /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code NewMultiArrayNode} represents an allocation of a multi-dimensional object array.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node is used to perform the finalizer registration at the end of the java.lang.Object
@@ -53,7 +53,7 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(REGISTER_FINALIZER);
-        gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(object()));
+        gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(object()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,8 @@
  */
 package com.oracle.graal.nodes.java;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -65,7 +64,7 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        InvokeKind invokeKind = Modifier.isStatic(replacementTargetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special;
+        InvokeKind invokeKind = replacementTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special;
         MethodCallTargetNode replacement = graph().add(
                         new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType));
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 
 /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -75,8 +76,8 @@
             int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1;
             if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) {
                 ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType();
-                if (componentType.isPrimitive() || ObjectStamp.isObjectAlwaysNull(value) || componentType.getSuperclass() == null ||
-                                (ObjectStamp.typeOrNull(value) != null && componentType.isAssignableFrom(ObjectStamp.typeOrNull(value)))) {
+                if (componentType.isPrimitive() || StampTool.isObjectAlwaysNull(value) || componentType.getSuperclass() == null ||
+                                (StampTool.typeOrNull(value) != null && componentType.isAssignableFrom(StampTool.typeOrNull(value)))) {
                     tool.setVirtualEntry(arrayState, index, value(), false);
                     tool.delete();
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,11 +26,11 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -51,7 +51,7 @@
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public TypeSwitchNode(ValueNode value, AbstractBeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert successors.length <= keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -134,7 +134,7 @@
                     tool.addToWorkList(defaultSuccessor());
                     graph().removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
-                    ArrayList<AbstractBeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
                     ResolvedJavaType[] newKeys = new ResolvedJavaType[validKeys];
                     int[] newKeySuccessors = new int[validKeys + 1];
                     double[] newKeyProbabilities = new double[validKeys + 1];
@@ -167,14 +167,14 @@
                     }
 
                     for (int i = 0; i < blockSuccessorCount(); i++) {
-                        AbstractBeginNode successor = blockSuccessor(i);
+                        BeginNode successor = blockSuccessor(i);
                         if (!newSuccessors.contains(successor)) {
                             tool.deleteBranch(successor);
                         }
                         setBlockSuccessor(i, null);
                     }
 
-                    AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]);
+                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
                     TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +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.nodes.spi;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * This interface can be used to generate LIR for arithmetic operations.
- */
-public interface ArithmeticLIRGenerator {
-    /**
-     * TODO remove reference to {@link Stamp}.
-     */
-    PlatformKind getPlatformKind(Stamp stamp);
-
-    Value emitNegate(Value input);
-
-    Value emitAdd(Value a, Value b);
-
-    Value emitSub(Value a, Value b);
-
-    Value emitMul(Value a, Value b);
-
-    /**
-     * TODO remove {@link DeoptimizeNode}.
-     */
-    Value emitDiv(Value a, Value b, DeoptimizingNode deopting);
-
-    /**
-     * TODO remove {@link DeoptimizeNode}.
-     */
-    Value emitRem(Value a, Value b, DeoptimizingNode deopting);
-
-    /**
-     * TODO remove {@link DeoptimizeNode}.
-     */
-    Value emitUDiv(Value a, Value b, DeoptimizingNode deopting);
-
-    /**
-     * TODO remove {@link DeoptimizeNode}.
-     */
-    Value emitURem(Value a, Value b, DeoptimizingNode deopting);
-
-    Value emitNot(Value input);
-
-    Value emitAnd(Value a, Value b);
-
-    Value emitOr(Value a, Value b);
-
-    Value emitXor(Value a, Value b);
-
-    Value emitShl(Value a, Value b);
-
-    Value emitShr(Value a, Value b);
-
-    Value emitUShr(Value a, Value b);
-
-    Value emitFloatConvert(FloatConvert op, Value inputVal);
-
-    Value emitReinterpret(PlatformKind to, Value inputVal);
-
-    Value emitNarrow(Value inputVal, int bits);
-
-    Value emitSignExtend(Value inputVal, int fromBits, int toBits);
-
-    Value emitZeroExtend(Value inputVal, int fromBits, int toBits);
-
-    Value emitMathAbs(Value input);
-
-    Value emitMathSqrt(Value input);
-
-    Value emitMathLog(Value input, boolean base10);
-
-    Value emitMathCos(Value input);
-
-    Value emitMathSin(Value input);
-
-    Value emitMathTan(Value input);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,9 @@
 package com.oracle.graal.nodes.spi;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.lir.gen.*;
 
 public interface ArithmeticLIRLowerable extends ArithmeticOperation {
 
-    void generate(NodeLIRBuilderTool gen);
+    void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.spi;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-
-public interface LIRGeneratorTool extends ArithmeticLIRGenerator {
-
-    TargetDescription target();
-
-    MetaAccessProvider getMetaAccess();
-
-    CodeCacheProvider getCodeCache();
-
-    ForeignCallsProvider getForeignCalls();
-
-    Value emitLoad(PlatformKind kind, Value address, Access access);
-
-    void emitStore(PlatformKind kind, Value address, Value input, Access access);
-
-    void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting);
-
-    Value emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args);
-
-    /**
-     * Checks whether the supplied constant can be used without loading it into a register for most
-     * operations, i.e., for commonly used arithmetic, logical, and comparison operations.
-     *
-     * @param c The constant to check.
-     * @return True if the constant can be used directly, false if the constant needs to be in a
-     *         register.
-     */
-    boolean canInlineConstant(Constant c);
-
-    boolean canStoreConstant(Constant c, boolean isCompressed);
-
-    RegisterAttributes attributes(Register register);
-
-    AllocatableValue newVariable(PlatformKind kind);
-
-    AllocatableValue emitMove(Value input);
-
-    void emitMove(AllocatableValue dst, Value src);
-
-    /**
-     * Emits an op that loads the address of some raw data.
-     *
-     * @param dst the variable into which the address is loaded
-     * @param data the data to be installed with the generated code
-     */
-    void emitData(AllocatableValue dst, byte[] data);
-
-    Value emitAddress(Value base, long displacement, Value index, int scale);
-
-    Value emitAddress(StackSlot slot);
-
-    void emitMembar(int barriers);
-
-    void emitUnwind(Value operand);
-
-    /**
-     * Called just before register allocation is performed on the LIR owned by this generator.
-     * Overriding implementations of this method must call the overridden method.
-     */
-    void beforeRegisterAllocation();
-
-    void emitIncomingValues(Value[] params);
-
-    /**
-     * Emits a return instruction. Implementations need to insert a move if the input is not in the
-     * correct location.
-     */
-    void emitReturn(Value input);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRTypeTool.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +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.nodes.spi;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * This interface can be used to access platform and VM specific kinds.
- */
-public interface LIRTypeTool {
-
-    PlatformKind getIntegerKind(int bits, boolean unsigned);
-
-    PlatformKind getFloatingKind(int bits);
-
-    PlatformKind getObjectKind();
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,10 +25,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This interface can be used to generate LIR for arithmetic operations where one of the operations
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,13 +26,17 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
 
 public interface NodeLIRBuilderTool extends NodeMappableLIRBuilder {
 
+    // TODO (je) remove and move into the Node
+    LIRFrameState state(DeoptimizingNode deopt);
+
     void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
 
     void emitIf(IfNode i);
@@ -50,8 +54,6 @@
 
     void visitLoopEnd(LoopEndNode i);
 
-    void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address);
-
     // These methods define the contract a runtime specific backend must provide.
 
     void visitSafepointNode(SafepointNode i);
@@ -62,7 +64,7 @@
 
     LIRGeneratorTool getLIRGeneratorTool();
 
-    void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability);
+    void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability);
 
     Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.spi;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -31,4 +32,8 @@
 public interface NodeWithState {
 
     Node asNode();
+
+    default NodeIterable<FrameState> states() {
+        return asNode().inputs().filter(FrameState.class);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Wed Apr 23 15:48:38 2014 +0200
@@ -41,12 +41,17 @@
 public interface VirtualizerTool {
 
     /**
-     * @return the {@link MetaAccessProvider} associated with the current compilation, which might
-     *         be required for creating constants, etc.
+     * @return the {@link MetaAccessProvider} associated with the current compilation.
      */
     MetaAccessProvider getMetaAccessProvider();
 
     /**
+     * @return the {@link ConstantReflectionProvider} associated with the current compilation, which
+     *         can be used to access {@link Constant}s.
+     */
+    ConstantReflectionProvider getConstantReflectionProvider();
+
+    /**
      * @return the {@link Assumptions} associated with the current compilation, which can be used to
      *         make type assumptions during virtualization.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2012, 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.type;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.spi.*;
-
-public class FloatStamp extends PrimitiveStamp {
-
-    private final double lowerBound;
-    private final double upperBound;
-    private final boolean nonNaN;
-
-    protected FloatStamp(int bits) {
-        this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false);
-    }
-
-    protected FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) {
-        super(bits);
-        this.lowerBound = lowerBound;
-        this.upperBound = upperBound;
-        this.nonNaN = nonNaN;
-    }
-
-    @Override
-    public Stamp unrestricted() {
-        return new FloatStamp(getBits());
-    }
-
-    @Override
-    public Stamp illegal() {
-        return new FloatStamp(getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, true);
-    }
-
-    @Override
-    public boolean isLegal() {
-        return lowerBound <= upperBound || !nonNaN;
-    }
-
-    @Override
-    public Kind getStackKind() {
-        if (getBits() > 32) {
-            return Kind.Double;
-        } else {
-            return Kind.Float;
-        }
-    }
-
-    @Override
-    public PlatformKind getPlatformKind(LIRTypeTool tool) {
-        return tool.getFloatingKind(getBits());
-    }
-
-    @Override
-    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
-        switch (getBits()) {
-            case 32:
-                return metaAccess.lookupJavaType(Float.TYPE);
-            case 64:
-                return metaAccess.lookupJavaType(Double.TYPE);
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    /**
-     * The (inclusive) lower bound on the value described by this stamp.
-     */
-    public double lowerBound() {
-        return lowerBound;
-    }
-
-    /**
-     * The (inclusive) upper bound on the value described by this stamp.
-     */
-    public double upperBound() {
-        return upperBound;
-    }
-
-    public boolean isNonNaN() {
-        return nonNaN;
-    }
-
-    public boolean isUnrestricted() {
-        return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
-    }
-
-    public boolean contains(double value) {
-        if (Double.isNaN(value)) {
-            return !nonNaN;
-        } else {
-            return value >= lowerBound && value <= upperBound;
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder str = new StringBuilder();
-        str.append('f');
-        str.append(getBits());
-        str.append(nonNaN ? "!" : "");
-        if (lowerBound == upperBound) {
-            str.append(" [").append(lowerBound).append(']');
-        } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) {
-            str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
-        }
-        return str.toString();
-    }
-
-    @Override
-    public Stamp meet(Stamp otherStamp) {
-        if (otherStamp == this) {
-            return this;
-        }
-        if (!(otherStamp instanceof FloatStamp)) {
-            return StampFactory.illegal(Kind.Illegal);
-        }
-        FloatStamp other = (FloatStamp) otherStamp;
-        assert getBits() == other.getBits();
-        double meetUpperBound = Math.max(upperBound, other.upperBound);
-        double meetLowerBound = Math.min(lowerBound, other.lowerBound);
-        boolean meetNonNaN = nonNaN && other.nonNaN;
-        if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) {
-            return this;
-        } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) {
-            return other;
-        } else {
-            return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN);
-        }
-    }
-
-    @Override
-    public Stamp join(Stamp otherStamp) {
-        if (otherStamp == this) {
-            return this;
-        }
-        if (!(otherStamp instanceof FloatStamp)) {
-            return StampFactory.illegal(Kind.Illegal);
-        }
-        FloatStamp other = (FloatStamp) otherStamp;
-        assert getBits() == other.getBits();
-        double joinUpperBound = Math.min(upperBound, other.upperBound);
-        double joinLowerBound = Math.max(lowerBound, other.lowerBound);
-        boolean joinNonNaN = nonNaN || other.nonNaN;
-        if (joinLowerBound == lowerBound && joinUpperBound == upperBound && joinNonNaN == nonNaN) {
-            return this;
-        } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) {
-            return other;
-        } else {
-            return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        long temp;
-        result = prime * result + super.hashCode();
-        temp = Double.doubleToLongBits(lowerBound);
-        result = prime * result + (int) (temp ^ (temp >>> 32));
-        result = prime * result + (nonNaN ? 1231 : 1237);
-        temp = Double.doubleToLongBits(upperBound);
-        result = prime * result + (int) (temp ^ (temp >>> 32));
-        return result;
-    }
-
-    @Override
-    public boolean isCompatible(Stamp stamp) {
-        if (this == stamp) {
-            return true;
-        }
-        if (stamp instanceof FloatStamp) {
-            FloatStamp other = (FloatStamp) stamp;
-            return getBits() == other.getBits();
-        }
-        return false;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) {
-            return false;
-        }
-        FloatStamp other = (FloatStamp) obj;
-        if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) {
-            return false;
-        }
-        if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) {
-            return false;
-        }
-        if (nonNaN != other.nonNaN) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public Constant asConstant() {
-        if (nonNaN && lowerBound == upperBound) {
-            switch (getBits()) {
-                case 32:
-                    return Constant.forFloat((float) lowerBound);
-                case 64:
-                    return Constant.forDouble(lowerBound);
-            }
-        }
-        return null;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2012, 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.type;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * This stamp represents the illegal type. Values with this type can not exist at run time.
- */
-public final class IllegalStamp extends Stamp {
-
-    private IllegalStamp() {
-    }
-
-    @Override
-    public Kind getStackKind() {
-        return Kind.Illegal;
-    }
-
-    @Override
-    public PlatformKind getPlatformKind(LIRTypeTool tool) {
-        throw GraalInternalError.shouldNotReachHere("illegal stamp should not reach backend");
-    }
-
-    @Override
-    public Stamp unrestricted() {
-        return this;
-    }
-
-    @Override
-    public Stamp illegal() {
-        return this;
-    }
-
-    @Override
-    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
-        throw GraalInternalError.shouldNotReachHere("illegal stamp has no Java type");
-    }
-
-    @Override
-    public Stamp meet(Stamp other) {
-        return this;
-    }
-
-    @Override
-    public Stamp join(Stamp other) {
-        return this;
-    }
-
-    @Override
-    public boolean isCompatible(Stamp stamp) {
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return "ILLEGAL";
-    }
-
-    @Override
-    public boolean isLegal() {
-        return false;
-    }
-
-    private static IllegalStamp instance = new IllegalStamp();
-
-    static IllegalStamp getInstance() {
-        return instance;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2012, 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.type;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * Describes the possible values of a {@link ValueNode} that produces an int or long result.
- *
- * The description consists of (inclusive) lower and upper bounds and up (may be set) and down
- * (always set) bit-masks.
- */
-public class IntegerStamp extends PrimitiveStamp {
-
-    private final boolean unsigned;
-
-    private final long lowerBound;
-    private final long upperBound;
-    private final long downMask;
-    private final long upMask;
-
-    public IntegerStamp(int bits, boolean unsigned, long lowerBound, long upperBound, long downMask, long upMask) {
-        super(bits);
-        this.unsigned = unsigned;
-        this.lowerBound = lowerBound;
-        this.upperBound = upperBound;
-        this.downMask = downMask;
-        this.upMask = upMask;
-        assert lowerBound >= defaultMinValue(bits, unsigned) : this;
-        assert upperBound <= defaultMaxValue(bits, unsigned) : this;
-        assert (downMask & defaultMask(bits)) == downMask : this;
-        assert (upMask & defaultMask(bits)) == upMask : this;
-    }
-
-    @Override
-    public Stamp unrestricted() {
-        return new IntegerStamp(getBits(), unsigned, defaultMinValue(getBits(), unsigned), defaultMaxValue(getBits(), unsigned), 0, defaultMask(getBits()));
-    }
-
-    @Override
-    public Stamp illegal() {
-        return new IntegerStamp(getBits(), unsigned, defaultMaxValue(getBits(), unsigned), defaultMinValue(getBits(), unsigned), defaultMask(getBits()), 0);
-    }
-
-    @Override
-    public boolean isLegal() {
-        if (unsigned) {
-            return Long.compareUnsigned(lowerBound, upperBound) <= 0;
-        } else {
-            return lowerBound <= upperBound;
-        }
-    }
-
-    @Override
-    public Kind getStackKind() {
-        if (getBits() > 32) {
-            return Kind.Long;
-        } else {
-            return Kind.Int;
-        }
-    }
-
-    @Override
-    public PlatformKind getPlatformKind(LIRTypeTool tool) {
-        return tool.getIntegerKind(getBits(), unsigned);
-    }
-
-    @Override
-    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
-        switch (getBits()) {
-            case 1:
-                assert unsigned;
-                return metaAccess.lookupJavaType(Boolean.TYPE);
-            case 8:
-                assert !unsigned;
-                return metaAccess.lookupJavaType(Byte.TYPE);
-            case 16:
-                if (unsigned) {
-                    return metaAccess.lookupJavaType(Character.TYPE);
-                } else {
-                    return metaAccess.lookupJavaType(Short.TYPE);
-                }
-            case 32:
-                assert !unsigned;
-                return metaAccess.lookupJavaType(Integer.TYPE);
-            case 64:
-                assert !unsigned;
-                return metaAccess.lookupJavaType(Long.TYPE);
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    /**
-     * Check whether the value described by this stamp is unsigned.
-     */
-    public boolean isUnsigned() {
-        return unsigned;
-    }
-
-    /**
-     * The (inclusive) lower bound on the value described by this stamp.
-     */
-    public long lowerBound() {
-        return lowerBound;
-    }
-
-    /**
-     * The (inclusive) upper bound on the value described by this stamp.
-     */
-    public long upperBound() {
-        return upperBound;
-    }
-
-    /**
-     * This bit-mask describes the bits that are always set in the value described by this stamp.
-     */
-    public long downMask() {
-        return downMask;
-    }
-
-    /**
-     * This bit-mask describes the bits that can be set in the value described by this stamp.
-     */
-    public long upMask() {
-        return upMask;
-    }
-
-    public boolean isUnrestricted() {
-        return lowerBound == defaultMinValue(getBits(), unsigned) && upperBound == defaultMaxValue(getBits(), unsigned) && downMask == 0 && upMask == defaultMask(getBits());
-    }
-
-    public boolean contains(long value) {
-        return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & defaultMask(getBits()));
-    }
-
-    public boolean isPositive() {
-        return lowerBound() >= 0;
-    }
-
-    public boolean isNegative() {
-        return upperBound() <= 0;
-    }
-
-    public boolean isStrictlyPositive() {
-        return lowerBound() > 0;
-    }
-
-    public boolean isStrictlyNegative() {
-        return upperBound() < 0;
-    }
-
-    public boolean canBePositive() {
-        return upperBound() > 0;
-    }
-
-    public boolean canBeNegative() {
-        return lowerBound() < 0;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder str = new StringBuilder();
-        str.append(unsigned ? 'u' : 'i');
-        str.append(getBits());
-        if (lowerBound == upperBound) {
-            str.append(" [").append(lowerBound).append(']');
-        } else if (lowerBound != defaultMinValue(getBits(), unsigned) || upperBound != defaultMaxValue(getBits(), unsigned)) {
-            str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
-        }
-        if (downMask != 0) {
-            str.append(" \u21ca");
-            new Formatter(str).format("%016x", downMask);
-        }
-        if (upMask != defaultMask(getBits())) {
-            str.append(" \u21c8");
-            new Formatter(str).format("%016x", upMask);
-        }
-        return str.toString();
-    }
-
-    private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) {
-        assert getBits() == other.getBits() && unsigned == other.unsigned;
-        if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0) {
-            return illegal();
-        } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) {
-            return this;
-        } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) {
-            return other;
-        } else {
-            return new IntegerStamp(getBits(), unsigned, newLowerBound, newUpperBound, newDownMask, newUpMask);
-        }
-    }
-
-    @Override
-    public Stamp meet(Stamp otherStamp) {
-        if (otherStamp == this) {
-            return this;
-        }
-        if (!(otherStamp instanceof IntegerStamp)) {
-            return StampFactory.illegal(Kind.Illegal);
-        }
-        IntegerStamp other = (IntegerStamp) otherStamp;
-        return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask);
-    }
-
-    @Override
-    public Stamp join(Stamp otherStamp) {
-        if (otherStamp == this) {
-            return this;
-        }
-        if (!(otherStamp instanceof IntegerStamp)) {
-            return StampFactory.illegal(Kind.Illegal);
-        }
-        IntegerStamp other = (IntegerStamp) otherStamp;
-        long newDownMask = downMask | other.downMask;
-        long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask;
-        return createStamp(other, Math.min(upperBound, other.upperBound), newLowerBound, newDownMask, upMask & other.upMask);
-    }
-
-    @Override
-    public boolean isCompatible(Stamp stamp) {
-        if (this == stamp) {
-            return true;
-        }
-        if (stamp instanceof IntegerStamp) {
-            IntegerStamp other = (IntegerStamp) stamp;
-            return getBits() == other.getBits() && unsigned == other.unsigned;
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + super.hashCode();
-        result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32));
-        result = prime * result + (int) (upperBound ^ (upperBound >>> 32));
-        result = prime * result + (int) (downMask ^ (downMask >>> 32));
-        result = prime * result + (int) (upMask ^ (upMask >>> 32));
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) {
-            return false;
-        }
-        IntegerStamp other = (IntegerStamp) obj;
-        if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) {
-            return false;
-        }
-        return true;
-    }
-
-    public static long defaultMask(int bits) {
-        assert 0 < bits && bits <= 64;
-        if (bits == 64) {
-            return 0xffffffffffffffffL;
-        } else {
-            return (1L << bits) - 1;
-        }
-    }
-
-    public static long defaultMinValue(int bits, boolean unsigned) {
-        if (unsigned) {
-            return 0;
-        } else {
-            return -1L << (bits - 1);
-        }
-    }
-
-    public static long defaultMaxValue(int bits, boolean unsigned) {
-        return defaultMask(unsigned ? bits : bits - 1);
-    }
-
-    public static long upMaskFor(int bits, long lowerBound, long upperBound) {
-        long mask = lowerBound | upperBound;
-        if (mask == 0) {
-            return 0;
-        } else {
-            return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & defaultMask(bits);
-        }
-    }
-
-    /**
-     * Checks if the 2 stamps represent values of the same sign. Returns true if the two stamps are
-     * both positive of null or if they are both strictly negative
-     *
-     * @return true if the two stamps are both positive of null or if they are both strictly
-     *         negative
-     */
-    public static boolean sameSign(IntegerStamp s1, IntegerStamp s2) {
-        return s1.isPositive() && s2.isPositive() || s1.isStrictlyNegative() && s2.isStrictlyNegative();
-    }
-
-    @Override
-    public Constant asConstant() {
-        if (lowerBound == upperBound) {
-            switch (getBits()) {
-                case 1:
-                    return Constant.forBoolean(lowerBound != 0);
-                case 8:
-                    return Constant.forByte((byte) lowerBound);
-                case 16:
-                    if (unsigned) {
-                        return Constant.forChar((char) lowerBound);
-                    } else {
-                        return Constant.forShort((short) lowerBound);
-                    }
-                case 32:
-                    return Constant.forInt((int) lowerBound);
-                case 64:
-                    return Constant.forLong(lowerBound);
-            }
-        }
-        return null;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,336 +0,0 @@
-/*
- * Copyright (c) 2012, 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.type;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-public class ObjectStamp extends Stamp {
-
-    private final ResolvedJavaType type;
-    private final boolean exactType;
-    private final boolean nonNull;
-    private final boolean alwaysNull;
-
-    public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
-        this.type = type;
-        this.exactType = exactType;
-        this.nonNull = nonNull;
-        this.alwaysNull = alwaysNull;
-    }
-
-    @Override
-    public Stamp unrestricted() {
-        return StampFactory.object();
-    }
-
-    @Override
-    public Stamp illegal() {
-        return new ObjectStamp(null, true, true, false);
-    }
-
-    @Override
-    public boolean isLegal() {
-        return !exactType || (type != null && (isConcreteType(type)));
-    }
-
-    @Override
-    public Kind getStackKind() {
-        return Kind.Object;
-    }
-
-    @Override
-    public PlatformKind getPlatformKind(LIRTypeTool tool) {
-        return tool.getObjectKind();
-    }
-
-    @Override
-    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
-        if (type != null) {
-            return type;
-        }
-        return metaAccess.lookupJavaType(Object.class);
-    }
-
-    public boolean nonNull() {
-        return nonNull;
-    }
-
-    public boolean alwaysNull() {
-        return alwaysNull;
-    }
-
-    public ResolvedJavaType type() {
-        return type;
-    }
-
-    public boolean isExactType() {
-        return exactType;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder str = new StringBuilder();
-        str.append('a');
-        str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.getName()).append(alwaysNull ? " NULL" : "");
-        return str.toString();
-    }
-
-    @Override
-    public Stamp meet(Stamp otherStamp) {
-        if (this == otherStamp) {
-            return this;
-        }
-        if (!(otherStamp instanceof ObjectStamp)) {
-            return StampFactory.illegal(Kind.Illegal);
-        }
-        ObjectStamp other = (ObjectStamp) otherStamp;
-        ResolvedJavaType meetType;
-        boolean meetExactType;
-        boolean meetNonNull;
-        boolean meetAlwaysNull;
-        if (other.alwaysNull) {
-            meetType = type();
-            meetExactType = exactType;
-            meetNonNull = false;
-            meetAlwaysNull = alwaysNull;
-        } else if (alwaysNull) {
-            meetType = other.type();
-            meetExactType = other.exactType;
-            meetNonNull = false;
-            meetAlwaysNull = other.alwaysNull;
-        } else {
-            meetType = meetTypes(type(), other.type());
-            meetExactType = exactType && other.exactType;
-            if (meetExactType && type != null && other.type != null) {
-                // meeting two valid exact types may result in a non-exact type
-                meetExactType = Objects.equals(meetType, type) && Objects.equals(meetType, other.type);
-            }
-            meetNonNull = nonNull && other.nonNull;
-            meetAlwaysNull = false;
-        }
-
-        if (Objects.equals(meetType, type) && meetExactType == exactType && meetNonNull == nonNull && meetAlwaysNull == alwaysNull) {
-            return this;
-        } else if (Objects.equals(meetType, other.type) && meetExactType == other.exactType && meetNonNull == other.nonNull && meetAlwaysNull == other.alwaysNull) {
-            return other;
-        } else {
-            return new ObjectStamp(meetType, meetExactType, meetNonNull, meetAlwaysNull);
-        }
-    }
-
-    @Override
-    public Stamp join(Stamp otherStamp) {
-        return join0(otherStamp, false);
-    }
-
-    @Override
-    public boolean isCompatible(Stamp other) {
-        if (this == other) {
-            return true;
-        }
-        if (other instanceof ObjectStamp) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Returns the stamp representing the type of this stamp after a cast to the type represented by
-     * the {@code to} stamp. While this is very similar to a {@link #join} operation, in the case
-     * where both types are not obviously related, the cast operation will prefer the type of the
-     * {@code to} stamp. This is necessary as long as ObjectStamps are not able to accurately
-     * represent intersection types.
-     *
-     * For example when joining the {@link RandomAccess} type with the {@link AbstractList} type,
-     * without intersection types, this would result in the most generic type ({@link Object} ). For
-     * this reason, in some cases a {@code castTo} operation is preferable in order to keep at least
-     * the {@link AbstractList} type.
-     *
-     * @param to the stamp this stamp should be casted to
-     * @return This stamp casted to the {@code to} stamp
-     */
-    public Stamp castTo(ObjectStamp to) {
-        return join0(to, true);
-    }
-
-    private Stamp join0(Stamp otherStamp, boolean castToOther) {
-        if (this == otherStamp) {
-            return this;
-        }
-        if (!(otherStamp instanceof ObjectStamp)) {
-            return StampFactory.illegal(Kind.Illegal);
-        }
-        ObjectStamp other = (ObjectStamp) otherStamp;
-        if (!isLegal()) {
-            return this;
-        } else if (!other.isLegal()) {
-            return other;
-        }
-
-        ResolvedJavaType joinType;
-        boolean joinAlwaysNull = alwaysNull || other.alwaysNull;
-        boolean joinNonNull = nonNull || other.nonNull;
-        boolean joinExactType = exactType || other.exactType;
-        if (Objects.equals(type, other.type)) {
-            joinType = type;
-        } else if (type == null && other.type == null) {
-            joinType = null;
-        } else if (type == null) {
-            joinType = other.type;
-        } else if (other.type == null) {
-            joinType = type;
-        } else {
-            // both types are != null and different
-            if (type.isAssignableFrom(other.type)) {
-                joinType = other.type;
-                if (exactType) {
-                    joinAlwaysNull = true;
-                }
-            } else if (other.type.isAssignableFrom(type)) {
-                joinType = type;
-                if (other.exactType) {
-                    joinAlwaysNull = true;
-                }
-            } else {
-                if (castToOther) {
-                    joinType = other.type;
-                    joinExactType = other.exactType;
-                } else {
-                    joinType = null;
-                }
-                if (joinExactType || (!type.isInterface() && !other.type.isInterface())) {
-                    joinAlwaysNull = true;
-                }
-            }
-        }
-        if (joinAlwaysNull) {
-            joinType = null;
-            joinExactType = false;
-        }
-        if (joinExactType && joinType == null) {
-            return StampFactory.illegal(Kind.Object);
-        }
-        if (joinAlwaysNull && joinNonNull) {
-            return StampFactory.illegal(Kind.Object);
-        } else if (joinExactType && !isConcreteType(joinType)) {
-            return StampFactory.illegal(Kind.Object);
-        }
-        if (Objects.equals(joinType, type) && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) {
-            return this;
-        } else if (Objects.equals(joinType, other.type) && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) {
-            return other;
-        } else {
-            return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
-        }
-    }
-
-    public static boolean isConcreteType(ResolvedJavaType type) {
-        return !(Modifier.isAbstract(type.getModifiers()) && !type.isArray());
-    }
-
-    private static ResolvedJavaType meetTypes(ResolvedJavaType a, ResolvedJavaType b) {
-        if (Objects.equals(a, b)) {
-            return a;
-        } else if (a == null || b == null) {
-            return null;
-        } else {
-            return a.findLeastCommonAncestor(b);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + (exactType ? 1231 : 1237);
-        result = prime * result + (nonNull ? 1231 : 1237);
-        result = prime * result + (alwaysNull ? 1231 : 1237);
-        result = prime * result + ((type == null) ? 0 : type.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        ObjectStamp other = (ObjectStamp) obj;
-        if (exactType != other.exactType || nonNull != other.nonNull || alwaysNull != other.alwaysNull) {
-            return false;
-        }
-        if (type == null) {
-            if (other.type != null) {
-                return false;
-            }
-        } else if (!type.equals(other.type)) {
-            return false;
-        }
-        return true;
-    }
-
-    public static boolean isObjectAlwaysNull(ValueNode node) {
-        return isObjectAlwaysNull(node.stamp());
-    }
-
-    public static boolean isObjectAlwaysNull(Stamp stamp) {
-        return (stamp instanceof ObjectStamp && ((ObjectStamp) stamp).isLegal() && ((ObjectStamp) stamp).alwaysNull());
-    }
-
-    public static boolean isObjectNonNull(ValueNode node) {
-        return isObjectNonNull(node.stamp());
-    }
-
-    public static boolean isObjectNonNull(Stamp stamp) {
-        return stamp instanceof ObjectStamp && ((ObjectStamp) stamp).isLegal() && ((ObjectStamp) stamp).nonNull();
-    }
-
-    public static ResolvedJavaType typeOrNull(ValueNode node) {
-        return typeOrNull(node.stamp());
-    }
-
-    public static ResolvedJavaType typeOrNull(Stamp stamp) {
-        if (stamp instanceof ObjectStamp) {
-            return ((ObjectStamp) stamp).type();
-        }
-        return null;
-    }
-
-    public static boolean isExactType(ValueNode node) {
-        return isExactType(node.stamp());
-    }
-
-    public static boolean isExactType(Stamp stamp) {
-        if (stamp instanceof ObjectStamp) {
-            return ((ObjectStamp) stamp).isExactType();
-        }
-        return false;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +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.nodes.type;
-
-import com.oracle.graal.nodes.*;
-
-/**
- * Describes the possible values of a {@link ValueNode} that produces a primitive value as result.
- */
-public abstract class PrimitiveStamp extends Stamp {
-
-    private final int bits;
-
-    protected PrimitiveStamp(int bits) {
-        this.bits = bits;
-    }
-
-    /**
-     * The width in bits of the value described by this stamp.
-     */
-    public int getBits() {
-        return bits;
-    }
-
-    public static int getBits(Stamp stamp) {
-        if (stamp instanceof PrimitiveStamp) {
-            return ((PrimitiveStamp) stamp).getBits();
-        } else {
-            return 0;
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + bits;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof PrimitiveStamp) {
-            PrimitiveStamp other = (PrimitiveStamp) obj;
-            return bits == other.bits;
-        }
-        return false;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2011, 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.type;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * A stamp is the basis for a type system over the nodes in a graph.
- */
-public abstract class Stamp {
-
-    protected Stamp() {
-    }
-
-    /**
-     * Returns the type of the stamp, guaranteed to be non-null. In some cases, this requires the
-     * lookup of class meta data, therefore the {@link MetaAccessProvider} is mandatory.
-     */
-    public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess);
-
-    public boolean alwaysDistinct(Stamp other) {
-        return !join(other).isLegal();
-    }
-
-    /**
-     * Gets a Java {@link Kind} that can be used to store a value of this stamp on the Java bytecode
-     * stack. Returns {@link Kind#Illegal} if a value of this stamp can not be stored on the
-     * bytecode stack.
-     */
-    public abstract Kind getStackKind();
-
-    /**
-     * Gets a platform dependent {@link PlatformKind} that can be used to store a value of this
-     * stamp.
-     */
-    public abstract PlatformKind getPlatformKind(LIRTypeTool tool);
-
-    /**
-     * Returns the union of this stamp and the given stamp. Typically used to create stamps for
-     * {@link ValuePhiNode}s.
-     *
-     * @param other The stamp that will enlarge this stamp.
-     * @return The union of this stamp and the given stamp.
-     */
-    public abstract Stamp meet(Stamp other);
-
-    /**
-     * Returns the intersection of this stamp and the given stamp.
-     *
-     * @param other The stamp that will tighten this stamp.
-     * @return The intersection of this stamp and the given stamp.
-     */
-    public abstract Stamp join(Stamp other);
-
-    /**
-     * Returns a stamp of the same kind, but allowing the full value range of the kind.
-     *
-     * {@link #unrestricted()} is the neutral element of the {@link #join(Stamp)} operation.
-     */
-    public abstract Stamp unrestricted();
-
-    /**
-     * Returns a stamp of the same kind, but with no allowed values.
-     *
-     * {@link #illegal()} is the neutral element of the {@link #meet(Stamp)} operation.
-     */
-    public abstract Stamp illegal();
-
-    /**
-     * Test whether two stamps have the same base type.
-     */
-    public abstract boolean isCompatible(Stamp other);
-
-    /**
-     * Test whether this stamp has legal values.
-     */
-    public abstract boolean isLegal();
-
-    /**
-     * If this stamp represents a single value, the methods returns this single value. It returns
-     * null otherwise.
-     *
-     * @return the constant corresponding to the single value of this stamp and null if this stamp
-     *         can represent less or more than one value.
-     */
-    public Constant asConstant() {
-        return null;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,254 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.type;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-
-public class StampFactory {
-
-    // JaCoCo Exclude
-
-    private static final Stamp[] stampCache = new Stamp[Kind.values().length];
-    private static final Stamp[] illegalStampCache = new Stamp[Kind.values().length];
-    private static final Stamp objectStamp = new ObjectStamp(null, false, false, false);
-    private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false);
-    private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true);
-    private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false);
-    private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
-
-    private static void setCache(Kind kind, Stamp stamp) {
-        stampCache[kind.ordinal()] = stamp;
-    }
-
-    private static void setIntCache(Kind kind) {
-        int bits = kind.getStackKind().getBitCount();
-        long mask;
-        if (kind.isUnsigned()) {
-            mask = IntegerStamp.defaultMask(kind.getBitCount());
-        } else {
-            mask = IntegerStamp.defaultMask(bits);
-        }
-        setCache(kind, new IntegerStamp(bits, false, kind.getMinValue(), kind.getMaxValue(), 0, mask));
-    }
-
-    private static void setFloatCache(Kind kind) {
-        setCache(kind, new FloatStamp(kind.getBitCount()));
-    }
-
-    static {
-        setIntCache(Kind.Boolean);
-        setIntCache(Kind.Byte);
-        setIntCache(Kind.Short);
-        setIntCache(Kind.Char);
-        setIntCache(Kind.Int);
-        setIntCache(Kind.Long);
-
-        setFloatCache(Kind.Float);
-        setFloatCache(Kind.Double);
-
-        setCache(Kind.Object, objectStamp);
-        setCache(Kind.Void, VoidStamp.getInstance());
-
-        for (Kind k : Kind.values()) {
-            if (stampCache[k.ordinal()] != null) {
-                illegalStampCache[k.ordinal()] = stampCache[k.ordinal()].illegal();
-            } else {
-                illegalStampCache[k.ordinal()] = IllegalStamp.getInstance();
-            }
-        }
-    }
-
-    /**
-     * Return a stamp for a Java kind, as it would be represented on the bytecode stack.
-     */
-    public static Stamp forKind(Kind kind) {
-        assert stampCache[kind.ordinal()] != null : "unexpected forKind(" + kind + ")";
-        return stampCache[kind.ordinal()];
-    }
-
-    /**
-     * Return the stamp for the {@code void} type. This will return a singleton instance than can be
-     * compared using {@code ==}.
-     */
-    public static Stamp forVoid() {
-        return VoidStamp.getInstance();
-    }
-
-    /**
-     * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an
-     * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated.
-     */
-    public static Stamp forNodeIntrinsic() {
-        return nodeIntrinsicStamp;
-    }
-
-    public static Stamp intValue() {
-        return forKind(Kind.Int);
-    }
-
-    public static Stamp positiveInt() {
-        return positiveInt;
-    }
-
-    public static Stamp illegal() {
-        return illegal(Kind.Illegal);
-    }
-
-    public static Stamp illegal(Kind kind) {
-        return illegalStampCache[kind.ordinal()];
-    }
-
-    public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) {
-        return new IntegerStamp(kind.getBitCount(), kind.isUnsigned(), lowerBound, upperBound, downMask, upMask);
-    }
-
-    public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound) {
-        return forInteger(kind.getBitCount(), kind.isUnsigned(), lowerBound, upperBound);
-    }
-
-    public static IntegerStamp forInteger(int bits, boolean unsigned) {
-        return new IntegerStamp(bits, unsigned, IntegerStamp.defaultMinValue(bits, unsigned), IntegerStamp.defaultMaxValue(bits, unsigned), 0, IntegerStamp.defaultMask(bits));
-    }
-
-    public static IntegerStamp forInteger(int bits, boolean unsigned, long lowerBound, long upperBound) {
-        long defaultMask = IntegerStamp.defaultMask(bits);
-        if (lowerBound == upperBound) {
-            return new IntegerStamp(bits, unsigned, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask);
-        }
-        final long downMask;
-        final long upMask;
-        if (lowerBound >= 0) {
-            int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound);
-            long differentBits = lowerBound ^ upperBound;
-            int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros);
-
-            upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount);
-            downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount));
-        } else {
-            if (upperBound >= 0) {
-                upMask = defaultMask;
-                downMask = 0;
-            } else {
-                int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound);
-                long differentBits = lowerBound ^ upperBound;
-                int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes);
-
-                upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes);
-                downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes);
-            }
-        }
-        return new IntegerStamp(bits, unsigned, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask);
-    }
-
-    public static FloatStamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
-        assert kind.isNumericFloat();
-        return new FloatStamp(kind.getBitCount(), lowerBound, upperBound, nonNaN);
-    }
-
-    public static Stamp forConstant(Constant value) {
-        Kind kind = value.getKind();
-        switch (kind) {
-            case Boolean:
-            case Byte:
-            case Char:
-            case Short:
-            case Int:
-            case Long:
-                long mask = value.asLong() & IntegerStamp.defaultMask(kind.getBitCount());
-                return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), mask, mask);
-            case Float:
-                return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
-            case Double:
-                return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
-            case Illegal:
-                return illegal(Kind.Illegal);
-            case Object:
-                if (value.isNull()) {
-                    return alwaysNull();
-                } else {
-                    return objectNonNull();
-                }
-            default:
-                throw new GraalInternalError("unexpected kind: %s", kind);
-        }
-    }
-
-    public static Stamp forConstant(Constant value, MetaAccessProvider metaAccess) {
-        assert value.getKind() == Kind.Object;
-        if (value.getKind() == Kind.Object) {
-            ResolvedJavaType type = value.isNull() ? null : metaAccess.lookupJavaType(value);
-            return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull());
-        } else {
-            throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.getKind());
-        }
-    }
-
-    public static Stamp object() {
-        return objectStamp;
-    }
-
-    public static Stamp objectNonNull() {
-        return objectNonNullStamp;
-    }
-
-    public static Stamp alwaysNull() {
-        return objectAlwaysNullStamp;
-    }
-
-    public static Stamp declared(ResolvedJavaType type) {
-        return declared(type, false);
-    }
-
-    public static Stamp declaredNonNull(ResolvedJavaType type) {
-        return declared(type, true);
-    }
-
-    public static Stamp declared(ResolvedJavaType type, boolean nonNull) {
-        return object(type, false, nonNull);
-    }
-
-    public static Stamp object(ResolvedJavaType type, boolean exactType, boolean nonNull) {
-        assert type != null;
-        assert type.getKind() == Kind.Object;
-        ResolvedJavaType exact = type.asExactType();
-        if (exact != null) {
-            assert !exactType || type.equals(exact);
-            return new ObjectStamp(exact, true, nonNull, false);
-        } else {
-            return new ObjectStamp(type, exactType, nonNull, false);
-        }
-    }
-
-    public static Stamp exactNonNull(ResolvedJavaType type) {
-        if (ObjectStamp.isConcreteType(type)) {
-            return new ObjectStamp(type, true, true, false);
-        } else {
-            return illegal(Kind.Object);
-        }
-    }
-
-    public static Stamp exact(ResolvedJavaType type) {
-        return new ObjectStamp(type, true, false, false);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampProvider.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.type;
-
-public interface StampProvider {
-
-    Stamp stamp();
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,8 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 
 /**
@@ -36,9 +38,9 @@
         if (stamp instanceof IntegerStamp) {
             IntegerStamp integerStamp = (IntegerStamp) stamp;
             int bits = integerStamp.getBits();
-            if (integerStamp.lowerBound() != IntegerStamp.defaultMinValue(bits, false)) {
+            if (integerStamp.lowerBound() != IntegerStamp.defaultMinValue(bits)) {
                 // TODO(ls) check if the mask calculation is correct...
-                return StampFactory.forInteger(bits, false, -integerStamp.upperBound(), -integerStamp.lowerBound());
+                return StampFactory.forInteger(bits, -integerStamp.upperBound(), -integerStamp.lowerBound());
             }
         } else if (stamp instanceof FloatStamp) {
             FloatStamp floatStamp = (FloatStamp) stamp;
@@ -53,8 +55,7 @@
             IntegerStamp integerStamp = (IntegerStamp) stamp;
             int bits = integerStamp.getBits();
             long defaultMask = IntegerStamp.defaultMask(bits);
-            return new IntegerStamp(bits, integerStamp.isUnsigned(), ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) &
-                            defaultMask);
+            return new IntegerStamp(bits, ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask);
         }
         return stamp.unrestricted();
     }
@@ -95,45 +96,36 @@
     }
 
     public static Stamp div(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.getBits() == stamp2.getBits() && stamp1.isUnsigned() == stamp2.isUnsigned();
+        assert stamp1.getBits() == stamp2.getBits();
         if (stamp2.isStrictlyPositive()) {
             long lowerBound = stamp1.lowerBound() / stamp2.lowerBound();
             long upperBound = stamp1.upperBound() / stamp2.lowerBound();
-            return StampFactory.forInteger(stamp1.getBits(), stamp1.isUnsigned(), lowerBound, upperBound);
+            return StampFactory.forInteger(stamp1.getBits(), lowerBound, upperBound);
         }
         return stamp1.unrestricted();
     }
 
-    private static boolean addOverflowsPositively(long x, long y, int bits, boolean unsigned) {
+    private static boolean addOverflowsPositively(long x, long y, int bits) {
         long result = x + y;
         if (bits == 64) {
-            if (unsigned) {
-                return ((x | y) & ~result) < 0;
-            } else {
-                return (~x & ~y & result) < 0;
-            }
+            return (~x & ~y & result) < 0;
         } else {
-            return result > IntegerStamp.defaultMaxValue(bits, unsigned);
+            return result > IntegerStamp.defaultMaxValue(bits);
         }
     }
 
-    private static boolean addOverflowsNegatively(long x, long y, int bits, boolean unsigned) {
-        if (unsigned) {
-            return false;
-        }
-
+    private static boolean addOverflowsNegatively(long x, long y, int bits) {
         long result = x + y;
         if (bits == 64) {
             return (x & y & ~result) < 0;
         } else {
-            return result < IntegerStamp.defaultMinValue(bits, unsigned);
+            return result < IntegerStamp.defaultMinValue(bits);
         }
     }
 
     public static IntegerStamp add(IntegerStamp stamp1, IntegerStamp stamp2) {
         int bits = stamp1.getBits();
-        boolean unsigned = stamp1.isUnsigned();
-        assert bits == stamp2.getBits() && unsigned == stamp2.isUnsigned();
+        assert bits == stamp2.getBits();
 
         if (stamp1.isUnrestricted()) {
             return stamp1;
@@ -151,30 +143,23 @@
 
         long lowerBound;
         long upperBound;
-        boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), bits, unsigned);
-        boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), bits, unsigned);
-        boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), bits, unsigned);
-        boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), bits, unsigned);
+        boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), bits);
+        boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), bits);
+        boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), bits);
+        boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), bits);
         if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsPositively && upperOverflowsPositively)) {
-            lowerBound = IntegerStamp.defaultMinValue(bits, unsigned);
-            upperBound = IntegerStamp.defaultMaxValue(bits, unsigned);
+            lowerBound = IntegerStamp.defaultMinValue(bits);
+            upperBound = IntegerStamp.defaultMaxValue(bits);
         } else {
-            lowerBound = (stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask;
-            upperBound = (stamp1.upperBound() + stamp2.upperBound()) & defaultMask;
-            if (!unsigned) {
-                lowerBound = SignExtendNode.signExtend(lowerBound, bits);
-                upperBound = SignExtendNode.signExtend(upperBound, bits);
-            }
+            lowerBound = SignExtendNode.signExtend((stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask, bits);
+            upperBound = SignExtendNode.signExtend((stamp1.upperBound() + stamp2.upperBound()) & defaultMask, bits);
         }
-        IntegerStamp limit = StampFactory.forInteger(bits, unsigned, lowerBound, upperBound);
+        IntegerStamp limit = StampFactory.forInteger(bits, lowerBound, upperBound);
         newUpMask &= limit.upMask();
-        upperBound &= newUpMask;
-        if (!unsigned) {
-            upperBound = SignExtendNode.signExtend(upperBound, bits);
-        }
+        upperBound = SignExtendNode.signExtend(upperBound & newUpMask, bits);
         newDownMask |= limit.downMask();
         lowerBound |= newDownMask;
-        return new IntegerStamp(bits, unsigned, lowerBound, upperBound, newDownMask, newUpMask);
+        return new IntegerStamp(bits, lowerBound, upperBound, newDownMask, newUpMask);
     }
 
     public static Stamp sub(IntegerStamp stamp1, IntegerStamp stamp2) {
@@ -195,11 +180,11 @@
             upperBound = upMask;
         } else {
             lowerBound = downMask | (-1L << (bits - 1));
-            upperBound = IntegerStamp.defaultMaxValue(bits, false) & upMask;
+            upperBound = IntegerStamp.defaultMaxValue(bits) & upMask;
         }
         lowerBound = IntegerConvertNode.convert(lowerBound, bits, false);
         upperBound = IntegerConvertNode.convert(upperBound, bits, false);
-        return new IntegerStamp(bits, false, lowerBound, upperBound, downMask, upMask);
+        return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask);
     }
 
     public static Stamp and(Stamp stamp1, Stamp stamp2) {
@@ -265,7 +250,7 @@
                     lowerBound = value.lowerBound() >>> shiftCount;
                     upperBound = value.upperBound() >>> shiftCount;
                 }
-                return new IntegerStamp(bits, value.isUnsigned(), lowerBound, upperBound, downMask, upMask);
+                return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask);
             }
         }
         long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound());
@@ -312,17 +297,7 @@
             long downMask = SignExtendNode.signExtend(inputStamp.downMask(), inputBits) & defaultMask;
             long upMask = SignExtendNode.signExtend(inputStamp.upMask(), inputBits) & defaultMask;
 
-            long lowerBound;
-            long upperBound;
-            if (inputStamp.isUnsigned()) {
-                lowerBound = SignExtendNode.signExtend(inputStamp.lowerBound(), inputBits) & defaultMask;
-                upperBound = SignExtendNode.signExtend(inputStamp.upperBound(), inputBits) & defaultMask;
-            } else {
-                lowerBound = inputStamp.lowerBound();
-                upperBound = inputStamp.upperBound();
-            }
-
-            return new IntegerStamp(resultBits, inputStamp.isUnsigned(), lowerBound, upperBound, downMask, upMask);
+            return new IntegerStamp(resultBits, inputStamp.lowerBound(), inputStamp.upperBound(), downMask, upMask);
         } else {
             return input.illegal();
         }
@@ -346,7 +321,7 @@
             long lowerBound = ZeroExtendNode.zeroExtend(inputStamp.lowerBound(), inputBits);
             long upperBound = ZeroExtendNode.zeroExtend(inputStamp.upperBound(), inputBits);
 
-            return new IntegerStamp(resultBits, inputStamp.isUnsigned(), lowerBound, upperBound, downMask, upMask);
+            return new IntegerStamp(resultBits, lowerBound, upperBound, downMask, upMask);
         } else {
             return input.illegal();
         }
@@ -355,7 +330,6 @@
     public static Stamp narrowingConversion(Stamp input, int resultBits) {
         if (input instanceof IntegerStamp) {
             IntegerStamp inputStamp = (IntegerStamp) input;
-            boolean unsigned = inputStamp.isUnsigned();
             int inputBits = inputStamp.getBits();
             assert resultBits <= inputBits;
             if (resultBits == inputBits) {
@@ -363,28 +337,24 @@
             }
 
             final long upperBound;
-            if (inputStamp.lowerBound() < IntegerStamp.defaultMinValue(resultBits, unsigned)) {
-                upperBound = IntegerStamp.defaultMaxValue(resultBits, unsigned);
+            if (inputStamp.lowerBound() < IntegerStamp.defaultMinValue(resultBits)) {
+                upperBound = IntegerStamp.defaultMaxValue(resultBits);
             } else {
-                upperBound = saturate(inputStamp.upperBound(), resultBits, unsigned);
+                upperBound = saturate(inputStamp.upperBound(), resultBits);
             }
             final long lowerBound;
-            if (inputStamp.upperBound() > IntegerStamp.defaultMaxValue(resultBits, unsigned)) {
-                lowerBound = IntegerStamp.defaultMinValue(resultBits, unsigned);
+            if (inputStamp.upperBound() > IntegerStamp.defaultMaxValue(resultBits)) {
+                lowerBound = IntegerStamp.defaultMinValue(resultBits);
             } else {
-                lowerBound = saturate(inputStamp.lowerBound(), resultBits, unsigned);
+                lowerBound = saturate(inputStamp.lowerBound(), resultBits);
             }
 
             long defaultMask = IntegerStamp.defaultMask(resultBits);
             long newDownMask = inputStamp.downMask() & defaultMask;
             long newUpMask = inputStamp.upMask() & defaultMask;
-            long newLowerBound = (lowerBound | newDownMask) & newUpMask;
-            long newUpperBound = (upperBound | newDownMask) & newUpMask;
-            if (!unsigned) {
-                newLowerBound = SignExtendNode.signExtend(newLowerBound, resultBits);
-                newUpperBound = SignExtendNode.signExtend(newUpperBound, resultBits);
-            }
-            return new IntegerStamp(resultBits, unsigned, newLowerBound, newUpperBound, newDownMask, newUpMask);
+            long newLowerBound = SignExtendNode.signExtend((lowerBound | newDownMask) & newUpMask, resultBits);
+            long newUpperBound = SignExtendNode.signExtend((upperBound | newDownMask) & newUpMask, resultBits);
+            return new IntegerStamp(resultBits, newLowerBound, newUpperBound, newDownMask, newUpMask);
         } else {
             return input.illegal();
         }
@@ -409,7 +379,7 @@
         long intMask = IntegerStamp.defaultMask(32);
         long newUpMask = signExtend(fromStamp.upMask() & defaultMask, toKind) & intMask;
         long newDownMask = signExtend(fromStamp.downMask() & defaultMask, toKind) & intMask;
-        return new IntegerStamp(toKind.getStackKind().getBitCount(), false, (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask);
+        return new IntegerStamp(toKind.getStackKind().getBitCount(), (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask);
     }
 
     private static long signExtend(long value, Kind valueKind) {
@@ -420,13 +390,13 @@
         }
     }
 
-    private static long saturate(long v, int bits, boolean unsigned) {
+    private static long saturate(long v, int bits) {
         if (bits < 64) {
-            long max = IntegerStamp.defaultMaxValue(bits, unsigned);
+            long max = IntegerStamp.defaultMaxValue(bits);
             if (v > max) {
                 return max;
             }
-            long min = IntegerStamp.defaultMinValue(bits, unsigned);
+            long min = IntegerStamp.defaultMinValue(bits);
             if (v < min) {
                 return min;
             }
@@ -471,15 +441,121 @@
                 }
                 // If the test succeeds then this proves that n is at greater than c so the bounds
                 // are [c+1..-n.upperBound)].
-                return StampFactory.forInteger(x.getBits(), false, x.lowerBound() + 1, y.upperBound());
+                return StampFactory.forInteger(x.getBits(), x.lowerBound() + 1, y.upperBound());
             }
             return null;
         }
         // n <| c, where c is a strictly positive constant
         if (y.lowerBound() == y.upperBound() && y.isStrictlyPositive()) {
             // The test proves that n is positive and less than c, [0..c-1]
-            return StampFactory.forInteger(y.getBits(), false, 0, y.lowerBound() - 1);
+            return StampFactory.forInteger(y.getBits(), 0, y.lowerBound() - 1);
         }
         return null;
     }
+
+    /**
+     * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object
+     * value which is known to be always null.
+     *
+     * @param node the node to check
+     * @return true if this node represents a legal object value which is known to be always null
+     */
+    public static boolean isObjectAlwaysNull(ValueNode node) {
+        return isObjectAlwaysNull(node.stamp());
+    }
+
+    /**
+     * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object
+     * stamp whose values are known to be always null.
+     *
+     * @param stamp the stamp to check
+     * @return true if this stamp represents a legal object stamp whose values are known to be
+     *         always null
+     */
+    public static boolean isObjectAlwaysNull(Stamp stamp) {
+        if (stamp instanceof ObjectStamp && stamp.isLegal()) {
+            return ((ObjectStamp) stamp).alwaysNull();
+        }
+        return false;
+    }
+
+    /**
+     * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object
+     * value which is known to never be null.
+     *
+     * @param node the node to check
+     * @return true if this node represents a legal object value which is known to never be null
+     */
+    public static boolean isObjectNonNull(ValueNode node) {
+        return isObjectNonNull(node.stamp());
+    }
+
+    /**
+     * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object
+     * stamp whose values known to be always null.
+     *
+     * @param stamp the stamp to check
+     * @return true if this stamp represents a legal object stamp whose values are known to be
+     *         always null
+     */
+    public static boolean isObjectNonNull(Stamp stamp) {
+        if (stamp instanceof ObjectStamp && stamp.isLegal()) {
+            return ((ObjectStamp) stamp).nonNull();
+        }
+        return false;
+    }
+
+    /**
+     * Returns the {@linkplain ResolvedJavaType java type} this {@linkplain ValueNode} has if it is
+     * a {@linkplain Stamp#isLegal() legal} Object value.
+     *
+     * @param node the node to check
+     * @return the javat type this value has if it is a legal Object type, null otherwise
+     */
+    public static ResolvedJavaType typeOrNull(ValueNode node) {
+        return typeOrNull(node.stamp());
+    }
+
+    /**
+     * Returns the {@linkplain ResolvedJavaType java type} this {@linkplain Stamp} has if it is a
+     * {@linkplain Stamp#isLegal() legal} Object stamp.
+     *
+     * @param stamp the stamp to check
+     * @return the java type this stamp has if it is a legal Object stamp, null otherwise
+     */
+    public static ResolvedJavaType typeOrNull(Stamp stamp) {
+        if (stamp instanceof ObjectStamp && stamp.isLegal()) {
+            return ((ObjectStamp) stamp).type();
+        }
+        return null;
+    }
+
+    /**
+     * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object
+     * value whose java type is known exactly. If this method returns true then the
+     * {@linkplain ResolvedJavaType java type} returned by {@link #typeOrNull(ValueNode)} is the
+     * concrete dynamic/runtime java type of this value.
+     *
+     * @param node the node to check
+     * @return true if this node represents a legal object value whose java type is known exactly
+     */
+    public static boolean isExactType(ValueNode node) {
+        return isExactType(node.stamp());
+    }
+
+    /**
+     * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object
+     * stamp whose {@linkplain ResolvedJavaType java type} is known exactly. If this method returns
+     * true then the java type returned by {@link #typeOrNull(Stamp)} is the only concrete
+     * dynamic/runtime java type possible for values of this stamp.
+     *
+     * @param stamp the stamp to check
+     * @return true if this node represents a legal object stamp whose java type is known exactly
+     */
+    public static boolean isExactType(Stamp stamp) {
+        if (stamp instanceof ObjectStamp && stamp.isLegal()) {
+            return ((ObjectStamp) stamp).isExactType();
+        }
+        return false;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/VoidStamp.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +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.nodes.type;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * Singleton stamp representing the value of type {@code void}.
- */
-public final class VoidStamp extends Stamp {
-
-    private VoidStamp() {
-    }
-
-    @Override
-    public Stamp unrestricted() {
-        return this;
-    }
-
-    @Override
-    public Kind getStackKind() {
-        return Kind.Void;
-    }
-
-    @Override
-    public PlatformKind getPlatformKind(LIRTypeTool tool) {
-        throw GraalInternalError.shouldNotReachHere("void stamp has no value");
-    }
-
-    @Override
-    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
-        return metaAccess.lookupJavaType(Void.TYPE);
-    }
-
-    @Override
-    public String toString() {
-        return "void";
-    }
-
-    @Override
-    public boolean alwaysDistinct(Stamp other) {
-        return this != other;
-    }
-
-    @Override
-    public Stamp meet(Stamp other) {
-        if (other instanceof IllegalStamp) {
-            return other.join(this);
-        }
-        if (this == other) {
-            return this;
-        }
-        return StampFactory.illegal(Kind.Illegal);
-    }
-
-    @Override
-    public Stamp join(Stamp other) {
-        if (other instanceof IllegalStamp) {
-            return other.join(this);
-        }
-        if (this == other) {
-            return this;
-        }
-        return StampFactory.illegal(Kind.Illegal);
-    }
-
-    @Override
-    public boolean isCompatible(Stamp stamp) {
-        return this == stamp;
-    }
-
-    @Override
-    public Stamp illegal() {
-        // there is no illegal void stamp
-        return this;
-    }
-
-    @Override
-    public boolean isLegal() {
-        return true;
-    }
-
-    private static VoidStamp instance = new VoidStamp();
-
-    static VoidStamp getInstance() {
-        return instance;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,262 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.util;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-public final class ComputeImmediateDominator {
-
-    private final MergeNode dominated;
-    private final Queue<FixedNode> toExplore;
-    private final Queue<FixedNode> speculativeExplore;
-    private final NodeMap<DominatorInfo> infoMap;
-    private final DominatorInfo fullInfo;
-    private FixedNode dominator;
-    private int nextBit = 1;
-
-    public ComputeImmediateDominator(MergeNode dominated) {
-        this.dominated = dominated;
-        this.toExplore = new LinkedList<>();
-        this.speculativeExplore = new LinkedList<>();
-        this.infoMap = dominated.graph().createNodeMap();
-        fullInfo = new DominatorInfo(dominated, true);
-
-        this.processMerge(dominated, fullInfo);
-        if (toExplore.size() == 1) {
-            dominator = toExplore.remove();
-        }
-    }
-
-    public FixedNode compute() {
-        try {
-            while (dominator == null && (!toExplore.isEmpty() || !speculativeExplore.isEmpty())) {
-                while (!toExplore.isEmpty()) {
-                    exploreUp(toExplore.remove());
-                    if (dominator != null) {
-                        return dominator;
-                    }
-                }
-                exploreUp(speculativeExplore.remove());
-            }
-            return dominator;
-        } catch (Throwable t) {
-            throw new GraalInternalError(t).addContext("Could not find a dominator").addContext(dominated);
-        }
-    }
-
-    private void exploreUp(FixedNode from) {
-        FixedNode p = from;
-        DominatorInfo info = infoMap.get(from);
-        if (info.isExplored()) {
-            return;
-        }
-        // TTY.println("exploreUp(" + from + ") with " + info);
-        info.setExplored();
-        while (p != null) {
-            if (p instanceof MergeNode) {
-                processMerge((MergeNode) p, info);
-                p = null;
-            } else if (p instanceof ControlSplitNode) {
-                processControlSplit((ControlSplitNode) p, info);
-                p = null;
-            } else {
-                p = (FixedNode) p.predecessor();
-            }
-        }
-    }
-
-    private void processControlSplit(ControlSplitNode cs, DominatorInfo info) {
-        // TTY.println("processControlSplit(" + cs + ", " + info + ")");
-        DominatorInfo csInfo = infoMap.get(cs);
-        if (csInfo == null) {
-            csInfo = new DominatorInfo(cs, false);
-            infoMap.set(cs, csInfo);
-        }
-        csInfo.add(info);
-        FixedNode next = (FixedNode) cs.predecessor();
-        if (checkControlSplitInfo(csInfo)) {
-            return;
-        }
-        if (csInfo.isExplored()) {
-            // TTY.println("  Already explored, propagate update");
-            propagateUpdate(csInfo);
-        } else {
-            if (csInfo.parentCount() == cs.successors().count()) { // all paths leading to this CS
-                                                                   // have been explored
-                // TTY.println("  All parents explored, Enqueue");
-                toExplore.add(next);
-                speculativeExplore.remove(next);
-            } else {
-                // TTY.println("  Not all parents explored : Enqueue speculative");
-                speculativeExplore.add(next);
-            }
-        }
-        infoMap.set(next, csInfo);
-    }
-
-    private boolean propagateUpdate(DominatorInfo di) {
-        // TTY.println("   propagateUpdate(" + di + ")");
-        for (DominatorInfo child : di.children()) {
-            // TTY.println("      add to child " + child);
-            if (child.add(di, false)) {
-                if (child.equals(fullInfo)) {
-                    // TTY.println("   Found DOM!");
-                    dominator = child.node();
-                    return true;
-                }
-                if (propagateUpdate(child)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private boolean checkControlSplitInfo(DominatorInfo di) {
-        // TTY.println("   checkControlSplitInfo(" + di + ")");
-        if (di.equals(fullInfo)) {
-            dominator = di.node();
-            // TTY.println("   Found DOM!");
-            return true;
-        }
-        return false;
-    }
-
-    private void processMerge(MergeNode merge, DominatorInfo info) {
-        // TTY.println("processMerge(" + merge + ", " + info + ")");
-        for (AbstractEndNode end : merge.cfgPredecessors()) {
-            toExplore.add(end);
-            infoMap.set(end, info.createChild(end));
-            // TTY.println("  Enqueue end : " + end + " with " + infoMap.get(end));
-        }
-    }
-
-    private class DominatorInfo {
-
-        private final FixedNode node;
-        private final BitSet bits;
-        private final BitSet ownBits;
-        private final Collection<DominatorInfo> children;
-        private final Collection<DominatorInfo> parents;
-        private boolean explored;
-
-        public DominatorInfo(FixedNode node, boolean full) {
-            this.node = node;
-            this.bits = new BitSet();
-            this.ownBits = new BitSet();
-            this.children = new ArrayList<>(2);
-            this.parents = new ArrayList<>(2);
-            if (full) {
-                addOwnBits(0);
-            }
-        }
-
-        public boolean isExplored() {
-            return explored;
-        }
-
-        public void setExplored() {
-            explored = true;
-        }
-
-        public DominatorInfo createChild(FixedNode childNode) {
-            DominatorInfo di = new DominatorInfo(childNode, false);
-            di.bits.or(bits);
-            di.ownBits.or(ownBits);
-            if (!children.isEmpty() || di.ownBits.isEmpty()) {
-                int newBit = nextBit++;
-                di.bits.xor(ownBits);
-                di.bits.set(newBit);
-                di.ownBits.clear();
-                di.ownBits.set(newBit);
-                addOwnBits(newBit);
-            }
-            children.add(di);
-            di.parents.add(this);
-            return di;
-        }
-
-        private void addOwnBits(int newBit) {
-            if (!bits.get(newBit)) {
-                ownBits.set(newBit);
-                bits.set(newBit);
-                for (DominatorInfo parent : parents) {
-                    parent.addOwnBits(newBit);
-                }
-            }
-        }
-
-        public boolean add(DominatorInfo i) {
-            return add(i, true);
-        }
-
-        public boolean add(DominatorInfo i, boolean addParent) {
-            boolean ret = true;
-            if (addParent) {
-                parents.add(i);
-                i.children.add(this);
-                bits.or(i.bits);
-            } else {
-                BitSet newBits = (BitSet) i.bits.clone();
-                newBits.andNot(bits);
-                newBits.andNot(i.ownBits);
-                ret = !newBits.isEmpty();
-                bits.or(newBits);
-            }
-            return ret;
-        }
-
-        public int parentCount() {
-            return parents.size();
-        }
-
-        public FixedNode node() {
-            return node;
-        }
-
-        public Collection<DominatorInfo> children() {
-            return children;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof DominatorInfo)) {
-                return false;
-            }
-            return ((DominatorInfo) obj).bits.equals(bits);
-        }
-
-        @Override
-        public String toString() {
-            return bits + " (o" + ownBits + ") " + node;
-        }
-
-        @Override
-        public int hashCode() {
-            return bits.hashCode();
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -38,7 +38,6 @@
 
         @Override
         public final boolean apply(Node n) {
-            // isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class)
             return n instanceof FloatingNode || n instanceof VirtualState || n instanceof CallTargetNode;
         }
     };
@@ -138,6 +137,11 @@
     }
 
     public static void removeFixedWithUnusedInputs(FixedWithNextNode fixed) {
+        if (fixed instanceof StateSplit) {
+            FrameState stateAfter = ((StateSplit) fixed).stateAfter();
+            ((StateSplit) fixed).setStateAfter(null);
+            killWithUnusedFloatingInputs(stateAfter);
+        }
         FixedNode next = fixed.next();
         fixed.setNext(null);
         fixed.replaceAtPredecessor(next);
@@ -164,7 +168,7 @@
     }
 
     public static void checkRedundantProxy(ProxyNode vpn) {
-        AbstractBeginNode proxyPoint = vpn.proxyPoint();
+        BeginNode proxyPoint = vpn.proxyPoint();
         if (proxyPoint instanceof LoopExitNode) {
             LoopExitNode exit = (LoopExitNode) proxyPoint;
             LoopBeginNode loopBegin = exit.loopBegin();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/NodeIterators.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.util;
-
-import java.util.*;
-
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.*;
-
-public class NodeIterators {
-
-    public static NodeIterable<FixedNode> dominators(final FixedNode n) {
-        return new AbstractNodeIterable<FixedNode>() {
-
-            @Override
-            public Iterator<FixedNode> iterator() {
-                return new NodeIterator<FixedNode>() {
-
-                    FixedNode p = n;
-
-                    @Override
-                    protected void forward() {
-                        if (current == null) {
-                            if (p instanceof MergeNode) {
-                                current = new ComputeImmediateDominator((MergeNode) p).compute();
-                            } else {
-                                current = (FixedNode) p.predecessor();
-                            }
-                            p = current;
-                        }
-                    }
-                };
-            }
-        };
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/TreeIterators.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.util;
-
-import java.util.*;
-
-public class TreeIterators {
-
-    public abstract static class PrefixTreeIterator<T> implements Iterator<T> {
-
-        private Deque<T> stack = new LinkedList<>();
-
-        public PrefixTreeIterator(T root) {
-            stack.push(root);
-        }
-
-        public PrefixTreeIterator(Iterable<T> roots) {
-            for (T root : roots) {
-                stack.addLast(root);
-            }
-        }
-
-        @Override
-        public boolean hasNext() {
-            return !stack.isEmpty();
-        }
-
-        @Override
-        public T next() {
-            T top = stack.pop();
-            LinkedList<T> list = new LinkedList<>();
-            for (T child : children(top)) {
-                list.addFirst(child);
-            }
-            for (T child : list) {
-                stack.push(child);
-            }
-            return top;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        protected abstract Iterable<T> children(T node);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Selects one object from a {@link CommitAllocationNode}. The object is identified by its
@@ -35,7 +35,7 @@
 public class AllocatedObjectNode extends FloatingNode implements Virtualizable, ArrayLengthProvider {
 
     @Input private VirtualObjectNode virtualObject;
-    @Input(InputType.Association) private CommitAllocationNode commit;
+    @Input(InputType.Extension) private CommitAllocationNode commit;
 
     public AllocatedObjectNode(VirtualObjectNode virtualObject) {
         super(StampFactory.exactNonNull(virtualObject.type()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,14 +25,14 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
-@NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Association})
+@NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Extension})
 public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable {
 
     @Input private final NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.virtual;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, IterableNodeType {
 
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,13 +29,13 @@
 public class OptionDescriptor {
 
     protected final String name;
-    protected final Class type;
+    protected final Class<?> type;
     protected final String help;
     protected final OptionValue<?> option;
     protected final Class<?> declaringClass;
     protected final String fieldName;
 
-    public OptionDescriptor(String name, Class type, String help, Class<?> declaringClass, String fieldName, OptionValue<?> option) {
+    public OptionDescriptor(String name, Class<?> type, String help, Class<?> declaringClass, String fieldName, OptionValue<?> option) {
         this.name = name;
         this.type = type;
         this.help = help;
@@ -48,7 +48,7 @@
     /**
      * Gets the type of values stored in the option.
      */
-    public Class getType() {
+    public Class<?> getType() {
         return type;
     }
 
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Wed Apr 23 15:48:38 2014 +0200
@@ -37,7 +37,7 @@
  * Processes static fields annotated with {@link Option}. An {@link Options} service is generated
  * for each top level class containing at least one such field. These service objects can be
  * retrieved as follows:
- * 
+ *
  * <pre>
  * ServiceLoader&lt;Options&gt; sl = ServiceLoader.loadInstalled(Options.class);
  * for (OptionDescriptor desc : sl) {
@@ -184,11 +184,11 @@
             out.println("        return options.iterator();");
             out.println("    }");
             if (needPrivateFieldAccessor) {
-                out.println("    private static " + OptionValue.class.getSimpleName() + " field(Class<?> declaringClass, String fieldName) {");
+                out.println("    private static " + OptionValue.class.getSimpleName() + "<?> field(Class<?> declaringClass, String fieldName) {");
                 out.println("        try {");
                 out.println("            java.lang.reflect.Field field = declaringClass.getDeclaredField(fieldName);");
                 out.println("            field.setAccessible(true);");
-                out.println("            return (" + OptionValue.class.getSimpleName() + ") field.get(null);");
+                out.println("            return (" + OptionValue.class.getSimpleName() + "<?>) field.get(null);");
                 out.println("        } catch (Exception e) {");
                 out.println("            throw (InternalError) new InternalError().initCause(e);");
                 out.println("        }");
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Wed Apr 23 15:48:38 2014 +0200
@@ -139,7 +139,7 @@
 
     private long reads;
     private OptionValue<?> next;
-    private static OptionValue head;
+    private static OptionValue<?> head;
 
     private static final boolean ShowReadsHistogram = Boolean.getBoolean("graal.showOptionValueReadsHistogram");
 
@@ -252,7 +252,7 @@
      * {@link OptionValue#override(OptionValue, Object)} or {@link OptionValue#override(Map)}.
      */
     public abstract static class OverrideScope implements AutoCloseable {
-        abstract void addToInherited(Map<OptionValue, Object> inherited);
+        abstract void addToInherited(Map<OptionValue<?>, Object> inherited);
 
         abstract <T> T getOverride(OptionValue<T> option);
 
@@ -276,7 +276,7 @@
         }
 
         @Override
-        void addToInherited(Map<OptionValue, Object> inherited) {
+        void addToInherited(Map<OptionValue<?>, Object> inherited) {
             inherited.put(option, value);
         }
 
@@ -304,7 +304,7 @@
 
     static class MultipleOverridesScope extends OverrideScope {
         final OverrideScope parent;
-        final Map<OptionValue, Object> overrides;
+        final Map<OptionValue<?>, Object> overrides;
 
         public MultipleOverridesScope(OverrideScope parent, OptionValue<?> option, Object value) {
             this.parent = parent;
@@ -348,7 +348,7 @@
         }
 
         @Override
-        void addToInherited(Map<OptionValue, Object> inherited) {
+        void addToInherited(Map<OptionValue<?>, Object> inherited) {
             if (parent != null) {
                 parent.addToInherited(inherited);
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.phases.common;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
@@ -151,7 +151,7 @@
                         break;
                     }
                 }
-                if (type != null && type != ObjectStamp.typeOrNull(node)) {
+                if (type != null && type != StampTool.typeOrNull(node)) {
                     newKnownTypes.put(node, type);
                 }
             }
@@ -234,15 +234,15 @@
 
         public ResolvedJavaType getNodeType(ValueNode node) {
             ResolvedJavaType result = knownTypes.get(GraphUtil.unproxify(node));
-            return result == null ? ObjectStamp.typeOrNull(node) : result;
+            return result == null ? StampTool.typeOrNull(node) : result;
         }
 
         public boolean isNull(ValueNode value) {
-            return ObjectStamp.isObjectAlwaysNull(value) || knownNull.contains(GraphUtil.unproxify(value));
+            return StampTool.isObjectAlwaysNull(value) || knownNull.contains(GraphUtil.unproxify(value));
         }
 
         public boolean isNonNull(ValueNode value) {
-            return ObjectStamp.isObjectNonNull(value) || knownNonNull.contains(GraphUtil.unproxify(value));
+            return StampTool.isObjectNonNull(value) || knownNonNull.contains(GraphUtil.unproxify(value));
         }
 
         @Override
@@ -407,7 +407,7 @@
             }
         }
 
-        private void registerControlSplitInfo(Node pred, AbstractBeginNode begin) {
+        private void registerControlSplitInfo(Node pred, BeginNode begin) {
             assert pred != null && begin != null;
             if (begin instanceof LoopExitNode) {
                 state.clear();
@@ -656,8 +656,8 @@
 
         @Override
         protected void node(FixedNode node) {
-            if (node instanceof AbstractBeginNode) {
-                AbstractBeginNode begin = (AbstractBeginNode) node;
+            if (node instanceof BeginNode) {
+                BeginNode begin = (BeginNode) node;
                 Node pred = node.predecessor();
 
                 if (pred != null) {
@@ -710,7 +710,7 @@
                     replacementAnchor = BeginNode.prevBegin(checkCast);
                     PiNode piNode;
                     if (isNull) {
-                        ConstantNode nullObject = ConstantNode.forObject(null, metaAccess, graph);
+                        ConstantNode nullObject = ConstantNode.defaultForKind(Kind.Object, graph);
                         piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.getValue(), metaAccess), replacementAnchor.asNode()));
                     } else {
                         piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode()));
@@ -742,7 +742,7 @@
 
                 LogicNode replacement = null;
                 ValueNode replacementAnchor = null;
-                AbstractBeginNode survivingSuccessor = null;
+                BeginNode survivingSuccessor = null;
                 if (state.trueConditions.containsKey(compare)) {
                     replacement = trueConstant;
                     replacementAnchor = state.trueConditions.get(compare);
@@ -764,7 +764,7 @@
                 }
 
                 if (replacement != null) {
-                    if (!(replacementAnchor instanceof AbstractBeginNode)) {
+                    if (!(replacementAnchor instanceof BeginNode)) {
                         ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor));
                         graph.addBeforeFixed(ifNode, anchor);
                     }
@@ -811,10 +811,10 @@
                     ValueNode receiver = callTarget.receiver();
                     if (receiver != null && (callTarget.invokeKind() == InvokeKind.Interface || callTarget.invokeKind() == InvokeKind.Virtual)) {
                         ResolvedJavaType type = state.getNodeType(receiver);
-                        if (!Objects.equals(type, ObjectStamp.typeOrNull(receiver))) {
+                        if (!Objects.equals(type, StampTool.typeOrNull(receiver))) {
                             ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod());
                             if (method != null) {
-                                if (Modifier.isFinal(method.getModifiers()) || Modifier.isFinal(type.getModifiers())) {
+                                if (method.canBeStaticallyBound() || type.isFinal()) {
                                     callTarget.setInvokeKind(InvokeKind.Special);
                                     callTarget.setTargetMethod(method);
                                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -47,11 +47,11 @@
  */
 public class ConvertDeoptimizeToGuardPhase extends Phase {
 
-    private static AbstractBeginNode findBeginNode(FixedNode startNode) {
+    private static BeginNode findBeginNode(FixedNode startNode) {
         Node n = startNode;
         while (true) {
-            if (n instanceof AbstractBeginNode) {
-                return (AbstractBeginNode) n;
+            if (n instanceof BeginNode) {
+                return (BeginNode) n;
             } else {
                 n = n.predecessor();
             }
@@ -71,7 +71,7 @@
 
         for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.class)) {
 
-            AbstractBeginNode pred = BeginNode.prevBegin(fixedGuard);
+            BeginNode pred = BeginNode.prevBegin(fixedGuard);
             if (pred instanceof MergeNode) {
                 MergeNode merge = (MergeNode) pred;
                 if (fixedGuard.condition() instanceof CompareNode) {
@@ -109,17 +109,17 @@
         new DeadCodeEliminationPhase().apply(graph);
     }
 
-    private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
+    private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
         if (deoptBegin instanceof MergeNode) {
             MergeNode mergeNode = (MergeNode) deoptBegin;
             Debug.log("Visiting %s", mergeNode);
-            List<AbstractBeginNode> begins = new ArrayList<>();
+            List<BeginNode> begins = new ArrayList<>();
             for (AbstractEndNode end : mergeNode.forwardEnds()) {
-                AbstractBeginNode newBeginNode = findBeginNode(end);
+                BeginNode newBeginNode = findBeginNode(end);
                 assert !begins.contains(newBeginNode);
                 begins.add(newBeginNode);
             }
-            for (AbstractBeginNode begin : begins) {
+            for (BeginNode begin : begins) {
                 assert !begin.isDeleted();
                 visitDeoptBegin(begin, deoptAction, deoptReason, graph);
             }
@@ -127,11 +127,11 @@
             return;
         } else if (deoptBegin.predecessor() instanceof IfNode) {
             IfNode ifNode = (IfNode) deoptBegin.predecessor();
-            AbstractBeginNode otherBegin = ifNode.trueSuccessor();
+            BeginNode otherBegin = ifNode.trueSuccessor();
             LogicNode conditionNode = ifNode.condition();
             FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor()));
             FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
-            AbstractBeginNode survivingSuccessor;
+            BeginNode survivingSuccessor;
             if (deoptBegin == ifNode.trueSuccessor()) {
                 survivingSuccessor = ifNode.falseSuccessor();
             } else {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,9 +25,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -92,9 +93,9 @@
 
     private static void exitLoops(AbstractDeoptimizeNode deopt, EndNode end, ControlFlowGraph cfg) {
         Block block = cfg.blockFor(deopt);
-        Loop loop = block.getLoop();
+        Loop<Block> loop = block.getLoop();
         while (loop != null) {
-            end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode(loop.loopBegin())));
+            end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode((LoopBeginNode) loop.header.getBeginNode())));
             loop = loop.parent;
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.phases.common;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -54,8 +55,8 @@
     }
 
     private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
-        AbstractBeginNode trueTarget = ifNode.trueSuccessor();
-        AbstractBeginNode falseTarget = ifNode.falseSuccessor();
+        BeginNode trueTarget = ifNode.trueSuccessor();
+        BeginNode falseTarget = ifNode.falseSuccessor();
         double firstIfProbability = shortCircuitProbability;
         /*
          * P(Y | not(X)) = P(Y inter not(X)) / P(not(X)) = (P(X union Y) - P(X)) / (1 - P(X))
@@ -77,9 +78,9 @@
         EndNode secondTrueEnd = graph.add(new EndNode());
         trueTargetMerge.addForwardEnd(firstTrueEnd);
         trueTargetMerge.addForwardEnd(secondTrueEnd);
-        AbstractBeginNode firstTrueTarget = AbstractBeginNode.begin(firstTrueEnd);
-        AbstractBeginNode secondTrueTarget = AbstractBeginNode.begin(secondTrueEnd);
-        AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
+        BeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
+        BeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
+        BeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
         IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability));
         ifNode.replaceAtPredecessor(firstIf);
         ifNode.safeDelete();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -191,7 +191,7 @@
         }
 
         @Override
-        protected Set<LocationIdentity> afterSplit(AbstractBeginNode node, Set<LocationIdentity> oldState) {
+        protected Set<LocationIdentity> afterSplit(BeginNode node, Set<LocationIdentity> oldState) {
             return new HashSet<>(oldState);
         }
 
@@ -292,7 +292,7 @@
         }
 
         @Override
-        protected MemoryMapImpl afterSplit(AbstractBeginNode node, MemoryMapImpl oldState) {
+        protected MemoryMapImpl afterSplit(BeginNode node, MemoryMapImpl oldState) {
             MemoryMapImpl result = new MemoryMapImpl(oldState);
             if (node.predecessor() instanceof InvokeWithExceptionNode) {
                 /*
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
@@ -92,7 +93,7 @@
         }
 
         @Override
-        protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) {
+        protected FrameState afterSplit(BeginNode node, FrameState oldState) {
             return oldState;
         }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.phases.common;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -154,12 +155,12 @@
 
         private void lowerToIf(GuardNode guard) {
             StructuredGraph graph = guard.graph();
-            AbstractBeginNode fastPath = graph.add(new BeginNode());
+            BeginNode fastPath = graph.add(new BeginNode());
             @SuppressWarnings("deprecation")
             DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation()));
-            AbstractBeginNode deoptBranch = AbstractBeginNode.begin(deopt);
-            AbstractBeginNode trueSuccessor;
-            AbstractBeginNode falseSuccessor;
+            BeginNode deoptBranch = BeginNode.begin(deopt);
+            BeginNode trueSuccessor;
+            BeginNode falseSuccessor;
             insertLoopExits(deopt);
             if (guard.negated()) {
                 trueSuccessor = deoptBranch;
@@ -174,10 +175,10 @@
         }
 
         private void insertLoopExits(DeoptimizeNode deopt) {
-            Loop loop = block.getLoop();
+            Loop<Block> loop = block.getLoop();
             StructuredGraph graph = deopt.graph();
             while (loop != null) {
-                LoopExitNode exit = graph.add(new LoopExitNode(loop.loopBegin()));
+                LoopExitNode exit = graph.add(new LoopExitNode((LoopBeginNode) loop.header.getBeginNode()));
                 graph.addBeforeFixed(deopt, exit);
                 loop = loop.parent;
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -40,6 +40,11 @@
         this.canonicalizer = canonicalizer;
     }
 
+    public IncrementalCanonicalizerPhase(CanonicalizerPhase canonicalizer, BasePhase<? super C> phase) {
+        this.canonicalizer = canonicalizer;
+        appendPhase(phase);
+    }
+
     @Override
     protected void run(StructuredGraph graph, C context) {
         Mark newNodesMark = graph.getMark();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,13 +22,15 @@
  */
 package com.oracle.graal.phases.common;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.phases.common.InliningPhase.Options.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
@@ -36,7 +38,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.common.InliningUtil.InlineInfo;
@@ -173,28 +174,30 @@
         Mark markBeforeInlining = callerGraph.getMark();
         InlineInfo callee = calleeInfo.callee();
         try {
-            List<Node> invokeUsages = callee.invoke().asNode().usages().snapshot();
-            callee.inline(new Providers(context), callerAssumptions);
-            callerAssumptions.record(calleeInfo.assumptions());
-            metricInliningRuns.increment();
-            Debug.dump(callerGraph, "after %s", callee);
+            try (Scope scope = Debug.scope("doInline", callerGraph)) {
+                List<Node> invokeUsages = callee.invoke().asNode().usages().snapshot();
+                callee.inline(new Providers(context), callerAssumptions);
+                callerAssumptions.record(calleeInfo.assumptions());
+                metricInliningRuns.increment();
+                Debug.dump(callerGraph, "after %s", callee);
 
-            if (OptCanonicalizer.getValue()) {
-                Mark markBeforeCanonicalization = callerGraph.getMark();
-                canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining);
+                if (OptCanonicalizer.getValue()) {
+                    Mark markBeforeCanonicalization = callerGraph.getMark();
+                    canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining);
 
-                // process invokes that are possibly created during canonicalization
-                for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) {
-                    if (newNode instanceof Invoke) {
-                        callerGraphInfo.pushInvoke((Invoke) newNode);
+                    // process invokes that are possibly created during canonicalization
+                    for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) {
+                        if (newNode instanceof Invoke) {
+                            callerGraphInfo.pushInvoke((Invoke) newNode);
+                        }
                     }
                 }
-            }
+
+                callerGraphInfo.computeProbabilities();
 
-            callerGraphInfo.computeProbabilities();
-
-            inliningCount++;
-            metricInliningPerformed.increment();
+                inliningCount++;
+                metricInliningPerformed.increment();
+            }
         } catch (BailoutException bailout) {
             throw bailout;
         } catch (AssertionError | RuntimeException e) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,8 @@
 
 import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
-import static com.oracle.graal.nodes.type.StampFactory.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-import static java.lang.reflect.Modifier.*;
-
-import java.lang.reflect.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.compiler.common.type.StampFactory.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -36,6 +33,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
@@ -137,13 +137,12 @@
      */
     private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final int inliningDepth, final boolean success, final String msg, final Object... args) {
         if (HotSpotPrintInlining.getValue()) {
-            final int mod = method.getModifiers();
             // 1234567
             TTY.print("        ");     // print timestamp
             // 1234
             TTY.print("     ");        // print compilation number
             // % s ! b n
-            TTY.print("%c%c%c%c%c ", ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ');
+            TTY.print("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ');
             TTY.print("     ");        // more indent
             TTY.print("    ");         // initial inlining indent
             for (int i = 0; i < inliningDepth; i++) {
@@ -432,7 +431,7 @@
             super(invoke);
             this.concrete = concrete;
             this.type = type;
-            assert type.isArray() || !isAbstract(type.getModifiers()) : type;
+            assert type.isArray() || !type.isAbstract() : type;
         }
 
         @Override
@@ -646,7 +645,7 @@
             }
 
             // create one separate block for each invoked method
-            AbstractBeginNode[] successors = new AbstractBeginNode[numberOfMethods + 1];
+            BeginNode[] successors = new BeginNode[numberOfMethods + 1];
             for (int i = 0; i < numberOfMethods; i++) {
                 successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, true);
             }
@@ -658,7 +657,7 @@
             } else {
                 unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated));
             }
-            successors[successors.length - 1] = AbstractBeginNode.begin(unknownTypeSux);
+            successors[successors.length - 1] = BeginNode.begin(unknownTypeSux);
 
             // replace the invoke exception edge
             if (invoke instanceof InvokeWithExceptionNode) {
@@ -684,7 +683,7 @@
 
             // do the actual inlining for every invoke
             for (int i = 0; i < numberOfMethods; i++) {
-                AbstractBeginNode node = successors[i];
+                BeginNode node = successors[i];
                 Invoke invokeForInlining = (Invoke) node.next();
 
                 ResolvedJavaType commonType;
@@ -770,10 +769,10 @@
         private void inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions) {
             assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
-            AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
+            BeginNode calleeEntryNode = graph.add(new BeginNode());
 
-            AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
-            AbstractBeginNode[] successors = new AbstractBeginNode[]{calleeEntryNode, unknownTypeSux};
+            BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
+            BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, false, metaAccess);
 
             calleeEntryNode.setNext(invoke.asNode());
@@ -781,7 +780,7 @@
             inline(invoke, methodAt(0), inlineableElementAt(0), assumptions, false);
         }
 
-        private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, AbstractBeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess) {
+        private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess) {
             assert ptypes.size() >= 1;
             ValueNode nonNullReceiver = nonNullReceiver(invoke);
             Kind hubKind = ((MethodCallTargetNode) invoke.callTarget()).targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind();
@@ -891,10 +890,10 @@
             return costEstimateMethodDispatch < costEstimateTypeDispatch;
         }
 
-        private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge,
-                        PhiNode exceptionObjectPhi, boolean useForInlining) {
+        private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi,
+                        boolean useForInlining) {
             Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining);
-            AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
+            BeginNode calleeEntryNode = graph.add(new BeginNode());
             calleeEntryNode.setNext(duplicatedInvoke.asNode());
 
             AbstractEndNode endNode = graph.add(new EndNode());
@@ -969,9 +968,9 @@
         }
 
         private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target, MetaAccessProvider metaAccess) {
-            AbstractBeginNode invocationEntry = graph.add(new BeginNode());
-            AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
-            AbstractBeginNode[] successors = new AbstractBeginNode[]{invocationEntry, unknownTypeSux};
+            BeginNode invocationEntry = graph.add(new BeginNode());
+            BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
+            BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, true, metaAccess);
 
             invocationEntry.setNext(invoke.asNode());
@@ -981,8 +980,8 @@
             replaceInvokeCallTarget(invoke, graph, kind, target);
         }
 
-        private static AbstractBeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
-            return AbstractBeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
+        private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
+            return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
         }
 
         @Override
@@ -1111,7 +1110,7 @@
 
     private static InlineInfo getAssumptionInlineInfo(InliningData data, Invoke invoke, Replacements replacements, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod concrete,
                     Assumption takenAssumption) {
-        assert !Modifier.isAbstract(concrete.getModifiers());
+        assert !concrete.isAbstract();
         if (!checkTargetConditions(data, replacements, invoke, concrete, optimisticOpts)) {
             return null;
         }
@@ -1119,7 +1118,7 @@
     }
 
     private static InlineInfo getExactInlineInfo(InliningData data, Invoke invoke, Replacements replacements, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod targetMethod) {
-        assert !Modifier.isAbstract(targetMethod.getModifiers());
+        assert !targetMethod.isAbstract();
         if (!checkTargetConditions(data, replacements, invoke, targetMethod, optimisticOpts)) {
             return null;
         }
@@ -1149,7 +1148,7 @@
             }
 
             ResolvedJavaType type = ptypes[0].getType();
-            assert type.isArray() || !isAbstract(type.getModifiers());
+            assert type.isArray() || !type.isAbstract();
             ResolvedJavaMethod concrete = type.resolveMethod(targetMethod);
             if (!checkTargetConditions(data, replacements, invoke, concrete, optimisticOpts)) {
                 return null;
@@ -1221,7 +1220,7 @@
                 if (index == -1) {
                     notRecordedTypeProbability += type.getProbability();
                 } else {
-                    assert type.getType().isArray() || !isAbstract(type.getType().getModifiers()) : type + " " + concrete;
+                    assert type.getType().isArray() || !type.getType().isAbstract() : type + " " + concrete;
                     usedTypes.add(type);
                     typesToConcretes.add(index);
                 }
@@ -1274,9 +1273,9 @@
     private static boolean checkTargetConditions(InliningData data, Replacements replacements, Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) {
         if (method == null) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method is not resolved");
-        } else if (Modifier.isNative(method.getModifiers()) && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) {
+        } else if (method.isNative() && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is a non-intrinsic native method");
-        } else if (Modifier.isAbstract(method.getModifiers())) {
+        } else if (method.isAbstract()) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is an abstract method");
         } else if (!method.getDeclaringClass().isInitialized()) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method's class is not initialized");
@@ -1347,7 +1346,7 @@
             }
         }
 
-        final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode);
+        final BeginNode prevBegin = BeginNode.prevBegin(invokeNode);
         DuplicationReplacement localReplacement = new DuplicationReplacement() {
 
             public Node replacement(Node node) {
@@ -1386,7 +1385,7 @@
             }
 
             // get rid of memory kill
-            AbstractBeginNode begin = invokeWithException.next();
+            BeginNode begin = invokeWithException.next();
             if (begin instanceof KillingBeginNode) {
                 BeginNode newBegin = new BeginNode();
                 graph.addAfterFixed(begin, graph.add(newBegin));
@@ -1396,19 +1395,8 @@
         } else {
             if (unwindNode != null) {
                 UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
-                MonitorExitNode monitorExit = findPrecedingMonitorExit(unwindDuplicate);
-                DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler);
-                unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode));
-                // move the deopt upwards if there is a monitor exit that tries to use the
-                // "after exception" frame state
-                // (because there is no "after exception" frame state!)
-                if (monitorExit != null) {
-                    if (monitorExit.stateAfter() != null && monitorExit.stateAfter().bci == FrameState.AFTER_EXCEPTION_BCI) {
-                        FrameState monitorFrameState = monitorExit.stateAfter();
-                        graph.removeFixed(monitorExit);
-                        monitorFrameState.safeDelete();
-                    }
-                }
+                DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+                unwindDuplicate.replaceAndDelete(deoptimizeNode);
             }
         }
 
@@ -1417,22 +1405,25 @@
             int callerLockDepth = stateAfter.nestedLockDepth();
             for (FrameState original : inlineGraph.getNodes(FrameState.class)) {
                 FrameState frameState = (FrameState) duplicates.get(original);
-                if (frameState != null) {
-                    assert frameState.bci != FrameState.BEFORE_BCI : frameState;
-                    if (frameState.bci == FrameState.AFTER_BCI) {
+                if (frameState != null && frameState.isAlive()) {
+                    assert frameState.bci != BytecodeFrame.BEFORE_BCI : frameState;
+                    if (frameState.bci == BytecodeFrame.AFTER_BCI) {
                         frameState.replaceAndDelete(returnKind == Kind.Void ? stateAfter : stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), returnKind,
                                         frameState.stackAt(0)));
-                    } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) {
-                        if (frameState.isAlive()) {
-                            assert stateAtExceptionEdge != null;
+                    } else if (frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI || (frameState.bci == BytecodeFrame.UNWIND_BCI && !frameState.method().isSynchronized())) {
+                        if (stateAtExceptionEdge != null) {
                             frameState.replaceAndDelete(stateAtExceptionEdge);
                         } else {
-                            assert stateAtExceptionEdge == null;
+                            handleMissingAfterExceptionFrameState(frameState);
                         }
+                    } else if (frameState.bci == BytecodeFrame.UNWIND_BCI) {
+                        handleMissingAfterExceptionFrameState(frameState);
                     } else {
                         // only handle the outermost frame states
                         if (frameState.outerFrameState() == null) {
-                            assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method());
+                            assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method());
+                            assert frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI && frameState.bci != BytecodeFrame.BEFORE_BCI && frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI &&
+                                            frameState.bci != BytecodeFrame.UNWIND_BCI : frameState.bci;
                             if (outerFrameState == null) {
                                 outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invokeNode.getKind());
                                 outerFrameState.setDuringCall(true);
@@ -1479,6 +1470,39 @@
         return duplicates;
     }
 
+    protected static void handleMissingAfterExceptionFrameState(FrameState nonReplacableFrameState) {
+        Graph graph = nonReplacableFrameState.graph();
+        NodeWorkList workList = graph.createNodeWorkList();
+        workList.add(nonReplacableFrameState);
+        for (Node node : workList) {
+            FrameState fs = (FrameState) node;
+            for (Node usage : fs.usages().snapshot()) {
+                if (!usage.isAlive()) {
+                    continue;
+                }
+                if (usage instanceof FrameState) {
+                    workList.add(usage);
+                } else {
+                    StateSplit stateSplit = (StateSplit) usage;
+                    FixedNode fixedStateSplit = stateSplit.asNode();
+                    if (fixedStateSplit instanceof MergeNode) {
+                        MergeNode merge = (MergeNode) fixedStateSplit;
+                        while (merge.isAlive()) {
+                            AbstractEndNode end = merge.forwardEnds().first();
+                            DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+                            end.replaceAtPredecessor(deoptimizeNode);
+                            GraphUtil.killCFG(end);
+                        }
+                    } else {
+                        DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+                        fixedStateSplit.replaceAtPredecessor(deoptimizeNode);
+                        GraphUtil.killCFG(fixedStateSplit);
+                    }
+                }
+            }
+        }
+    }
+
     public static ValueNode mergeReturns(MergeNode merge, List<? extends ReturnNode> returnNodes) {
         PhiNode returnValuePhi = null;
 
@@ -1504,7 +1528,7 @@
         for (Node node : duplicates.values()) {
             if (node instanceof FrameState) {
                 FrameState frameState = (FrameState) node;
-                assert frameState.bci == FrameState.AFTER_BCI || frameState.bci == FrameState.INVALID_FRAMESTATE_BCI : node.toString(Verbosity.Debugger);
+                assert frameState.bci == BytecodeFrame.AFTER_BCI || frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI : node.toString(Verbosity.Debugger);
             }
         }
         return true;
@@ -1518,7 +1542,7 @@
         assert !callTarget.isStatic() : callTarget.targetMethod();
         StructuredGraph graph = callTarget.graph();
         ValueNode firstParam = callTarget.arguments().get(0);
-        if (firstParam.getKind() == Kind.Object && !ObjectStamp.isObjectNonNull(firstParam)) {
+        if (firstParam.getKind() == Kind.Object && !StampTool.isObjectNonNull(firstParam)) {
             IsNullNode condition = graph.unique(new IsNullNode(firstParam));
             Stamp stamp = firstParam.stamp().join(objectNonNull());
             GuardingPiNode nonNullReceiver = graph.add(new GuardingPiNode(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp));
@@ -1566,7 +1590,7 @@
         try {
             return macroNodeClass.getConstructor(Invoke.class).newInstance(invoke);
         } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
-            throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass);
+            throw new GraalGraphInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass);
         }
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.phases.common;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.phases.common;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -36,7 +37,6 @@
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 
 /**
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -55,11 +55,11 @@
     @Override
     protected void run(StructuredGraph graph) {
         LazyCFG cfg = new LazyCFG(graph);
-        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
+        for (BeginNode begin : graph.getNodes(BeginNode.class)) {
             if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) {
                 NodeIterable<GuardNode> guards = begin.guards();
                 if (guards.isNotEmpty()) {
-                    AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin);
+                    BeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin);
                     // newAnchor == begin is possible because postdominator computation assumes that
                     // loops never end
                     if (newAnchor != begin) {
@@ -76,14 +76,14 @@
         }
     }
 
-    public static AbstractBeginNode getOptimalAnchor(LazyCFG cfg, AbstractBeginNode begin) {
+    public static BeginNode getOptimalAnchor(LazyCFG cfg, BeginNode begin) {
         if (begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode) {
             return begin;
         }
         return computeOptimalAnchor(cfg.get(), begin);
     }
 
-    private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) {
+    private static BeginNode computeOptimalAnchor(ControlFlowGraph cfg, BeginNode begin) {
         Block anchor = cfg.blockFor(begin);
         while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) {
             anchor = anchor.getDominator();
@@ -92,7 +92,7 @@
     }
 
     private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) {
-        AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit);
+        BeginNode successor = findMinimumUsagesSuccessor(controlSplit);
         int successorCount = controlSplit.successors().count();
         List<GuardNode> otherGuards = new ArrayList<>(successorCount - 1);
         for (GuardNode guard : successor.guards().snapshot()) {
@@ -109,7 +109,7 @@
             }
 
             if (otherGuards.size() == successorCount - 1) {
-                AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit));
+                BeginNode anchor = computeOptimalAnchor(cfg.get(), BeginNode.prevBegin(controlSplit));
                 GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
                 for (GuardNode otherGuard : otherGuards) {
                     otherGuard.replaceAndDelete(newGuard);
@@ -126,12 +126,12 @@
                         conditonGuard.getSpeculation().equals(guard.getSpeculation());
     }
 
-    private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
+    private static BeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
         NodeClassIterator successors = controlSplit.successors().iterator();
-        AbstractBeginNode min = (AbstractBeginNode) successors.next();
+        BeginNode min = (BeginNode) successors.next();
         int minUsages = min.usages().count();
         while (successors.hasNext()) {
-            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
+            BeginNode successor = (BeginNode) successors.next();
             int count = successor.usages().count();
             if (count < minUsages) {
                 minUsages = count;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -43,11 +44,11 @@
  * for each node would be too costly, so this phase takes the compromise that it trusts split
  * probabilities, but not loop frequencies. This means that it will insert counters at the start of
  * a method and at each loop header.
- * 
+ *
  * A schedule is created so that floating nodes can also be taken into account. The weight of a node
  * is determined heuristically in the
  * {@link ProfileCompiledMethodsPhase#getNodeWeight(ScheduledNode)} method.
- * 
+ *
  * Additionally, there's a second counter that's only increased for code sections without invokes.
  */
 public class ProfileCompiledMethodsPhase extends Phase {
@@ -65,18 +66,18 @@
         schedule.apply(graph, false);
 
         ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
-        for (Loop loop : cfg.getLoops()) {
-            double loopProbability = probabilities.get(loop.loopBegin());
+        for (Loop<Block> loop : cfg.getLoops()) {
+            double loopProbability = probabilities.get(loop.header.getBeginNode());
             if (loopProbability > (1D / Integer.MAX_VALUE)) {
-                addSectionCounters(loop.loopBegin(), loop.blocks, loop.children, schedule, probabilities);
+                addSectionCounters(loop.header.getBeginNode(), loop.blocks, loop.children, schedule, probabilities);
             }
         }
-        addSectionCounters(graph.start(), Arrays.asList(cfg.getBlocks()), Arrays.asList(cfg.getLoops()), schedule, probabilities);
+        addSectionCounters(graph.start(), Arrays.asList(cfg.getBlocks()), cfg.getLoops(), schedule, probabilities);
     }
 
-    private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop> childLoops, SchedulePhase schedule, NodesToDoubles probabilities) {
+    private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop<Block>> childLoops, SchedulePhase schedule, NodesToDoubles probabilities) {
         HashSet<Block> blocks = new HashSet<>(sectionBlocks);
-        for (Loop loop : childLoops) {
+        for (Loop<?> loop : childLoops) {
             blocks.removeAll(loop.blocks);
         }
         double weight = getSectionWeight(schedule, probabilities, blocks) / probabilities.get(start);
@@ -108,7 +109,7 @@
     private static double getNodeWeight(ScheduledNode node) {
         if (node instanceof MergeNode) {
             return ((MergeNode) node).phiPredecessorCount();
-        } else if (node instanceof AbstractBeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode ||
+        } else if (node instanceof BeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode ||
                         node instanceof CallTargetNode || node instanceof ValueProxy || node instanceof VirtualObjectNode || node instanceof ReinterpretNode) {
             return 0;
         } else if (node instanceof AccessMonitorNode) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.phases.common;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,12 @@
  */
 package com.oracle.graal.phases.common;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.Graph.Mark;
@@ -37,7 +39,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
@@ -293,7 +294,7 @@
                 // EndNode
                 FixedWithNextNode anchorDuplicate = (FixedWithNextNode) duplicates.get(anchor);
                 // move dependencies on the ValueAnchorNode to the previous BeginNode
-                AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(forwardEnd);
+                BeginNode prevBegin = BeginNode.prevBegin(forwardEnd);
                 anchorDuplicate.replaceAtUsages(InputType.Guard, prevBegin);
                 anchorDuplicate.replaceAtUsages(InputType.Anchor, prevBegin);
                 assert anchorDuplicate.usages().isEmpty();
@@ -493,7 +494,7 @@
                         Position pos = iter.nextPosition();
                         if (pos.get(usage) == duplicated) {
                             switch (pos.getInputType(usage)) {
-                                case Association:
+                                case Extension:
                                 case Condition:
                                 case State:
                                     // clone the offending node to the outside
@@ -524,6 +525,7 @@
                                     }
                                     pos.set(usage, newPhi);
                                     break;
+                                case Association:
                                 default:
                                     throw GraalInternalError.shouldNotReachHere();
                             }
@@ -541,7 +543,7 @@
                 Node input = pos.get(duplicated);
                 if (input != null && !duplicatedNodes.contains(input)) {
                     switch (pos.getInputType(duplicated)) {
-                        case Association:
+                        case Extension:
                         case Condition:
                         case State:
                             if (input != merge) {
@@ -549,6 +551,7 @@
                                 worklist.add(input);
                             }
                             break;
+                        case Association:
                         case Guard:
                         case Anchor:
                         case Value:
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -55,7 +55,7 @@
         }
         Node predecessor = deopt.predecessor();
         Node branch = null;
-        while (predecessor instanceof AbstractBeginNode) {
+        while (predecessor instanceof BeginNode) {
             branch = predecessor;
             predecessor = predecessor.predecessor();
         }
@@ -73,8 +73,8 @@
 
     private static void replaceWithTrappingNullCheck(DeoptimizeNode deopt, IfNode ifNode, LogicNode condition) {
         IsNullNode isNullNode = (IsNullNode) condition;
-        AbstractBeginNode nonTrappingContinuation = ifNode.falseSuccessor();
-        AbstractBeginNode trappingContinuation = ifNode.trueSuccessor();
+        BeginNode nonTrappingContinuation = ifNode.falseSuccessor();
+        BeginNode trappingContinuation = ifNode.trueSuccessor();
         NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.object()));
         trappingNullCheck.setStateBefore(deopt.stateBefore());
         deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,283 +0,0 @@
-/*
- * Copyright (c) 2009, 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.phases;
-
-import com.oracle.graal.options.*;
-
-/**
- * This class encapsulates options that control the behavior of the Graal compiler.
- */
-// @formatter:off
-public final class GraalOptions {
-
-    @Option(help = "Use baseline compiler configuration")
-    public static final OptionValue<Boolean> UseBaselineCompiler = new OptionValue<>(false);
-    @Option(help = "Enable use of compiler intrinsics")
-    public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true);
-    @Option(help = "Enable inlining of monomorphic calls")
-    static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true);
-    @Option(help = "Enable inlining of polymorphic calls")
-    static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true);
-    @Option(help = "Enable inlining of megamorphic calls")
-    static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D);
-    @Option(help = "")
-    public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(20000);
-    @Option(help = "")
-    public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(5);
-
-    // inlining settings
-    @Option(help = "")
-    public static final OptionValue<Float> BoostInliningForEscapeAnalysis = new OptionValue<>(2f);
-    @Option(help = "")
-    public static final OptionValue<Float> RelevanceCapForInlining = new OptionValue<>(1f);
-    @Option(help = "")
-    public static final OptionValue<Float> CapInheritedRelevance = new OptionValue<>(1f);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IterativeInlining = new OptionValue<>(false);
-
-    @Option(help = "")
-    public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10);
-    @Option(help = "")
-    public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300);
-    @Option(help = "")
-    public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300);
-    @Option(help = "")
-    public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0);
-    @Option(help = "")
-    public static final OptionValue<Boolean> InlineEverything = new OptionValue<>(false);
-
-    // escape analysis settings
-    @Option(help = "")
-    public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2);
-    @Option(help = "")
-    public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null);
-    @Option(help = "")
-    public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32);
-    @Option(help = "")
-    public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false);
-
-    @Option(help = "")
-    public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5);
-    @Option(help = "")
-    public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1);
-
-    // profiling information
-    @Option(help = "")
-    public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40);
-
-    // graph caching
-    @Option(help = "")
-    public static final OptionValue<Boolean> CacheGraphs = new OptionValue<>(true);
-
-    //loop transform settings TODO (gd) tune
-    @Option(help = "")
-    public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Integer> FullUnrollMaxNodes = new OptionValue<>(300);
-    @Option(help = "")
-    public static final OptionValue<Integer> ExactFullUnrollMaxNodes = new OptionValue<>(1200);
-    @Option(help = "")
-    public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f);
-    @Option(help = "")
-    public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3);
-    @Option(help = "")
-    public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(50);
-    @Option(help = "")
-    public static final OptionValue<Integer> LoopUnswitchUncertaintyBoost = new OptionValue<>(5);
-    @Option(help = "")
-    public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true);
-
-    // debugging settings
-    @Option(help = "")
-    public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false);
-
-    @Option(help = "")
-    public static final OptionValue<String> PrintFilter = new OptionValue<>(null);
-
-    // Debug settings:
-    @Option(help = "")
-    public static final OptionValue<Boolean> BootstrapReplacements = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Integer> GCDebugStartCycle = new OptionValue<>(-1);
-    // Ideal graph visualizer output settings
-    @Option(help = "Dump IdealGraphVisualizer output in binary format")
-    public static final OptionValue<Boolean> PrintBinaryGraphs = new OptionValue<>(true);
-    @Option(help = "Output probabilities for fixed nodes during binary graph dumping")
-    public static final OptionValue<Boolean> PrintGraphProbabilities = new OptionValue<>(false);
-    @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.")
-    public static final OptionValue<Boolean> PrintCFG = new OptionValue<>(false);
-    @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.")
-    public static final OptionValue<Boolean> PrintBackendCFG = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> PrintIdealGraphFile = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<String> PrintIdealGraphAddress = new OptionValue<>("127.0.0.1");
-    @Option(help = "")
-    public static final OptionValue<Integer> PrintIdealGraphPort = new OptionValue<>(4444);
-    @Option(help = "")
-    public static final OptionValue<Integer> PrintBinaryGraphPort = new OptionValue<>(4445);
-
-    // Other printing settings
-    @Option(help = "")
-    public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false);
-    @Option(help = "Print profiling information when parsing a method's bytecode")
-    public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> PrintCodeBytes = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> TraceEscapeAnalysis = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
-    @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required")
-    public static final OptionValue<String> DecompileAfterPhase = new OptionValue<>(null);
-
-    // HotSpot command line options
-    @Option(help = "")
-    public static final OptionValue<Boolean> HotSpotPrintCompilation = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> HotSpotCIPrintCompilerName = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false);
-
-    // Register allocator debugging
-    @Option(help = "")
-    public static final OptionValue<String> RegisterPressure = new OptionValue<>(null);
-
-    // Code generator settings
-    @Option(help = "")
-    public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
-    @Option(help = "")
-           static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true);
-           @Option(help = "")
-           static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true);
-           @Option(help = "")
-           static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true);
-           @Option(help = "")
-    public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true);
-    @Option(help = "")
-           static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true);
-           @Option(help = "")
-    public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> GenAssertionCode = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> AlignCallsForPatching = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true);
-
-    @Option(help = "")
-    public static final OptionValue<Boolean> MemoryAwareScheduling = new OptionValue<>(true);
-
-    // Translating tableswitch instructions
-    @Option(help = "")
-    public static final OptionValue<Integer> MinimumJumpTableSize = new OptionValue<>(5);
-    @Option(help = "")
-    public static final OptionValue<Integer> RangeTestsSwitchDensity = new OptionValue<>(5);
-    @Option(help = "")
-    public static final OptionValue<Double> MinTableSwitchDensity = new OptionValue<>(0.5);
-
-    // Ahead of time compilation
-    @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);
-
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptDeoptimizationGrouping = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
-    @Option(help = "Allow backend to emit arithmetic and compares directly against memory.")
-    public static final OptionValue<Boolean> OptFoldMemory = new OptionValue<>(true);
-
-
-    /**
-     * Counts the various paths taken through snippets.
-     */
-    @Option(help = "")
-    public static final OptionValue<Boolean> SnippetCounters = new OptionValue<>(false);
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 
 public final class OptimisticOptimizations {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -105,26 +106,26 @@
         private Scope[] computeScopes() {
             ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
 
-            Loop[] loops = cfg.getLoops();
-            HashMap<Loop, Scope> processedScopes = new HashMap<>();
-            Scope[] result = new Scope[loops.length + 1];
+            List<Loop<Block>> loops = cfg.getLoops();
+            HashMap<Loop<Block>, Scope> processedScopes = new HashMap<>();
+            Scope[] result = new Scope[loops.size() + 1];
             Scope methodScope = new Scope(graph.start(), null);
             processedScopes.put(null, methodScope);
 
             result[0] = methodScope;
-            for (int i = 0; i < loops.length; i++) {
-                result[i + 1] = createScope(loops[i], processedScopes);
+            for (int i = 0; i < loops.size(); i++) {
+                result[i + 1] = createScope(loops.get(i), processedScopes);
             }
 
             return result;
         }
 
-        private Scope createScope(Loop loop, HashMap<Loop, Scope> processedLoops) {
+        private Scope createScope(Loop<Block> loop, HashMap<Loop<Block>, Scope> processedLoops) {
             Scope parent = processedLoops.get(loop.parent);
             if (parent == null) {
                 parent = createScope(loop.parent, processedLoops);
             }
-            Scope result = new Scope(loop.loopBegin(), parent);
+            Scope result = new Scope(loop.header.getBeginNode(), parent);
             processedLoops.put(loop, result);
             return result;
         }
@@ -171,7 +172,7 @@
         int pathBeginCount = pathBeginNodes.size();
 
         for (Node sux : controlSplit.successors()) {
-            double probability = controlSplit.probability((AbstractBeginNode) sux);
+            double probability = controlSplit.probability((BeginNode) sux);
             if (probability > maxProbability) {
                 maxProbability = probability;
                 maxSux = sux;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Wed Apr 23 15:48:38 2014 +0200
@@ -223,7 +223,7 @@
         }
 
         @Override
-        public void afterSplit(AbstractBeginNode node) {
+        public void afterSplit(BeginNode node) {
             assert node.predecessor() != null;
             Node pred = node.predecessor();
             ControlSplitNode x = (ControlSplitNode) pred;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.phases.graph;
 
+import com.oracle.graal.compiler.common.type.*;
 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 {
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Apr 23 15:48:38 2014 +0200
@@ -58,7 +58,7 @@
      * 
      * @param node the successor of the control split that is about to be visited
      */
-    public void afterSplit(AbstractBeginNode node) {
+    public void afterSplit(BeginNode node) {
         // empty default implementation
     }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -43,7 +43,7 @@
 public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
 
     private final NodeBitMap visitedEnds;
-    private final Deque<AbstractBeginNode> nodeQueue;
+    private final Deque<BeginNode> nodeQueue;
     private final IdentityHashMap<FixedNode, T> nodeStates;
     private final FixedNode start;
 
@@ -109,13 +109,13 @@
             for (Node node : successors) {
                 if (node != null) {
                     nodeStates.put((FixedNode) node.predecessor(), state);
-                    nodeQueue.addFirst((AbstractBeginNode) node);
+                    nodeQueue.addFirst((BeginNode) node);
                 }
             }
         } else {
             for (Node node : x.successors()) {
                 if (node != null) {
-                    nodeQueue.addFirst((AbstractBeginNode) node);
+                    nodeQueue.addFirst((BeginNode) node);
                 }
             }
         }
@@ -124,7 +124,7 @@
     private FixedNode nextQueuedNode() {
         int maxIterations = nodeQueue.size();
         while (maxIterations-- > 0) {
-            AbstractBeginNode node = nodeQueue.removeFirst();
+            BeginNode node = nodeQueue.removeFirst();
             if (node instanceof MergeNode) {
                 MergeNode merge = (MergeNode) node;
                 state = nodeStates.get(merge.forwardEndAt(0)).clone();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 
@@ -45,14 +46,14 @@
 
         protected abstract StateT cloneState(StateT oldState);
 
-        protected abstract List<StateT> processLoop(Loop loop, StateT initialState);
+        protected abstract List<StateT> processLoop(Loop<Block> loop, StateT initialState);
     }
 
     private ReentrantBlockIterator() {
         // no instances allowed
     }
 
-    public static <StateT> LoopInfo<StateT> processLoop(BlockIteratorClosure<StateT> closure, Loop loop, StateT initialState) {
+    public static <StateT> LoopInfo<StateT> processLoop(BlockIteratorClosure<StateT> closure, Loop<Block> loop, StateT initialState) {
         IdentityHashMap<FixedNode, StateT> blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks));
 
         LoopInfo<StateT> info = new LoopInfo<>();
@@ -101,8 +102,8 @@
                             states.put(current.getEndNode(), state);
                         } else {
                             // recurse into the loop
-                            Loop loop = successor.getLoop();
-                            LoopBeginNode loopBegin = loop.loopBegin();
+                            Loop<Block> loop = successor.getLoop();
+                            LoopBeginNode loopBegin = (LoopBeginNode) loop.header.getBeginNode();
                             assert successor.getBeginNode() == loopBegin;
 
                             List<StateT> exitStates = closure.processLoop(loop, state);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -41,7 +41,7 @@
 
         protected abstract StateT merge(MergeNode merge, List<StateT> states);
 
-        protected abstract StateT afterSplit(AbstractBeginNode node, StateT oldState);
+        protected abstract StateT afterSplit(BeginNode node, StateT oldState);
 
         protected abstract Map<LoopExitNode, StateT> processLoop(LoopBeginNode loop, StateT initialState);
 
@@ -81,7 +81,7 @@
     }
 
     public static <StateT> Map<FixedNode, StateT> apply(NodeIteratorClosure<StateT> closure, FixedNode start, StateT initialState, Set<FixedNode> boundary) {
-        Deque<AbstractBeginNode> nodeQueue = new ArrayDeque<>();
+        Deque<BeginNode> nodeQueue = new ArrayDeque<>();
         IdentityHashMap<FixedNode, StateT> blockEndStates = new IdentityHashMap<>();
 
         StateT state = initialState;
@@ -146,14 +146,14 @@
                             continue;
                         } else {
                             while (successors.hasNext()) {
-                                AbstractBeginNode successor = (AbstractBeginNode) successors.next();
+                                BeginNode successor = (BeginNode) successors.next();
                                 StateT successorState = closure.afterSplit(successor, state);
                                 if (closure.continueIteration(successorState)) {
                                     blockEndStates.put(successor, successorState);
                                     nodeQueue.add(successor);
                                 }
                             }
-                            state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state);
+                            state = closure.afterSplit((BeginNode) firstSuccessor, state);
                             current = closure.continueIteration(state) ? firstSuccessor : null;
                             continue;
                         }
@@ -167,7 +167,7 @@
             } else {
                 current = nodeQueue.removeFirst();
                 state = blockEndStates.get(current);
-                assert !(current instanceof MergeNode) && current instanceof AbstractBeginNode;
+                assert !(current instanceof MergeNode) && current instanceof BeginNode;
             }
         } while (true);
     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -36,7 +36,7 @@
 public abstract class StatelessPostOrderNodeIterator {
 
     private final NodeBitMap visitedEnds;
-    private final Deque<AbstractBeginNode> nodeQueue;
+    private final Deque<BeginNode> nodeQueue;
     private final FixedNode start;
 
     public StatelessPostOrderNodeIterator(FixedNode start) {
@@ -76,7 +76,7 @@
                 controlSplit((ControlSplitNode) current);
                 for (Node node : current.successors()) {
                     if (node != null) {
-                        nodeQueue.addFirst((AbstractBeginNode) node);
+                        nodeQueue.addFirst((BeginNode) node);
                     }
                 }
                 current = nodeQueue.pollFirst();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,14 @@
 package com.oracle.graal.phases.schedule;
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.nodes.cfg.ControlFlowGraph.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
@@ -152,7 +154,7 @@
         }
 
         @Override
-        protected List<KillSet> processLoop(Loop loop, KillSet state) {
+        protected List<KillSet> processLoop(Loop<Block> loop, KillSet state) {
             LoopInfo<KillSet> info = ReentrantBlockIterator.processLoop(this, loop, cloneState(state));
 
             assert loop.header.getBeginNode() instanceof LoopBeginNode;
@@ -201,7 +203,7 @@
             }
         }
 
-        AbstractBeginNode startNode = cfg.getStartBlock().getBeginNode();
+        BeginNode startNode = cfg.getStartBlock().getBeginNode();
         assert startNode instanceof StartNode;
 
         KillSet accm = foundExcludeNode ? set : excludedLocations;
@@ -649,12 +651,7 @@
          * implies that the inputs' blocks have a total ordering via their dominance relation. So in
          * order to find the earliest block placement for this node we need to find the input block
          * that is dominated by all other input blocks.
-         * 
-         * While iterating over the inputs a set of dominator blocks of the current earliest
-         * placement is maintained. When the block of an input is not within this set, it becomes
-         * the current earliest placement and the list of dominator blocks is updated.
          */
-        BitSet dominators = new BitSet(cfg.getBlocks().length);
 
         if (node.predecessor() != null) {
             throw new SchedulingError();
@@ -667,12 +664,24 @@
             } else {
                 inputEarliest = earliestBlock(input);
             }
-            if (!dominators.get(inputEarliest.getId())) {
+            if (earliest == null) {
                 earliest = inputEarliest;
-                do {
-                    dominators.set(inputEarliest.getId());
-                    inputEarliest = inputEarliest.getDominator();
-                } while (inputEarliest != null && !dominators.get(inputEarliest.getId()));
+            } else if (earliest != inputEarliest) {
+                // Find out whether earliest or inputEarliest is earlier.
+                Block a = earliest.getDominator();
+                Block b = inputEarliest;
+                while (true) {
+                    if (a == inputEarliest || b == null) {
+                        // Nothing to change, the previous earliest block is still earliest.
+                        break;
+                    } else if (b == earliest || a == null) {
+                        // New earliest is the earliest.
+                        earliest = inputEarliest;
+                        break;
+                    }
+                    a = a.getDominator();
+                    b = b.getDominator();
+                }
             }
         }
         if (earliest == null) {
@@ -753,7 +762,7 @@
                     // If a FrameState is an outer FrameState this method behaves as if the inner
                     // FrameState was the actual usage, by recursing.
                     blocksForUsage(node, unscheduledUsage, closure, strategy);
-                } else if (unscheduledUsage instanceof AbstractBeginNode) {
+                } else if (unscheduledUsage instanceof BeginNode) {
                     // Only FrameStates can be connected to BeginNodes.
                     if (!(usage instanceof FrameState)) {
                         throw new SchedulingError(usage.toString());
@@ -922,7 +931,7 @@
             }
             if (canNotMove) {
                 if (b.getEndNode() instanceof ControlSplitNode) {
-                    throw new GraalInternalError("Schedule is not possible : needs to move a node after the last node of the block which can not be move").addContext(lastSorted).addContext(
+                    throw new GraalGraphInternalError("Schedule is not possible : needs to move a node after the last node of the block which can not be move").addContext(lastSorted).addContext(
                                     b.getEndNode());
                 }
 
@@ -977,13 +986,21 @@
             stateAfter = ((StateSplit) i).stateAfter();
         }
 
+        if (i instanceof LoopExitNode) {
+            for (ProxyNode proxy : ((LoopExitNode) i).proxies()) {
+                addToLatestSorting(b, proxy, sortedInstructions, visited, reads, beforeLastLocation);
+            }
+        }
+
         for (Node input : i.inputs()) {
             if (input instanceof FrameState) {
                 if (input != stateAfter) {
                     addUnscheduledToLatestSorting(b, (FrameState) input, sortedInstructions, visited, reads, beforeLastLocation);
                 }
             } else {
-                addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation);
+                if (!(i instanceof ProxyNode && input instanceof LoopExitNode)) {
+                    addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation);
+                }
             }
         }
 
@@ -1047,7 +1064,7 @@
                 }
             }
 
-            if (instruction instanceof AbstractBeginNode) {
+            if (instruction instanceof BeginNode) {
                 ArrayList<ProxyNode> proxies = (instruction instanceof LoopExitNode) ? new ArrayList<>() : null;
                 for (ScheduledNode inBlock : blockToNodesMap.get(b)) {
                     if (!visited.isMarked(inBlock)) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,7 +26,7 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,10 +24,13 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
 import com.oracle.graal.phases.schedule.*;
@@ -58,16 +61,10 @@
             } else {
                 for (Node input : node.inputs()) {
                     if (!visited.isMarked(input)) {
-                        if (input instanceof FrameState && node instanceof StateSplit && input == ((StateSplit) node).stateAfter()) {
-                            // nothing to do - after frame states are known, allowed cycles
+                        if (input instanceof FrameState) {
+                            // nothing to do - frame states are known, allowed cycles
                         } else {
-                            /*
-                             * TODO assertion does not hold for Substrate VM (in general for all
-                             * notDataflow inputs)
-                             * 
-                             * assert false : "unexpected cycle detected at input " + node + " -> "
-                             * + input;
-                             */
+                            assert false : "unexpected cycle detected at input " + node + " -> " + input;
                         }
                     }
                 }
@@ -125,8 +122,7 @@
                 }
             }
         } catch (GraalInternalError e) {
-            e.addContext(node);
-            throw e;
+            throw GraalGraphInternalError.transformAndAddContext(e, node);
         }
     }
 
@@ -146,7 +142,7 @@
             BlockIteratorClosure<NodeBitMap> closure = new BlockIteratorClosure<NodeBitMap>() {
 
                 @Override
-                protected List<NodeBitMap> processLoop(Loop loop, NodeBitMap initialState) {
+                protected List<NodeBitMap> processLoop(Loop<Block> loop, NodeBitMap initialState) {
                     return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates;
                 }
 
@@ -162,11 +158,15 @@
                     FrameState pendingStateAfter = null;
                     for (final ScheduledNode node : list) {
                         FrameState stateAfter = node instanceof StateSplit ? ((StateSplit) node).stateAfter() : null;
+                        if (node instanceof InfopointNode) {
+                            stateAfter = ((InfopointNode) node).getState();
+                        }
 
                         if (pendingStateAfter != null && node instanceof FixedNode) {
                             pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {
                                 public void apply(Node usage, Node nonVirtualNode) {
-                                    assert currentState.isMarked(nonVirtualNode) : nonVirtualNode + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list;
+                                    assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage +
+                                                    " before " + node + " in block " + block + " \n" + list;
                                 }
                             });
                             pendingStateAfter = null;
@@ -186,15 +186,23 @@
                                 }
                             }
                         } else if (node instanceof LoopExitNode) {
-                            // the contents of the loop are only accessible via proxies at the exit
-                            currentState.clearAll();
-                            currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin()));
+                            if (!graph.isAfterFloatingReadPhase()) {
+                                // loop contents are only accessible via proxies at the exit
+                                currentState.clearAll();
+                                currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin()));
+                            }
                             // Loop proxies aren't scheduled, so they need to be added explicitly
                             currentState.markAll(((LoopExitNode) node).proxies());
                         } else {
                             for (Node input : node.inputs()) {
                                 if (input != stateAfter) {
-                                    assert currentState.isMarked(input) : input + " not available at " + node + " in block " + block + "\n" + list;
+                                    if (input instanceof FrameState) {
+                                        ((FrameState) input).applyToNonVirtual((usage, nonVirtual) -> {
+                                            assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list;
+                                        });
+                                    } else {
+                                        assert currentState.isMarked(input) || input instanceof VirtualObjectNode : input + " not available at " + node + " in block " + block + "\n" + list;
+                                    }
                                 }
                             }
                         }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Providers.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Providers.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,13 +24,14 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.spi.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.tiers.*;
 
 /**
  * A set of providers, some of which may not be present (i.e., null).
  */
-public class Providers {
+public class Providers implements CodeGenProviders {
 
     private final MetaAccessProvider metaAccess;
     private final CodeCacheProvider codeCache;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.phases.verify;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.type.*;
@@ -45,7 +46,7 @@
     private boolean isAssignableType(ValueNode node, MetaAccessProvider metaAccess) {
         if (node.stamp() instanceof ObjectStamp) {
             ResolvedJavaType valueType = metaAccess.lookupJavaType(klass);
-            ResolvedJavaType nodeType = ObjectStamp.typeOrNull(node);
+            ResolvedJavaType nodeType = StampTool.typeOrNull(node);
 
             if (nodeType != null && valueType.isAssignableFrom(nodeType)) {
                 return true;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.printer;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.io.*;
 import java.nio.*;
@@ -31,6 +31,7 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.nodes.*;
@@ -282,7 +283,7 @@
         } else if (object instanceof Enum<?>) {
             writeByte(POOL_ENUM);
             writePoolObject(object.getClass());
-            writeInt(((Enum) object).ordinal());
+            writeInt(((Enum<?>) object).ordinal());
         } else if (object instanceof JavaType) {
             JavaType type = (JavaType) object;
             writeByte(POOL_CLASS);
@@ -296,13 +297,13 @@
             Collection<Position> directInputPositions = nodeClass.getFirstLevelInputPositions();
             writeShort((char) directInputPositions.size());
             for (Position pos : directInputPositions) {
-                writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1);
+                writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1);
                 writePoolObject(nodeClass.getName(pos));
             }
             Collection<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions();
             writeShort((char) directSuccessorPositions.size());
             for (Position pos : directSuccessorPositions) {
-                writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1);
+                writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1);
                 writePoolObject(nodeClass.getName(pos));
             }
         } else if (object instanceof ResolvedJavaMethod) {
@@ -432,7 +433,7 @@
     private void writeEdges(Node node, Collection<Position> positions) throws IOException {
         NodeClass nodeClass = node.getNodeClass();
         for (Position pos : positions) {
-            if (pos.subIndex == NodeClass.NOT_ITERABLE) {
+            if (pos.getSubIndex() == NodeClass.NOT_ITERABLE) {
                 Node edge = nodeClass.get(node, pos);
                 writeNodeRef(edge);
             } else {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,12 +31,14 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.alloc.Interval.UsePosList;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.java.*;
+import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -53,10 +55,11 @@
     protected NodeLIRBuilder nodeLirGenerator;
     protected ControlFlowGraph cfg;
     protected SchedulePhase schedule;
+    protected ResolvedJavaMethod method;
 
     /**
      * Creates a control flow graph printer.
-     * 
+     *
      * @param out where the output generated via this printer shown be written
      */
     public CFGPrinter(OutputStream out) {
@@ -65,7 +68,7 @@
 
     /**
      * Prints the control flow graph denoted by a given block map.
-     * 
+     *
      * @param label A label describing the compilation phase that produced the control flow graph.
      * @param blockMap A data structure describing the blocks in a method and how they are
      *            connected.
@@ -125,7 +128,7 @@
 
     /**
      * Prints the specified list of blocks.
-     * 
+     *
      * @param label A label describing the compilation phase that produced the control flow graph.
      * @param blocks The list of blocks to be printed.
      */
@@ -154,6 +157,12 @@
             printBlock(block, printNodes);
         }
         end("cfg");
+        // NOTE: we do this only because the c1visualizer does not recognize the bytecode block if
+        // it is proceeding the cfg blocks. Currently we have no direct influence on the emit order.
+        // As a workaround we dump the bytecode after every cfg.
+        if (method != null) {
+            printBytecodes(new BytecodeDisassembler(false).disassemble(method));
+        }
 
         latestScheduling = null;
     }
@@ -204,8 +213,13 @@
         begin("block");
 
         out.print("name \"").print(blockToString(block)).println('"');
-        out.println("from_bci -1");
-        out.println("to_bci -1");
+        if (block instanceof BciBlock) {
+            out.print("from_bci ").println(((BciBlock) block).startBci);
+            out.print("to_bci ").println(((BciBlock) block).endBci);
+        } else {
+            out.println("from_bci -1");
+            out.println("to_bci -1");
+        }
 
         out.print("predecessors ");
         for (AbstractBlock<?> pred : block.getPredecessors()) {
@@ -366,12 +380,12 @@
                 continue;
             }
 
-            if (pos.index != lastIndex) {
+            if (pos.getIndex() != lastIndex) {
                 if (lastIndex != -1) {
                     out.print(suffix);
                 }
                 out.print(prefix).print(node.getNodeClass().getName(pos)).print(": ");
-                lastIndex = pos.index;
+                lastIndex = pos.getIndex();
             }
             out.print(nodeToString(node.getNodeClass().get(node, pos))).print(" ");
         }
@@ -425,7 +439,7 @@
 
     /**
      * Prints the LIR for each instruction in a given block.
-     * 
+     *
      * @param block the block to print
      */
     private void printLIR(AbstractBlock<?> block) {
@@ -475,7 +489,7 @@
             return "-";
         }
         String prefix;
-        if (node instanceof AbstractBeginNode && (lir == null && schedule == null)) {
+        if (node instanceof BeginNode && (lir == null && schedule == null)) {
             prefix = "B";
         } else if (node instanceof ValueNode) {
             ValueNode value = (ValueNode) node;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.alloc.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -131,6 +132,9 @@
         if (!checkMethodScope()) {
             return;
         }
+        if (curMethod instanceof ResolvedJavaMethod) {
+            cfgPrinter.method = (ResolvedJavaMethod) curMethod;
+        }
 
         if (object instanceof LIR) {
             cfgPrinter.lir = (LIR) object;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.printer;
 
 import static com.oracle.graal.compiler.GraalDebugConfig.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.io.*;
 import java.util.*;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.printer;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.io.*;
 import java.util.concurrent.atomic.*;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.printer;
 
 import static com.oracle.graal.compiler.GraalDebugConfig.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.io.*;
 import java.net.*;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Apr 23 15:48:38 2014 +0200
@@ -171,7 +171,7 @@
                     printProperty(bit, "true");
                 }
             }
-            if (node.getClass() == AbstractBeginNode.class) {
+            if (node.getClass() == BeginNode.class) {
                 printProperty("shortName", "B");
             } else if (node.getClass() == AbstractEndNode.class) {
                 printProperty("shortName", "E");
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,6 +26,7 @@
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -49,7 +50,7 @@
      * conversion. If the float value is a NaN, infinity or if the result of the conversion is
      * larger than {@link Integer#MAX_VALUE} then CVTTSS2SI returns {@link Integer#MIN_VALUE} and
      * extra tests are required on the float value to return the correct int value.
-     * 
+     *
      * @param input the float being converted
      * @param result the result produced by the CVTTSS2SI instruction
      */
@@ -74,7 +75,7 @@
      * conversion. If the float value is a NaN or infinity then CVTTSS2SI returns
      * {@link Long#MIN_VALUE} and extra tests are required on the float value to return the correct
      * long value.
-     * 
+     *
      * @param input the float being converted
      * @param result the result produced by the CVTTSS2SI instruction
      */
@@ -99,7 +100,7 @@
      * conversion. If the double value is a NaN, infinity or if the result of the conversion is
      * larger than {@link Integer#MAX_VALUE} then CVTTSD2SI returns {@link Integer#MIN_VALUE} and
      * extra tests are required on the double value to return the correct int value.
-     * 
+     *
      * @param input the double being converted
      * @param result the result produced by the CVTTSS2SI instruction
      */
@@ -124,7 +125,7 @@
      * conversion. If the double value is a NaN, infinity or if the result of the conversion is
      * larger than {@link Long#MAX_VALUE} then CVTTSD2SI returns {@link Long#MIN_VALUE} and extra
      * tests are required on the double value to return the correct long value.
-     * 
+     *
      * @param input the double being converted
      * @param result the result produced by the CVTTSS2SI instruction
      */
@@ -149,8 +150,8 @@
         private final SnippetInfo d2i;
         private final SnippetInfo d2l;
 
-        public Templates(Providers providers, TargetDescription target) {
-            super(providers, target);
+        public Templates(Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) {
+            super(providers, snippetReflection, target);
 
             f2i = snippet(AMD64ConvertSnippets.class, "f2i");
             f2l = snippet(AMD64ConvertSnippets.class, "f2l");
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.replacements.amd64;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node has the semantics of the AMD64 floating point conversions. It is used in the lowering
@@ -51,7 +52,7 @@
         throw GraalInternalError.shouldNotReachHere();
     }
 
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(value)));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitFloatConvert(op, builder.operand(value)));
     }
 }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,7 @@
 
 package com.oracle.graal.replacements.amd64;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
--- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,14 +23,16 @@
 package com.oracle.graal.replacements.hsail;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.hsail.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node implements HSAIL intrinsics for specific {@link Math} routines.
@@ -49,7 +51,7 @@
 
     /**
      * Gets the parameter passed to the math operation that this node represents.
-     * 
+     *
      * @return the parameter
      */
     public ValueNode getParameter() {
@@ -58,7 +60,7 @@
 
     /**
      * Returns the math operation represented by this node.
-     * 
+     *
      * @return the operation
      */
     public HSAILArithmetic operation() {
@@ -67,7 +69,7 @@
 
     /**
      * Creates a new HSAILMathIntrinsicNode.
-     * 
+     *
      * @param x the argument to the math operation
      * @param op the math operation
      */
@@ -81,30 +83,30 @@
      * Generates the LIR instructions for the math operation represented by this node.
      */
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value input = gen.operand(getParameter());
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value input = builder.operand(getParameter());
         Value result;
         switch (operation()) {
             case ABS:
-                result = gen.getLIRGeneratorTool().emitMathAbs(input);
+                result = gen.emitMathAbs(input);
                 break;
             case CEIL:
-                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathCeil(input);
+                result = ((HSAILLIRGenerator) gen).emitMathCeil(input);
                 break;
             case FLOOR:
-                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathFloor(input);
+                result = ((HSAILLIRGenerator) gen).emitMathFloor(input);
                 break;
             case RINT:
-                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathRint(input);
+                result = ((HSAILLIRGenerator) gen).emitMathRint(input);
                 break;
             case SQRT:
-                result = gen.getLIRGeneratorTool().emitMathSqrt(input);
+                result = gen.emitMathSqrt(input);
                 break;
 
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        gen.setResult(this, result);
+        builder.setResult(this, result);
     }
 
     /**
@@ -132,7 +134,7 @@
 
     /**
      * Node intrinsic for {@link Math} routines taking a single int parameter.
-     * 
+     *
      * @param value
      * @param op the math operation
      * @return the result of the operation
@@ -142,7 +144,7 @@
 
     /**
      * Node intrinsic for {@link Math} routines taking a single double parameter.
-     * 
+     *
      * @param value the input parameter
      * @param op the math operation
      * @return the result of the operation
@@ -152,7 +154,7 @@
 
     /**
      * Node intrinsic for {@link Math} routines taking a single float parameter.
-     * 
+     *
      * @param value the input parameter
      * @param op the math operation
      * @return the result of the operation
@@ -162,10 +164,10 @@
 
     /**
      * Node intrinsic for {@link Math} routines taking a single double parameter.
-     * 
+     *
      * @param value the input parameter
      * @param op the math operation
-     * 
+     *
      * @return the result of the operation
      */
     @NodeIntrinsic
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -82,11 +82,11 @@
         return o.getClass().getName().length();
     }
 
-    public static boolean isInstanceDynamic(Class c, Object o) {
+    public static boolean isInstanceDynamic(Class<?> c, Object o) {
         return c.isInstance(o);
     }
 
-    public static int isInstanceIntDynamic(Class c, Object o) {
+    public static int isInstanceIntDynamic(Class<?> c, Object o) {
         if (c.isInstance(o)) {
             return o.toString().length();
         }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -116,7 +116,7 @@
 
     @LongTest
     public void test5() {
-        Map map = new HashMap<>();
+        Map<?, ?> map = new HashMap<>();
         test("isMap", profile(), map);
         test("isMap", profile(HashMap.class), map);
         test("isMap", profile(TreeMap.class, HashMap.class), map);
@@ -129,7 +129,7 @@
 
     @LongTest
     public void test6() {
-        Map map = new HashMap<>();
+        Map<?, ?> map = new HashMap<>();
         test("isMapInt", profile(), map);
         test("isMapInt", profile(HashMap.class), map);
         test("isMapInt", profile(TreeMap.class, HashMap.class), map);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -135,8 +135,8 @@
         return new String(value);
     }
 
-    public static HashMap newHashMap(int initialCapacity) {
-        return new HashMap(initialCapacity);
+    public static HashMap<?, ?> newHashMap(int initialCapacity) {
+        return new HashMap<>(initialCapacity);
     }
 
     static class SomeObject {
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -83,12 +83,12 @@
 
     ResolvedJavaType arrayType;
     ResolvedJavaType bottomType;
-    Class bottomClass;
+    Class<?> bottomClass;
     int[] dimensions;
 
     @LongTest
     public void test1() {
-        for (Class clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) {
+        for (Class<?> clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) {
             bottomClass = clazz;
             bottomType = getMetaAccess().lookupJavaType(clazz);
             arrayType = bottomType;
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -47,7 +47,7 @@
     private final ReplacementsImpl installer;
 
     public ObjectAccessTest() {
-        installer = new ReplacementsImpl(getProviders(), new Assumptions(false), getTarget());
+        installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), new Assumptions(false), getTarget());
     }
 
     private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
@@ -127,7 +127,7 @@
         JavaWriteNode write = (JavaWriteNode) graph.start().next();
         Assert.assertEquals(graph.getParameter(2), write.value());
         Assert.assertEquals(graph.getParameter(0), write.object());
-        Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci);
+        Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci);
 
         IndexedLocationNode location = (IndexedLocationNode) write.location();
         Assert.assertEquals(kind, location.getValueKind());
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -53,7 +53,7 @@
 
     public PointerTest() {
         target = getCodeCache().getTarget();
-        installer = new ReplacementsImpl(getProviders(), new Assumptions(false), getTarget());
+        installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), new Assumptions(false), getTarget());
     }
 
     private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
@@ -139,7 +139,7 @@
 
         JavaWriteNode write = (JavaWriteNode) cast.next();
         Assert.assertEquals(graph.getParameter(2), write.value());
-        Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci);
+        Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci);
 
         Assert.assertEquals(cast, write.object());
         Assert.assertEquals(graph.getParameter(0), cast.getInput());
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -22,16 +22,10 @@
  */
 package com.oracle.graal.replacements.test;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
-import static com.oracle.graal.replacements.UnsafeSubstitutions.*;
-
 import java.lang.reflect.*;
-import java.util.concurrent.atomic.*;
 
 import org.junit.*;
 
-import sun.misc.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.*;
@@ -44,287 +38,6 @@
  */
 public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest {
 
-    static long off(Object o, String name) {
-        try {
-            return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name));
-        } catch (Exception e) {
-            Assert.fail(e.toString());
-            return 0L;
-        }
-    }
-
-    static class Foo {
-
-        boolean z;
-        byte b;
-        short s;
-        char c;
-        int i;
-        long l;
-        float f;
-        double d;
-        Object o;
-
-        void testGet(Field field, long offset, String getName, Object value) throws Exception {
-            field.set(this, value);
-            Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class);
-            Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class);
-            Object expected = m1.invoke(unsafe, this, offset);
-            Object actual = m2.invoke(null, unsafe, this, offset);
-            Assert.assertEquals(expected, actual);
-        }
-
-        void testDirect(Field field, long offset, String type, Object value) throws Exception {
-            if (type.equals("Boolean") || type.equals("Object")) {
-                // No direct memory access for these types
-                return;
-            }
-
-            long address = unsafe.allocateMemory(offset + 16);
-
-            String getName = "get" + type;
-            String putName = "put" + type;
-            Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType());
-            Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class);
-
-            Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
-            Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class);
-
-            m1.invoke(unsafe, address + offset, value);
-            Object expected = m2.invoke(unsafe, address + offset);
-
-            m3.invoke(null, unsafe, address + offset, value);
-            Object actual = m4.invoke(null, unsafe, address + offset);
-
-            unsafe.freeMemory(address);
-            Assert.assertEquals(expected, actual);
-        }
-
-        void testPut(Field field, long offset, String putName, Object value) throws Exception {
-            Object initialValue = field.get(new Foo());
-            field.set(this, initialValue);
-
-            try {
-                Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
-                Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType());
-                m1.invoke(unsafe, this, offset, value);
-                Object expected = field.get(this);
-                m2.invoke(null, unsafe, this, offset, value);
-                Object actual = field.get(this);
-                Assert.assertEquals(expected, actual);
-            } catch (NoSuchMethodException e) {
-                if (!putName.startsWith("putOrdered")) {
-                    throw e;
-                }
-            }
-        }
-
-        void test(String fieldName, String typeSuffix, Object value) {
-            try {
-                Field field = Foo.class.getDeclaredField(fieldName);
-                long offset = unsafe.objectFieldOffset(field);
-                testGet(field, offset, "get" + typeSuffix, value);
-                testGet(field, offset, "get" + typeSuffix + "Volatile", value);
-                testPut(field, offset, "put" + typeSuffix, value);
-                testPut(field, offset, "put" + typeSuffix + "Volatile", value);
-                testPut(field, offset, "putOrdered" + typeSuffix, value);
-                testDirect(field, offset, typeSuffix, value);
-            } catch (Exception e) {
-                throw new AssertionError(e);
-            }
-        }
-    }
-
-    @Test
-    public void testUnsafeSubstitutions() throws Exception {
-        test("unsafeCompareAndSwapInt");
-        test("unsafeCompareAndSwapLong");
-        test("unsafeCompareAndSwapObject");
-
-        test("unsafeGetBoolean");
-        test("unsafeGetByte");
-        test("unsafeGetShort");
-        test("unsafeGetChar");
-        test("unsafeGetInt");
-        test("unsafeGetLong");
-        test("unsafeGetFloat");
-        test("unsafeGetDouble");
-        test("unsafeGetObject");
-
-        test("unsafePutBoolean");
-        test("unsafePutByte");
-        test("unsafePutShort");
-        test("unsafePutChar");
-        test("unsafePutInt");
-        test("unsafePutFloat");
-        test("unsafePutDouble");
-        test("unsafePutObject");
-
-        test("unsafeDirectMemoryRead");
-        test("unsafeDirectMemoryWrite");
-
-        AtomicInteger a1 = new AtomicInteger(42);
-        AtomicInteger a2 = new AtomicInteger(42);
-        assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53));
-        assertEquals(a1.get(), a2.get());
-
-        AtomicLong l1 = new AtomicLong(42);
-        AtomicLong l2 = new AtomicLong(42);
-        assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53));
-        assertEquals(l1.get(), l2.get());
-
-        AtomicReference o1 = new AtomicReference<>("42");
-        AtomicReference o2 = new AtomicReference<>("42");
-        assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53"));
-        assertEquals(o1.get(), o2.get());
-
-        Foo f1 = new Foo();
-        f1.test("z", "Boolean", Boolean.TRUE);
-        f1.test("b", "Byte", Byte.MIN_VALUE);
-        f1.test("s", "Short", Short.MAX_VALUE);
-        f1.test("c", "Char", '!');
-        f1.test("i", "Int", 1010010);
-        f1.test("f", "Float", -34.5F);
-        f1.test("l", "Long", 99999L);
-        f1.test("d", "Double", 1234.5678D);
-        f1.test("o", "Object", "object");
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapInt(obj, offset, 0, 1);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapLong(obj, offset, 0, 1);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapObject(obj, offset, null, new Object());
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) {
-        unsafe.putBoolean(obj, offset, value);
-        unsafe.putBooleanVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) {
-        unsafe.putByte(obj, offset, value);
-        unsafe.putByteVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) {
-        unsafe.putShort(obj, offset, value);
-        unsafe.putShortVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) {
-        unsafe.putChar(obj, offset, value);
-        unsafe.putCharVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) {
-        unsafe.putInt(obj, offset, value);
-        unsafe.putIntVolatile(obj, offset, value);
-        unsafe.putOrderedInt(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) {
-        unsafe.putLong(obj, offset, value);
-        unsafe.putLongVolatile(obj, offset, value);
-        unsafe.putOrderedLong(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) {
-        unsafe.putFloat(obj, offset, value);
-        unsafe.putFloatVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) {
-        unsafe.putDouble(obj, offset, value);
-        unsafe.putDoubleVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) {
-        unsafe.putObject(obj, offset, value);
-        unsafe.putObjectVolatile(obj, offset, value);
-        unsafe.putOrderedObject(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) {
-        // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist
-        return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) {
-        // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist
-        unsafe.putByte(address, value);
-        unsafe.putShort(address, value);
-        unsafe.putChar(address, (char) value);
-        unsafe.putInt(address, value);
-        unsafe.putLong(address, value);
-        unsafe.putFloat(address, value);
-        unsafe.putDouble(address, value);
-    }
-
     @Test
     public void testMathSubstitutions() {
         assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class);     // Java
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/TypeCheckTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/TypeCheckTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -48,11 +48,11 @@
         return super.getCode(method, graph, forceCompile);
     }
 
-    protected JavaTypeProfile profile(Class... types) {
+    protected JavaTypeProfile profile(Class<?>... types) {
         return profile(TriState.FALSE, types);
     }
 
-    protected JavaTypeProfile profile(TriState nullSeen, Class... types) {
+    protected JavaTypeProfile profile(TriState nullSeen, Class<?>... types) {
         if (types.length == 0) {
             return null;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,451 @@
+/*
+ * 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.replacements.test;
+
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+import static com.oracle.graal.replacements.UnsafeSubstitutions.*;
+
+import java.lang.reflect.*;
+import java.util.concurrent.atomic.*;
+
+import org.junit.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.replacements.*;
+
+/**
+ * Tests the VM independent {@link UnsafeSubstitutions}.
+ */
+public class UnsafeSubstitutionsTest extends MethodSubstitutionTest {
+
+    private static Object executeVarargsSafe(InstalledCode code, Object... args) {
+        try {
+            return code.executeVarargs(args);
+        } catch (InvalidInstalledCodeException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static Object invokeSafe(Method method, Object receiver, Object... args) {
+        method.setAccessible(true);
+        try {
+            return method.invoke(receiver, args);
+        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void testSubstitution(String testMethodName, Class<?> holder, String methodName, Class<?>[] parameterTypes, Object receiver, Object[] args1, Object[] args2) {
+        Method originalMethod = getMethod(holder, methodName, parameterTypes);
+        Method testMethod = getMethod(testMethodName);
+
+        // Force compilation
+        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod));
+        assert code != null;
+
+        // Verify that the original method and the substitution produce the same value
+        {
+            Object expected = invokeSafe(originalMethod, receiver, args1);
+            Object actual = invokeSafe(testMethod, null, args2);
+            assertEquals(expected, actual);
+        }
+
+        // Verify that the generated code and the original produce the same value
+        {
+            Object expected = invokeSafe(originalMethod, receiver, args1);
+            Object actual = executeVarargsSafe(code, args2);
+            assertEquals(expected, actual);
+        }
+    }
+
+    static long off(Object o, String name) {
+        try {
+            return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name));
+        } catch (Exception e) {
+            Assert.fail(e.toString());
+            return 0L;
+        }
+    }
+
+    static class Foo {
+
+        boolean z;
+        byte b;
+        short s;
+        char c;
+        int i;
+        long l;
+        float f;
+        double d;
+        Object o;
+
+        void testGet(Field field, long offset, String getName, Object value) throws Exception {
+            field.set(this, value);
+            Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class);
+            Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class);
+            Object expected = m1.invoke(unsafe, this, offset);
+            Object actual = m2.invoke(null, unsafe, this, offset);
+            Assert.assertEquals(expected, actual);
+        }
+
+        void testDirect(Field field, long offset, String type, Object value) throws Exception {
+            if (type.equals("Boolean") || type.equals("Object")) {
+                // No direct memory access for these types
+                return;
+            }
+
+            long address = unsafe.allocateMemory(offset + 16);
+
+            String getName = "get" + type;
+            String putName = "put" + type;
+            Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType());
+            Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class);
+
+            Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
+            Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class);
+
+            m1.invoke(unsafe, address + offset, value);
+            Object expected = m2.invoke(unsafe, address + offset);
+
+            m3.invoke(null, unsafe, address + offset, value);
+            Object actual = m4.invoke(null, unsafe, address + offset);
+
+            unsafe.freeMemory(address);
+            Assert.assertEquals(expected, actual);
+        }
+
+        void testPut(Field field, long offset, String putName, Object value) throws Exception {
+            Object initialValue = field.get(new Foo());
+            field.set(this, initialValue);
+
+            try {
+                Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
+                Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType());
+                m1.invoke(unsafe, this, offset, value);
+                Object expected = field.get(this);
+                m2.invoke(null, unsafe, this, offset, value);
+                Object actual = field.get(this);
+                Assert.assertEquals(expected, actual);
+            } catch (NoSuchMethodException e) {
+                if (!putName.startsWith("putOrdered")) {
+                    throw e;
+                }
+            }
+        }
+
+        void test(String fieldName, String typeSuffix, Object value) {
+            try {
+                Field field = Foo.class.getDeclaredField(fieldName);
+                long offset = unsafe.objectFieldOffset(field);
+                testGet(field, offset, "get" + typeSuffix, value);
+                testGet(field, offset, "get" + typeSuffix + "Volatile", value);
+                testPut(field, offset, "put" + typeSuffix, value);
+                testPut(field, offset, "put" + typeSuffix + "Volatile", value);
+                testPut(field, offset, "putOrdered" + typeSuffix, value);
+                testDirect(field, offset, typeSuffix, value);
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+    @Test
+    public void testUnsafeSubstitutions() throws Exception {
+        test("unsafeCompareAndSwapInt");
+        test("unsafeCompareAndSwapLong");
+        test("unsafeCompareAndSwapObject");
+
+        test("unsafeGetBoolean");
+        test("unsafeGetByte");
+        test("unsafeGetShort");
+        test("unsafeGetChar");
+        test("unsafeGetInt");
+        test("unsafeGetLong");
+        test("unsafeGetFloat");
+        test("unsafeGetDouble");
+        test("unsafeGetObject");
+
+        test("unsafePutBoolean");
+        test("unsafePutByte");
+        test("unsafePutShort");
+        test("unsafePutChar");
+        test("unsafePutInt");
+        test("unsafePutFloat");
+        test("unsafePutDouble");
+        test("unsafePutObject");
+
+        test("unsafeDirectMemoryRead");
+        test("unsafeDirectMemoryWrite");
+
+        AtomicInteger a1 = new AtomicInteger(42);
+        AtomicInteger a2 = new AtomicInteger(42);
+        assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53));
+        assertEquals(a1.get(), a2.get());
+
+        AtomicLong l1 = new AtomicLong(42);
+        AtomicLong l2 = new AtomicLong(42);
+        assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53));
+        assertEquals(l1.get(), l2.get());
+
+        AtomicReference<String> o1 = new AtomicReference<>("42");
+        AtomicReference<String> o2 = new AtomicReference<>("42");
+        assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53"));
+        assertEquals(o1.get(), o2.get());
+
+        Foo f1 = new Foo();
+        f1.test("z", "Boolean", Boolean.TRUE);
+        f1.test("b", "Byte", Byte.MIN_VALUE);
+        f1.test("s", "Short", Short.MAX_VALUE);
+        f1.test("c", "Char", '!');
+        f1.test("i", "Int", 1010010);
+        f1.test("f", "Float", -34.5F);
+        f1.test("l", "Long", 99999L);
+        f1.test("d", "Double", 1234.5678D);
+        f1.test("o", "Object", "object");
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapInt(obj, offset, 0, 1);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapLong(obj, offset, 0, 1);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapObject(obj, offset, null, new Object());
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) {
+        unsafe.putBoolean(obj, offset, value);
+        unsafe.putBooleanVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) {
+        unsafe.putByte(obj, offset, value);
+        unsafe.putByteVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) {
+        unsafe.putShort(obj, offset, value);
+        unsafe.putShortVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) {
+        unsafe.putChar(obj, offset, value);
+        unsafe.putCharVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) {
+        unsafe.putInt(obj, offset, value);
+        unsafe.putIntVolatile(obj, offset, value);
+        unsafe.putOrderedInt(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) {
+        unsafe.putLong(obj, offset, value);
+        unsafe.putLongVolatile(obj, offset, value);
+        unsafe.putOrderedLong(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) {
+        unsafe.putFloat(obj, offset, value);
+        unsafe.putFloatVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) {
+        unsafe.putDouble(obj, offset, value);
+        unsafe.putDoubleVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) {
+        unsafe.putObject(obj, offset, value);
+        unsafe.putObjectVolatile(obj, offset, value);
+        unsafe.putOrderedObject(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) {
+        // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist
+        return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) {
+        // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist
+        unsafe.putByte(address, value);
+        unsafe.putShort(address, value);
+        unsafe.putChar(address, (char) value);
+        unsafe.putInt(address, value);
+        unsafe.putLong(address, value);
+        unsafe.putFloat(address, value);
+        unsafe.putDouble(address, value);
+    }
+
+    @Test
+    public void testGetAndAddInt() throws Exception {
+        Foo f1 = new Foo();
+        Foo f2 = new Foo();
+        long offset = off(f1, "i");
+        Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, int.class};
+        for (int delta = Integer.MAX_VALUE - 10; delta < Integer.MAX_VALUE; delta++) {
+            Object[] args1 = new Object[]{f1, offset, delta};
+            Object[] args2 = new Object[]{f2, offset, delta};
+            testSubstitution("getAndAddInt", Unsafe.class, "getAndAddInt", parameterTypes, unsafe, args1, args2);
+        }
+    }
+
+    public static int getAndAddInt(Object obj, long offset, int delta) {
+        return unsafe.getAndAddInt(obj, offset, delta);
+    }
+
+    @Test
+    public void testGetAndAddLong() throws Exception {
+        Foo f1 = new Foo();
+        Foo f2 = new Foo();
+        long offset = off(f1, "l");
+        Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, long.class};
+        for (long delta = Long.MAX_VALUE - 10; delta < Long.MAX_VALUE; delta++) {
+            Object[] args1 = new Object[]{f1, offset, delta};
+            Object[] args2 = new Object[]{f2, offset, delta};
+            testSubstitution("getAndAddLong", Unsafe.class, "getAndAddLong", parameterTypes, unsafe, args1, args2);
+        }
+    }
+
+    public static long getAndAddLong(Object obj, long offset, long delta) {
+        return unsafe.getAndAddLong(obj, offset, delta);
+    }
+
+    @Test
+    public void testGetAndSetInt() throws Exception {
+        Foo f1 = new Foo();
+        Foo f2 = new Foo();
+        long offset = off(f1, "i");
+        Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, int.class};
+        for (int delta = Integer.MAX_VALUE - 10; delta < Integer.MAX_VALUE; delta++) {
+            Object[] args1 = new Object[]{f1, offset, delta};
+            Object[] args2 = new Object[]{f2, offset, delta};
+            testSubstitution("getAndSetInt", Unsafe.class, "getAndSetInt", parameterTypes, unsafe, args1, args2);
+        }
+    }
+
+    public static int getAndSetInt(Object obj, long offset, int newValue) {
+        return unsafe.getAndSetInt(obj, offset, newValue);
+    }
+
+    @Test
+    public void testGetAndSetLong() throws Exception {
+        Foo f1 = new Foo();
+        Foo f2 = new Foo();
+        long offset = off(f1, "l");
+        Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, long.class};
+        for (long newValue = Long.MAX_VALUE - 10; newValue < Long.MAX_VALUE; newValue++) {
+            Object[] args1 = new Object[]{f1, offset, newValue};
+            Object[] args2 = new Object[]{f2, offset, newValue};
+            testSubstitution("getAndSetLong", Unsafe.class, "getAndSetLong", parameterTypes, unsafe, args1, args2);
+        }
+    }
+
+    public static long getAndSetLong(Object obj, long offset, long newValue) {
+        return unsafe.getAndSetLong(obj, offset, newValue);
+    }
+
+    @Test
+    public void testGetAndSetObject() throws Exception {
+        Foo f1 = new Foo();
+        Foo f2 = new Foo();
+        long offset = off(f1, "o");
+        Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, Object.class};
+        for (long i = 0; i < 10; i++) {
+            Object o = new Object();
+            Object[] args1 = new Object[]{f1, offset, o};
+            Object[] args2 = new Object[]{f2, offset, o};
+            testSubstitution("getAndSetObject", Unsafe.class, "getAndSetObject", parameterTypes, unsafe, args1, args2);
+            System.gc();
+        }
+    }
+
+    public static Object getAndSetObject(Object obj, long offset, Object newValue) {
+        return unsafe.getAndSetObject(obj, offset, newValue);
+    }
+
+}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -42,7 +42,7 @@
     private final ReplacementsImpl installer;
 
     public WordTest() {
-        installer = new ReplacementsImpl(getProviders(), new Assumptions(false), getTarget());
+        installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), new Assumptions(false), getTarget());
     }
 
     private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/MethodSubstitutionVerifier.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/MethodSubstitutionVerifier.java	Wed Apr 23 15:48:38 2014 +0200
@@ -89,17 +89,17 @@
         }
 
         String originalName = originalName(substitutionMethod, annotation);
-        TypeMirror[] originalSignature = originalSignature(substitutionMethod, annotation);
+        TypeMirror[] originalSignature = originalSignature(originalType, substitutionMethod, annotation);
         if (originalSignature == null) {
             return;
         }
         ExecutableElement originalMethod = originalMethod(substitutionMethod, annotation, originalType, originalName, originalSignature);
         if (DEBUG && originalMethod != null) {
-            env.getMessager().printMessage(Kind.ERROR, String.format("Found original method %s in type %s.", originalMethod, findEnclosingClass(originalMethod)));
+            env.getMessager().printMessage(Kind.NOTE, String.format("Found original method %s in type %s.", originalMethod, findEnclosingClass(originalMethod)));
         }
     }
 
-    private TypeMirror[] originalSignature(ExecutableElement method, AnnotationMirror annotation) {
+    private TypeMirror[] originalSignature(TypeElement originalType, ExecutableElement method, AnnotationMirror annotation) {
         boolean isStatic = resolveAnnotationValue(Boolean.class, findAnnotationValue(annotation, ORIGINAL_IS_STATIC));
         AnnotationValue signatureValue = findAnnotationValue(annotation, ORIGINAL_SIGNATURE);
         String signatureString = resolveAnnotationValue(String.class, signatureValue);
@@ -113,7 +113,11 @@
                     env.getMessager().printMessage(Kind.ERROR, "Method signature must be a static method with the 'this' object as its first parameter", method, annotation);
                     return null;
                 } else {
-                    parameters.remove(0);
+                    TypeMirror thisParam = parameters.remove(0);
+                    if (!isSubtype(originalType.asType(), thisParam)) {
+                        Name thisName = method.getParameters().get(0).getSimpleName();
+                        env.getMessager().printMessage(Kind.ERROR, String.format("The type of %s must assignable from %s", thisName, originalType), method, annotation);
+                    }
                 }
             }
             parameters.add(0, method.getReturnType());
@@ -201,6 +205,26 @@
         return env.getTypeUtils().isSameType(original, substitution);
     }
 
+    /**
+     * Tests whether one type is a subtype of another. Any type is considered to be a subtype of
+     * itself.
+     *
+     * @param t1 the first type
+     * @param t2 the second type
+     * @return {@code true} if and only if the first type is a subtype of the second
+     */
+    private boolean isSubtype(TypeMirror t1, TypeMirror t2) {
+        TypeMirror t1Erased = t1;
+        TypeMirror t2Erased = t2;
+        if (needsErasure(t1Erased)) {
+            t1Erased = env.getTypeUtils().erasure(t1Erased);
+        }
+        if (needsErasure(t2Erased)) {
+            t2Erased = env.getTypeUtils().erasure(t2Erased);
+        }
+        return env.getTypeUtils().isSubtype(t1Erased, t2Erased);
+    }
+
     private static boolean needsErasure(TypeMirror typeMirror) {
         return typeMirror.getKind() != TypeKind.NONE && typeMirror.getKind() != TypeKind.VOID && !typeMirror.getKind().isPrimitive() && typeMirror.getKind() != TypeKind.OTHER &&
                         typeMirror.getKind() != TypeKind.NULL;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,21 +22,21 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 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.graal.nodes.util.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -56,7 +56,7 @@
 
         @Override
         public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
-            if (Modifier.isNative(method.getModifiers())) {
+            if (method.isNative()) {
                 return false;
             }
             if (method.getAnnotation(Fold.class) != null) {
@@ -173,30 +173,13 @@
         return value.shortValue();
     }
 
-    public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider metaAccess) {
+    public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
         ValueNode value = box.getValue();
         if (value.isConstant()) {
             Constant sourceConstant = value.asConstant();
-            switch (box.getBoxingKind()) {
-                case Boolean:
-                    return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), metaAccess, box.graph());
-                case Byte:
-                    return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), metaAccess, box.graph());
-                case Char:
-                    return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), metaAccess, box.graph());
-                case Short:
-                    return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), metaAccess, box.graph());
-                case Int:
-                    return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), metaAccess, box.graph());
-                case Long:
-                    return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), metaAccess, box.graph());
-                case Float:
-                    return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), metaAccess, box.graph());
-                case Double:
-                    return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), metaAccess, box.graph());
-                default:
-                    assert false : "Unexpected source kind for boxing";
-                    break;
+            Constant boxedConstant = constantReflection.boxPrimitive(sourceConstant);
+            if (boxedConstant != null && boxedConstant.getKind() == box.getBoxingKind()) {
+                return ConstantNode.forConstant(boxedConstant, metaAccess, box.graph());
             }
         }
         return null;
@@ -207,8 +190,8 @@
         private final EnumMap<Kind, SnippetInfo> boxSnippets = new EnumMap<>(Kind.class);
         private final EnumMap<Kind, SnippetInfo> unboxSnippets = new EnumMap<>(Kind.class);
 
-        public Templates(Providers providers, TargetDescription target) {
-            super(providers, target);
+        public Templates(Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) {
+            super(providers, snippetReflection, target);
             for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) {
                 boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf"));
                 unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value"));
@@ -216,7 +199,7 @@
         }
 
         public void lower(BoxNode box, LoweringTool tool) {
-            FloatingNode canonical = canonicalizeBoxing(box, providers.getMetaAccess());
+            FloatingNode canonical = canonicalizeBoxing(box, providers.getMetaAccess(), providers.getConstantReflection());
             // if in AOT mode, we don't want to embed boxed constants.
             if (canonical != null && !ImmutableCode.getValue()) {
                 box.graph().replaceFloating(box, canonical);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
@@ -33,12 +34,12 @@
 import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
 
 /**
- * This phase ensures that there's a single {@linkplain FrameState#AFTER_BCI collapsed frame state}
- * per path.
+ * This phase ensures that there's a single {@linkplain BytecodeFrame#AFTER_BCI collapsed frame
+ * state} per path.
  * 
  * Removes other frame states from {@linkplain StateSplit#hasSideEffect() non-side-effecting} nodes
- * in the graph, and replaces them with {@linkplain FrameState#INVALID_FRAMESTATE_BCI invalid frame
- * states}.
+ * in the graph, and replaces them with {@linkplain BytecodeFrame#INVALID_FRAMESTATE_BCI invalid
+ * frame states}.
  * 
  * The invalid frame states ensure that no deoptimization to a snippet frame state will happen.
  */
@@ -65,7 +66,7 @@
             return new IterationState(this, sideEffect.asNode(), null, true);
         }
 
-        public IterationState addBranch(AbstractBeginNode begin) {
+        public IterationState addBranch(BeginNode begin) {
             return new IterationState(this, begin, null, this.invalid);
         }
 
@@ -176,7 +177,7 @@
                 if (!unwindSideEffects.contains(returnSideEffect) && !maskedSideEffects.contains(returnSideEffect)) {
                     StateSplit split = (StateSplit) returnSideEffect;
                     if (split.stateAfter() != null) {
-                        split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI)));
+                        split.setStateAfter(graph.add(new FrameState(BytecodeFrame.AFTER_BCI)));
                     }
                 }
             }
@@ -185,14 +186,14 @@
                 if (!returnSideEffects.contains(unwindSideEffect) && !maskedSideEffects.contains(unwindSideEffect)) {
                     StateSplit split = (StateSplit) unwindSideEffect;
                     if (split.stateAfter() != null) {
-                        split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_EXCEPTION_BCI)));
+                        split.setStateAfter(graph.add(new FrameState(BytecodeFrame.AFTER_EXCEPTION_BCI)));
                     }
                 }
             }
         }
 
         @Override
-        protected IterationState afterSplit(AbstractBeginNode node, IterationState oldState) {
+        protected IterationState afterSplit(BeginNode node, IterationState oldState) {
             return oldState.addBranch(node);
         }
 
@@ -214,7 +215,7 @@
         }
 
         private static FrameState createInvalidFrameState(FixedNode node) {
-            return node.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI));
+            return node.graph().add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
         }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CompositeValueClassSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.replacements;
-
-import static com.oracle.graal.phases.GraalOptions.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.replacements.nodes.*;
-
-/**
- * Substitutions for improving the performance of {@link CompositeValueClass#getClass()}.
- */
-@ClassSubstitution(CompositeValueClass.class)
-public class CompositeValueClassSubstitutions {
-
-    /**
-     * A macro node for calls to {@link CompositeValueClass#get(Class)}. It can use the compiler's
-     * knowledge about node classes to replace itself with a constant value for a constant
-     * {@link Class} parameter.
-     */
-    public static class CompositeValueClassGetNode extends PureFunctionMacroNode {
-
-        public CompositeValueClassGetNode(Invoke invoke) {
-            super(invoke);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        protected Constant evaluate(Constant param, MetaAccessProvider metaAccess) {
-            if (param.isNull() || ImmutableCode.getValue()) {
-                return null;
-            }
-            return Constant.forObject(CompositeValueClass.get((Class<? extends CompositeValue>) param.asObject()));
-        }
-    }
-
-    @MacroSubstitution(isStatic = true, forced = true, macro = CompositeValueClassGetNode.class)
-    private static native CompositeValueClass get(Class<?> c);
-}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -50,8 +50,6 @@
             replacements.registerSubstitutions(CharacterSubstitutions.class);
             replacements.registerSubstitutions(ShortSubstitutions.class);
             replacements.registerSubstitutions(UnsignedMathSubstitutions.class);
-            replacements.registerSubstitutions(NodeClassSubstitutions.class);
-            replacements.registerSubstitutions(CompositeValueClassSubstitutions.class);
         }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
@@ -95,7 +96,7 @@
     }
 
     public InvokeNode createInvoke(Class<?> declaringClass, String name, ValueNode... args) {
-        return createInvoke(declaringClass, name, InvokeKind.Static, null, FrameState.UNKNOWN_BCI, args);
+        return createInvoke(declaringClass, name, InvokeKind.Static, null, BytecodeFrame.UNKNOWN_BCI, args);
     }
 
     /**
@@ -124,7 +125,7 @@
      * arguments.
      */
     public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, HIRFrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
-        assert Modifier.isStatic(method.getModifiers()) == (invokeKind == InvokeKind.Static);
+        assert method.isStatic() == (invokeKind == InvokeKind.Static);
         Signature signature = method.getSignature();
         JavaType returnType = signature.getReturnType(null);
         assert checkArgs(method, args);
@@ -156,7 +157,7 @@
      */
     public boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) {
         Signature signature = method.getSignature();
-        boolean isStatic = Modifier.isStatic(method.getModifiers());
+        boolean isStatic = method.isStatic();
         if (signature.getParameterCount(!isStatic) != args.length) {
             throw new AssertionError(graph + ": wrong number of arguments to " + method);
         }
@@ -179,16 +180,16 @@
     /**
      * Rewrite all word types in the graph.
      */
-    public void rewriteWordTypes() {
-        new WordTypeRewriterPhase(providers.getMetaAccess(), providers.getCodeCache().getTarget().wordKind).apply(graph);
+    public void rewriteWordTypes(SnippetReflectionProvider snippetReflection) {
+        new WordTypeRewriterPhase(providers.getMetaAccess(), snippetReflection, providers.getCodeCache().getTarget().wordKind).apply(graph);
     }
 
     /**
-     * {@linkplain #inline(InvokeNode) Inlines} all invocations currently in the graph.
+     * {@linkplain #inline Inlines} all invocations currently in the graph.
      */
-    public void inlineInvokes() {
+    public void inlineInvokes(SnippetReflectionProvider snippetReflection) {
         for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) {
-            inline(invoke);
+            inline(invoke, snippetReflection);
         }
 
         // Clean up all code that is now dead after inlining.
@@ -201,9 +202,9 @@
      * {@linkplain ReplacementsImpl#makeGraph processed} in the same manner as for snippets and
      * method substitutions.
      */
-    public void inline(InvokeNode invoke) {
+    public void inline(InvokeNode invoke, SnippetReflectionProvider snippetReflection) {
         ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
-        ReplacementsImpl repl = new ReplacementsImpl(providers, new Assumptions(false), providers.getCodeCache().getTarget());
+        ReplacementsImpl repl = new ReplacementsImpl(providers, snippetReflection, new Assumptions(false), providers.getCodeCache().getTarget());
         StructuredGraph calleeGraph = repl.makeGraph(method, null, method, null, FrameStateProcessing.CollapseFrameForSingleSideEffect);
         InliningUtil.inline(invoke, calleeGraph, false);
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,8 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -53,8 +55,8 @@
  */
 public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates {
 
-    public InstanceOfSnippetsTemplates(Providers providers, TargetDescription target) {
-        super(providers, target);
+    public InstanceOfSnippetsTemplates(Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) {
+        super(providers, snippetReflection, target);
     }
 
     /**
@@ -130,7 +132,7 @@
 
         /**
          * Gets the result of this instantiation as a condition.
-         * 
+         *
          * @param testValue the returned condition is true if the result is equal to this value
          */
         LogicNode asCondition(ValueNode testValue) {
@@ -148,7 +150,7 @@
 
         /**
          * Gets the result of the instantiation as a materialized value.
-         * 
+         *
          * @param t the true value for the materialization
          * @param f the false value for the materialization
          */
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,15 +22,11 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.replacements.nodes.*;
 
 /**
  * Substitutions for improving the performance of some critical methods in {@link NodeClass}
@@ -42,33 +38,13 @@
 @ClassSubstitution(NodeClass.class)
 public class NodeClassSubstitutions {
 
-    /**
-     * A macro node for calls to {@link NodeClass#get(Class)}. It can use the compiler's knowledge
-     * about node classes to replace itself with a constant value for a constant {@link Class}
-     * parameter.
-     */
-    public static class NodeClassGetNode extends PureFunctionMacroNode {
-
-        public NodeClassGetNode(Invoke invoke) {
-            super(invoke);
-        }
-
-        @Override
-        protected Constant evaluate(Constant param, MetaAccessProvider metaAccess) {
-            return param.isNull() || ImmutableCode.getValue() ? null : Constant.forObject(NodeClass.get((Class<?>) param.asObject()));
-        }
-    }
-
-    @MacroSubstitution(isStatic = true, forced = true, macro = NodeClassGetNode.class)
-    private static native NodeClass get(Class<?> c);
-
     @MethodSubstitution
     private static Node getNode(Node node, long offset) {
         return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), Node.class);
     }
 
     @MethodSubstitution
-    private static NodeList getNodeList(Node node, long offset) {
+    private static NodeList<?> getNodeList(Node node, long offset) {
         return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), NodeList.class);
     }
 
@@ -78,7 +54,7 @@
     }
 
     @MethodSubstitution
-    private static void putNodeList(Node node, long offset, NodeList value) {
+    private static void putNodeList(Node node, long offset, NodeList<?> value) {
         UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION);
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -29,6 +29,9 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
@@ -39,7 +42,6 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
@@ -52,9 +54,11 @@
 public class NodeIntrinsificationPhase extends Phase {
 
     private final Providers providers;
+    private final SnippetReflectionProvider snippetReflection;
 
-    public NodeIntrinsificationPhase(Providers providers) {
+    public NodeIntrinsificationPhase(Providers providers, SnippetReflectionProvider snippetReflection) {
         this.providers = providers;
+        this.snippetReflection = snippetReflection;
     }
 
     @Override
@@ -77,7 +81,7 @@
         NodeIntrinsic intrinsic = getIntrinsic(target);
         if (intrinsic != null) {
             assert target.getAnnotation(Fold.class) == null;
-            assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target;
+            assert target.isStatic() : "node intrinsic must be static: " + target;
 
             ResolvedJavaType[] parameterTypes = resolveJavaTypes(signatureToTypes(target), declaringClass);
 
@@ -167,25 +171,25 @@
                 }
                 ConstantNode constantNode = (ConstantNode) argument;
                 Constant constant = constantNode.asConstant();
-                Object o = constant.asBoxedValue();
-                if (o instanceof Class<?>) {
-                    reflectionCallArguments[i] = Constant.forObject(providers.getMetaAccess().lookupJavaType((Class<?>) o));
+                ResolvedJavaType type = providers.getConstantReflection().asJavaType(constant);
+                if (type != null) {
+                    reflectionCallArguments[i] = snippetReflection.forObject(type);
                     parameterTypes[i] = providers.getMetaAccess().lookupJavaType(ResolvedJavaType.class);
                 } else {
                     if (parameterTypes[i].getKind() == Kind.Boolean) {
-                        reflectionCallArguments[i] = Constant.forObject(Boolean.valueOf(constant.asInt() != 0));
+                        reflectionCallArguments[i] = snippetReflection.forObject(Boolean.valueOf(constant.asInt() != 0));
                     } else if (parameterTypes[i].getKind() == Kind.Byte) {
-                        reflectionCallArguments[i] = Constant.forObject(Byte.valueOf((byte) constant.asInt()));
+                        reflectionCallArguments[i] = snippetReflection.forObject(Byte.valueOf((byte) constant.asInt()));
                     } else if (parameterTypes[i].getKind() == Kind.Short) {
-                        reflectionCallArguments[i] = Constant.forObject(Short.valueOf((short) constant.asInt()));
+                        reflectionCallArguments[i] = snippetReflection.forObject(Short.valueOf((short) constant.asInt()));
                     } else if (parameterTypes[i].getKind() == Kind.Char) {
-                        reflectionCallArguments[i] = Constant.forObject(Character.valueOf((char) constant.asInt()));
+                        reflectionCallArguments[i] = snippetReflection.forObject(Character.valueOf((char) constant.asInt()));
                     } else {
                         reflectionCallArguments[i] = constant;
                     }
                 }
             } else {
-                reflectionCallArguments[i] = Constant.forObject(argument);
+                reflectionCallArguments[i] = snippetReflection.forObject(argument);
                 parameterTypes[i] = providers.getMetaAccess().lookupJavaType(ValueNode.class);
             }
         }
@@ -226,7 +230,7 @@
         }
 
         try {
-            ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments).asObject();
+            ValueNode intrinsicNode = (ValueNode) snippetReflection.asObject(constructor.newInstance(arguments));
 
             if (setStampFromReturnType) {
                 intrinsicNode.setStamp(invokeStamp);
@@ -267,11 +271,13 @@
             if (getParameterAnnotation(InjectedNodeParameter.class, i, c) != null) {
                 injected = injected == null ? new Constant[1] : Arrays.copyOf(injected, injected.length + 1);
                 if (signature[i].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) {
-                    injected[injected.length - 1] = Constant.forObject(metaAccess);
+                    injected[injected.length - 1] = snippetReflection.forObject(metaAccess);
                 } else if (signature[i].equals(metaAccess.lookupJavaType(StructuredGraph.class))) {
-                    injected[injected.length - 1] = Constant.forObject(graph);
+                    injected[injected.length - 1] = snippetReflection.forObject(graph);
                 } else if (signature[i].equals(metaAccess.lookupJavaType(ForeignCallsProvider.class))) {
-                    injected[injected.length - 1] = Constant.forObject(providers.getForeignCalls());
+                    injected[injected.length - 1] = snippetReflection.forObject(providers.getForeignCalls());
+                } else if (signature[i].equals(metaAccess.lookupJavaType(SnippetReflectionProvider.class))) {
+                    injected[injected.length - 1] = snippetReflection.forObject(snippetReflection);
                 } else {
                     throw new GraalInternalError("Cannot handle injected argument of type %s in %s", toJavaName(signature[i]), format("%H.%n(%p)", c));
                 }
@@ -311,9 +317,9 @@
             arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1);
             arguments[fixedArgs] = componentType.newArray(nodeConstructorArguments.length - fixedArgs);
 
-            Object varargs = arguments[fixedArgs].asObject();
+            Object varargs = snippetReflection.asObject(arguments[fixedArgs]);
             for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
-                Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i].asBoxedValue());
+                Array.set(varargs, i - fixedArgs, snippetReflection.asBoxedValue(nodeConstructorArguments[i]));
             }
         } else {
             return null;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,7 @@
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -35,10 +35,12 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderPhase.Instance;
 import com.oracle.graal.nodes.*;
@@ -56,6 +58,7 @@
 public class ReplacementsImpl implements Replacements {
 
     protected final Providers providers;
+    protected final SnippetReflectionProvider snippetReflection;
     protected final TargetDescription target;
     protected final Assumptions assumptions;
 
@@ -71,8 +74,9 @@
     private final Set<ResolvedJavaMethod> forcedSubstitutions;
     private final Map<Class<? extends SnippetTemplateCache>, SnippetTemplateCache> snippetTemplateCache;
 
-    public ReplacementsImpl(Providers providers, Assumptions assumptions, TargetDescription target) {
+    public ReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, Assumptions assumptions, TargetDescription target) {
         this.providers = providers.copyWith(this);
+        this.snippetReflection = snippetReflection;
         this.target = target;
         this.assumptions = assumptions;
         this.graphs = new ConcurrentHashMap<>();
@@ -92,7 +96,7 @@
     @Override
     public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry) {
         assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName();
-        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native";
+        assert !method.isAbstract() && !method.isNative() : "Snippet must not be abstract or native";
 
         StructuredGraph graph = UseSnippetGraphCache ? graphs.get(method) : null;
         if (graph == null) {
@@ -121,7 +125,7 @@
 
         // Do deferred intrinsification of node intrinsics
 
-        new NodeIntrinsificationPhase(providers).apply(specializedSnippet);
+        new NodeIntrinsificationPhase(providers, snippetReflection).apply(specializedSnippet);
         new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers, assumptions));
         NodeIntrinsificationVerificationPhase.verify(specializedSnippet);
     }
@@ -232,7 +236,7 @@
         if (originalMember instanceof Method) {
             original = metaAccess.lookupJavaMethod((Method) originalMember);
         } else {
-            original = metaAccess.lookupJavaConstructor((Constructor) originalMember);
+            original = metaAccess.lookupJavaConstructor((Constructor<?>) originalMember);
         }
         if (Debug.isLogEnabled()) {
             Debug.log("substitution: %s --> %s", MetaUtil.format("%H.%n(%p) %r", original), MetaUtil.format("%H.%n(%p) %r", substitute));
@@ -255,7 +259,7 @@
         if (originalMethod instanceof Method) {
             originalJavaMethod = metaAccess.lookupJavaMethod((Method) originalMethod);
         } else {
-            originalJavaMethod = metaAccess.lookupJavaConstructor((Constructor) originalMethod);
+            originalJavaMethod = metaAccess.lookupJavaConstructor((Constructor<?>) originalMethod);
         }
         registeredMacroSubstitutions.put(originalJavaMethod, macro);
         return originalJavaMethod;
@@ -364,7 +368,7 @@
          * Does final processing of a snippet graph.
          */
         protected void finalizeGraph(StructuredGraph graph) {
-            new NodeIntrinsificationPhase(providers).apply(graph);
+            new NodeIntrinsificationPhase(providers, snippetReflection).apply(graph);
             if (!SnippetTemplate.hasConstantParameter(method)) {
                 NodeIntrinsificationVerificationPhase.verify(graph);
             }
@@ -412,8 +416,8 @@
             try (Scope s = Debug.scope("buildInitialGraph", graph)) {
                 MetaAccessProvider metaAccess = providers.getMetaAccess();
                 createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
-                new WordTypeVerificationPhase(metaAccess, target.wordKind).apply(graph);
-                new WordTypeRewriterPhase(metaAccess, target.wordKind).apply(graph);
+                new WordTypeVerificationPhase(metaAccess, snippetReflection, target.wordKind).apply(graph);
+                new WordTypeRewriterPhase(metaAccess, snippetReflection, target.wordKind).apply(graph);
 
                 if (OptCanonicalizer.getValue()) {
                     new CanonicalizerPhase(true).apply(graph, new PhaseContext(providers, assumptions));
@@ -449,7 +453,7 @@
          * Called after all inlining for a given graph is complete.
          */
         protected void afterInlining(StructuredGraph graph) {
-            new NodeIntrinsificationPhase(providers).apply(graph);
+            new NodeIntrinsificationPhase(providers, snippetReflection).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
             if (OptCanonicalizer.getValue()) {
                 new CanonicalizerPhase(true).apply(graph, new PhaseContext(providers, assumptions));
@@ -458,17 +462,30 @@
 
         private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy, int inliningDepth) {
             assert inliningDepth < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded";
-            assert isInlinableSnippet(methodToParse) : methodToParse;
+            assert isInlinable(methodToParse) : methodToParse;
             final StructuredGraph graph = buildInitialGraph(methodToParse);
             try (Scope s = Debug.scope("buildGraph", graph)) {
-
+                Set<MethodCallTargetNode> doNotInline = null;
                 for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.class)) {
+                    if (doNotInline != null && doNotInline.contains(callTarget)) {
+                        continue;
+                    }
                     ResolvedJavaMethod callee = callTarget.targetMethod();
                     if (callee.equals(recursiveEntry)) {
-                        if (isInlinableSnippet(substitutedMethod)) {
+                        if (isInlinable(substitutedMethod)) {
                             final StructuredGraph originalGraph = buildInitialGraph(substitutedMethod);
+                            Mark mark = graph.getMark();
                             InliningUtil.inline(callTarget.invoke(), originalGraph, true);
-
+                            for (MethodCallTargetNode inlinedCallTarget : graph.getNewNodes(mark).filter(MethodCallTargetNode.class)) {
+                                if (doNotInline == null) {
+                                    doNotInline = new HashSet<>();
+                                }
+                                // We do not want to do further inlining (now) for calls
+                                // in the original method as this can cause unlimited
+                                // recursive inlining given an eager inlining policy such
+                                // as DefaultSnippetInliningPolicy.
+                                doNotInline.add(inlinedCallTarget);
+                            }
                             Debug.dump(graph, "after inlining %s", callee);
                             afterInline(graph, originalGraph, null);
                         }
@@ -514,8 +531,8 @@
         }
     }
 
-    private static boolean isInlinableSnippet(final ResolvedJavaMethod methodToParse) {
-        return !Modifier.isAbstract(methodToParse.getModifiers()) && !Modifier.isNative(methodToParse.getModifiers());
+    private static boolean isInlinable(final ResolvedJavaMethod method) {
+        return !method.isAbstract() && !method.isNative();
     }
 
     private static String originalName(Method substituteMethod, String methodSubstitution) {
@@ -533,7 +550,7 @@
      * @param optional if true, resolution failure returns null
      * @return the resolved class or null if resolution fails and {@code optional} is true
      */
-    static Class resolveType(String className, boolean optional) {
+    static Class<?> resolveType(String className, boolean optional) {
         try {
             // Need to use launcher class path to handle classes
             // that are not on the boot class path
@@ -547,7 +564,7 @@
         }
     }
 
-    private static Class resolveType(JavaType type) {
+    private static Class<?> resolveType(JavaType type) {
         JavaType base = type;
         int dimensions = 0;
         while (base.getComponentType() != null) {
@@ -555,15 +572,15 @@
             dimensions++;
         }
 
-        Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base), false);
+        Class<?> baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base), false);
         return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass();
     }
 
     static class JavaSignature {
-        final Class returnType;
-        final Class[] parameters;
+        final Class<?> returnType;
+        final Class<?>[] parameters;
 
-        public JavaSignature(Class returnType, Class[] parameters) {
+        public JavaSignature(Class<?> returnType, Class<?>[] parameters) {
             this.parameters = parameters;
             this.returnType = returnType;
         }
@@ -582,8 +599,8 @@
     }
 
     private JavaSignature originalSignature(Method substituteMethod, String methodSubstitution, boolean isStatic) {
-        Class[] parameters;
-        Class returnType;
+        Class<?>[] parameters;
+        Class<?> returnType;
         if (methodSubstitution.isEmpty()) {
             parameters = substituteMethod.getParameterTypes();
             if (!isStatic) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,8 +23,6 @@
 package com.oracle.graal.replacements;
 
 import java.lang.annotation.*;
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.replacements.nodes.*;
@@ -89,7 +87,7 @@
 
         @Override
         public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
-            if (Modifier.isNative(method.getModifiers())) {
+            if (method.isNative()) {
                 return false;
             }
             if (method.getAnnotation(Fold.class) != null) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,13 +24,13 @@
 
 //JaCoCo Exclude
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.io.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.replacements.nodes.*;
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Apr 23 15:48:38 2014 +0200
@@ -35,6 +35,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
@@ -47,7 +49,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.common.FloatingReadPhase.MemoryMapImpl;
@@ -101,7 +102,7 @@
             this.method = method;
             instantiationCounter = Debug.metric("SnippetInstantiationCount[%s]", method);
             instantiationTimer = Debug.timer("SnippetInstantiationTime[%s]", method);
-            assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
+            assert method.isStatic() : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
             int count = method.getSignature().getParameterCount(false);
             constantParameters = new boolean[count];
             varargsParameters = new boolean[count];
@@ -207,7 +208,7 @@
             return this;
         }
 
-        public Arguments addVarargs(String name, Class componentType, Stamp argStamp, Object value) {
+        public Arguments addVarargs(String name, Class<?> componentType, Stamp argStamp, Object value) {
             assert check(name, false, true);
             Varargs varargs = new Varargs(componentType, argStamp, value);
             values[nextParamIdx] = varargs;
@@ -276,17 +277,17 @@
      */
     static class Varargs {
 
-        protected final Class componentType;
+        protected final Class<?> componentType;
         protected final Stamp stamp;
         protected final Object value;
         protected final int length;
 
-        protected Varargs(Class componentType, Stamp stamp, Object value) {
+        protected Varargs(Class<?> componentType, Stamp stamp, Object value) {
             this.componentType = componentType;
             this.stamp = stamp;
             this.value = value;
             if (value instanceof List) {
-                this.length = ((List) value).size();
+                this.length = ((List<?>) value).size();
             } else {
                 this.length = Array.getLength(value);
             }
@@ -399,11 +400,13 @@
     public abstract static class AbstractTemplates implements SnippetTemplateCache {
 
         protected final Providers providers;
+        protected final SnippetReflectionProvider snippetReflection;
         protected final TargetDescription target;
         private final ConcurrentHashMap<CacheKey, SnippetTemplate> templates;
 
-        protected AbstractTemplates(Providers providers, TargetDescription target) {
+        protected AbstractTemplates(Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) {
             this.providers = providers;
+            this.snippetReflection = snippetReflection;
             this.target = target;
             if (UseSnippetTemplateCache) {
                 this.templates = new ConcurrentHashMap<>();
@@ -443,7 +446,7 @@
             if (template == null) {
                 SnippetTemplates.increment();
                 try (TimerCloseable a = SnippetTemplateCreationTime.start(); Scope s = Debug.scope("SnippetSpecialization", args.info.method)) {
-                    template = new SnippetTemplate(providers, args);
+                    template = new SnippetTemplate(providers, snippetReflection, args);
                     if (UseSnippetTemplateCache) {
                         templates.put(args.cacheKey, template);
                     }
@@ -470,10 +473,14 @@
         return false;
     }
 
+    private final SnippetReflectionProvider snippetReflection;
+
     /**
      * Creates a snippet template.
      */
-    protected SnippetTemplate(final Providers providers, Arguments args) {
+    protected SnippetTemplate(final Providers providers, SnippetReflectionProvider snippetReflection, Arguments args) {
+        this.snippetReflection = snippetReflection;
+
         StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method);
         instantiationTimer = Debug.timer("SnippetTemplateInstantiationTime[%#s]", args);
         instantiationCounter = Debug.metric("SnippetTemplateInstantiationCount[%#s]", args);
@@ -502,7 +509,7 @@
                 if (arg instanceof Constant) {
                     constantArg = (Constant) arg;
                 } else {
-                    constantArg = Constant.forBoxed(kind, arg);
+                    constantArg = snippetReflection.forBoxed(kind, arg);
                 }
                 nodeReplacements.put(snippetGraph.getParameter(i), ConstantNode.forConstant(constantArg, metaAccess, snippetCopy));
             } else if (args.info.isVarargsParameter(i)) {
@@ -702,9 +709,7 @@
             assert arg instanceof Constant : method + ": word constant parameters must be passed boxed in a Constant value: " + arg;
             return true;
         }
-        if (kind == Kind.Object) {
-            assert arg == null || type.isInstance(Constant.forObject(arg)) : method + ": wrong value type for " + name + ": expected " + type.getName() + ", got " + arg.getClass().getName();
-        } else {
+        if (kind != Kind.Object) {
             assert arg != null && kind.toBoxedJavaClass() == arg.getClass() : method + ": wrong value kind for " + name + ": expected " + kind + ", got " +
                             (arg == null ? "null" : arg.getClass().getSimpleName());
         }
@@ -803,10 +808,10 @@
                 ParameterNode[] params = (ParameterNode[]) parameter;
                 Varargs varargs = (Varargs) argument;
                 int length = params.length;
-                List list = null;
+                List<?> list = null;
                 Object array = null;
                 if (varargs.value instanceof List) {
-                    list = (List) varargs.value;
+                    list = (List<?>) varargs.value;
                     assert list.size() == length : length + " != " + list.size();
                 } else {
                     array = varargs.value;
@@ -843,20 +848,10 @@
      */
     protected Constant forBoxed(Object argument, Kind localKind) {
         assert localKind == localKind.getStackKind();
-        if (localKind == Kind.Int && !(argument instanceof Integer)) {
-            if (argument instanceof Boolean) {
-                return Constant.forBoxed(Kind.Boolean, argument);
-            }
-            if (argument instanceof Byte) {
-                return Constant.forBoxed(Kind.Byte, argument);
-            }
-            if (argument instanceof Short) {
-                return Constant.forBoxed(Kind.Short, argument);
-            }
-            assert argument instanceof Character;
-            return Constant.forBoxed(Kind.Char, argument);
+        if (localKind == Kind.Int) {
+            return Constant.forBoxedPrimitive(argument);
         }
-        return Constant.forBoxed(localKind, argument);
+        return snippetReflection.forBoxed(localKind, argument);
     }
 
     /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.replacements.nodes.*;
 
 import edu.umd.cs.findbugs.annotations.*;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -42,17 +42,17 @@
 
     @MethodSubstitution(isStatic = false)
     public static boolean compareAndSwapObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object expected, Object x) {
-        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x);
+        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Object, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
     public static boolean compareAndSwapInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int expected, int x) {
-        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x);
+        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Int, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
     public static boolean compareAndSwapLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long expected, long x) {
-        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x);
+        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Long, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -387,7 +387,7 @@
     }
 
     @MethodSubstitution(isStatic = false)
-    public static Object allocateInstance(final Unsafe thisObj, Class clazz) throws InstantiationException {
+    public static Object allocateInstance(final Unsafe thisObj, Class<?> clazz) throws InstantiationException {
         if (clazz.isPrimitive()) {
             throw new InstantiationException(clazz.getName());
         }
@@ -399,4 +399,47 @@
         }
         return DynamicNewInstanceNode.allocateInstance(clazz, true);
     }
+
+    /**
+     * Guard for {@link Unsafe#getAndSetInt} method family.
+     */
+    public static class GetAndSetGuard implements SubstitutionGuard {
+        public boolean execute() {
+            // FIXME should return whether the current compilation target supports these
+            String arch = System.getProperty("os.arch");
+            switch (arch) {
+                case "amd64":
+                case "x86_64":
+                    return true;
+                default:
+                    return false;
+            }
+        }
+    }
+
+    @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class)
+    public static int getAndAddInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int delta) {
+        return AtomicReadAndAddNode.getAndAddInt(o, offset, delta, LocationIdentity.ANY_LOCATION);
+    }
+
+    @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class)
+    public static long getAndAddLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long delta) {
+        return AtomicReadAndAddNode.getAndAddLong(o, offset, delta, LocationIdentity.ANY_LOCATION);
+    }
+
+    @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class)
+    public static int getAndSetInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int newValue) {
+        return AtomicReadAndWriteNode.getAndSetInt(o, offset, newValue, Kind.Int, LocationIdentity.ANY_LOCATION);
+    }
+
+    @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class)
+    public static long getAndSetLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long newValue) {
+        return AtomicReadAndWriteNode.getAndSetLong(o, offset, newValue, Kind.Long, LocationIdentity.ANY_LOCATION);
+    }
+
+    @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class)
+    public static Object getAndSetObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object newValue) {
+        return AtomicReadAndWriteNode.getAndSetObject(o, offset, newValue, Kind.Object, LocationIdentity.ANY_LOCATION);
+    }
+
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.nodes.calc.Condition.*;
+import static com.oracle.graal.compiler.common.calc.Condition.*;
 import static com.oracle.graal.nodes.calc.ConditionalNode.*;
 
 import com.oracle.graal.api.code.*;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
@@ -30,7 +31,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
@@ -30,7 +31,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class BitCountNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
@@ -30,7 +31,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class BitScanForwardNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
@@ -30,7 +31,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class BitScanReverseNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.replacements.nodes;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.replacements.nodes;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,9 +24,9 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
 
 /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.replacements.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
 
 /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.replacements.nodes;
 
-import static java.lang.reflect.Modifier.*;
-
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
@@ -88,7 +88,7 @@
         StructuredGraph methodSubstitution = tool.getReplacements().getMethodSubstitution(getTargetMethod());
         if (methodSubstitution != null) {
             methodSubstitution = methodSubstitution.copy();
-            if (stateAfter() == null || stateAfter().bci == FrameState.AFTER_BCI) {
+            if (stateAfter() == null || stateAfter().bci == BytecodeFrame.AFTER_BCI) {
                 /*
                  * handles the case of a MacroNode inside a snippet used for another MacroNode
                  * lowering
@@ -135,7 +135,7 @@
         if (replacementGraph != null) {
             // Pull out the receiver null check so that a replaced
             // receiver can be lowered if necessary
-            if (!isStatic(targetMethod.getModifiers())) {
+            if (!targetMethod.isStatic()) {
                 ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
                 if (nonNullReceiver instanceof Lowerable) {
                     ((Lowerable) nonNullReceiver).lower(tool);
@@ -172,7 +172,7 @@
             if (!call.targetMethod().equals(getTargetMethod())) {
                 throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName());
             }
-            assert invoke.stateAfter().bci == FrameState.AFTER_BCI;
+            assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI;
             // Here we need to fix the bci of the invoke
             InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci()));
             newInvoke.setStateAfter(invoke.stateAfter());
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,14 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class MathIntrinsicNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable {
 
@@ -61,35 +63,35 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value input = gen.operand(x());
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value input = builder.operand(x());
         Value result;
         switch (operation()) {
             case ABS:
-                result = gen.getLIRGeneratorTool().emitMathAbs(input);
+                result = gen.emitMathAbs(input);
                 break;
             case SQRT:
-                result = gen.getLIRGeneratorTool().emitMathSqrt(input);
+                result = gen.emitMathSqrt(input);
                 break;
             case LOG:
-                result = gen.getLIRGeneratorTool().emitMathLog(input, false);
+                result = gen.emitMathLog(input, false);
                 break;
             case LOG10:
-                result = gen.getLIRGeneratorTool().emitMathLog(input, true);
+                result = gen.emitMathLog(input, true);
                 break;
             case SIN:
-                result = gen.getLIRGeneratorTool().emitMathSin(input);
+                result = gen.emitMathSin(input);
                 break;
             case COS:
-                result = gen.getLIRGeneratorTool().emitMathCos(input);
+                result = gen.emitMathCos(input);
                 break;
             case TAN:
-                result = gen.getLIRGeneratorTool().emitMathTan(input);
+                result = gen.emitMathTan(input);
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        gen.setResult(this, result);
+        builder.setResult(this, result);
     }
 
     public Constant evalConst(Constant... inputs) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,14 +22,15 @@
  */
 package com.oracle.graal.replacements.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode {
+public class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable {
 
     public MemoryAnchorNode() {
         super(StampFactory.forVoid());
@@ -39,6 +40,11 @@
         // Nothing to emit, since this node is used for structural purposes only.
     }
 
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        return usages().isEmpty() ? null : this;
+    }
+
     public MemoryCheckpoint asMemoryCheckpoint() {
         return null;
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,10 +24,10 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Access the value of a specific register.
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
@@ -30,7 +31,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class ReverseBytesNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,10 +24,10 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Changes the value of a specific register.
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.amd64.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
@@ -50,22 +49,9 @@
                 AMD64MacroAssembler asm = (AMD64MacroAssembler) this.asm;
                 Register thisRegister = codeCache.getRegisterConfig().getCallingConventionRegisters(Type.JavaCall, Kind.Object)[0];
                 Register spillRegister = AMD64.r10; // TODO(mg): fix me
-                AMD64Address nMethodAddress = new AMD64Address(thisRegister, getFieldOffset("installedCode", OptimizedCallTarget.class));
-                int verifiedEntryPoint = asm.position();
-                if (config.useCompressedOops) {
-                    asm.movl(spillRegister, nMethodAddress);
-                    asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.position() - verifiedEntryPoint));
-                    AMD64HotSpotMove.decodePointer(asm, spillRegister, registers.getHeapBaseRegister(), config.getOopEncoding());
-                } else {
-                    asm.movq(spillRegister, nMethodAddress);
-                    asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.position() - verifiedEntryPoint));
-                }
                 Label doProlog = new Label();
 
-                asm.cmpq(spillRegister, 0);
-                asm.jcc(ConditionFlag.Equal, doProlog);
-
-                AMD64Address codeBlobAddress = new AMD64Address(spillRegister, getFieldOffset("codeBlob", HotSpotInstalledCode.class));
+                AMD64Address codeBlobAddress = new AMD64Address(thisRegister, getFieldOffset("address", InstalledCode.class));
                 asm.movq(spillRegister, codeBlobAddress);
                 asm.cmpq(spillRegister, 0);
                 asm.jcc(ConditionFlag.Equal, doProlog);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,205 @@
+/*
+ * 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.hotspot;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.stack.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.SlowPath;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public abstract class HotSpotFrameInstance implements FrameInstance {
+
+    protected final InspectedFrame stackFrame;
+
+    public HotSpotFrameInstance(InspectedFrame stackFrame) {
+        this.stackFrame = stackFrame;
+    }
+
+    protected abstract int getNotifyIndex();
+
+    protected abstract int getCallTargetIndex();
+
+    protected abstract int getFrameIndex();
+
+    @SlowPath
+    public Frame getFrame(FrameAccess access, boolean slowPath) {
+        if (access == FrameAccess.NONE) {
+            return null;
+        }
+        if (!slowPath && getNotifyIndex() != -1) {
+            MaterializedFrameNotify notify = (MaterializedFrameNotify) stackFrame.getLocal(getNotifyIndex());
+            if (notify != null) {
+                if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) {
+                    notify.setOutsideFrameAccess(access);
+                }
+                if (stackFrame.isVirtual(getFrameIndex())) {
+                    stackFrame.materializeVirtualObjects(true);
+                }
+            }
+        }
+        switch (access) {
+            case READ_ONLY: {
+                Frame frame = (Frame) stackFrame.getLocal(getFrameIndex());
+                // assert that it is really used read only
+                assert (frame = new ReadOnlyFrame(frame)) != null;
+                return frame;
+            }
+            case READ_WRITE:
+            case MATERIALIZE:
+                if (stackFrame.isVirtual(getFrameIndex())) {
+                    stackFrame.materializeVirtualObjects(false);
+                }
+                return (Frame) stackFrame.getLocal(getFrameIndex());
+            default:
+                throw GraalInternalError.unimplemented();
+        }
+    }
+
+    public boolean isVirtualFrame() {
+        return stackFrame.isVirtual(getFrameIndex());
+    }
+
+    public abstract CallTarget getCallTarget();
+
+    public abstract CallTarget getTargetCallTarget();
+
+    public DirectCallNode getCallNode() {
+        Object receiver = stackFrame.getLocal(getNotifyIndex());
+        if (receiver instanceof DirectCallNode) {
+            return (DirectCallNode) receiver;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * This class represents a frame that is taken from the
+     * {@link OptimizedDirectCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[], boolean, boolean)}
+     * method.
+     */
+    public static final class CallNodeFrame extends HotSpotFrameInstance {
+        public static final Method METHOD;
+        static {
+            try {
+                METHOD = OptimizedDirectCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class, boolean.class, boolean.class);
+            } catch (NoSuchMethodException | SecurityException e) {
+                throw new GraalInternalError(e);
+            }
+        }
+        private static final int NOTIFY_INDEX = 0;
+        private static final int CALL_TARGET_INDEX = 1;
+        private static final int FRAME_INDEX = 2;
+
+        public CallNodeFrame(InspectedFrame stackFrame) {
+            super(stackFrame);
+        }
+
+        @Override
+        protected int getNotifyIndex() {
+            return NOTIFY_INDEX;
+        }
+
+        @Override
+        protected int getCallTargetIndex() {
+            return CALL_TARGET_INDEX;
+        }
+
+        @Override
+        protected int getFrameIndex() {
+            return FRAME_INDEX;
+        }
+
+        @Override
+        public CallTarget getCallTarget() {
+            return getCallNode().getRootNode().getCallTarget();
+        }
+
+        @Override
+        public CallTarget getTargetCallTarget() {
+            return (CallTarget) stackFrame.getLocal(getCallTargetIndex());
+        }
+    }
+
+    /**
+     * This class represents a frame that is taken from the
+     * {@link RootCallTarget#callProxy(VirtualFrame)} method.
+     */
+    @SuppressWarnings("javadoc")
+    public static final class CallTargetFrame extends HotSpotFrameInstance {
+        public static final Method METHOD;
+        static {
+            try {
+                METHOD = OptimizedCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class);
+            } catch (NoSuchMethodException | SecurityException e) {
+                throw new GraalInternalError(e);
+            }
+        }
+        private static final int NOTIFY_INDEX = -1;
+        private static final int CALL_TARGET_INDEX = 0;
+        private static final int FRAME_INDEX = 1;
+        private final boolean currentFrame;
+
+        public CallTargetFrame(InspectedFrame stackFrame, boolean currentFrame) {
+            super(stackFrame);
+            this.currentFrame = currentFrame;
+        }
+
+        @Override
+        public Frame getFrame(FrameAccess access, boolean slowPath) {
+            if (!slowPath && currentFrame) {
+                throw new UnsupportedOperationException("cannot access current frame as fast path");
+            }
+            return super.getFrame(access, slowPath);
+        }
+
+        @Override
+        protected int getNotifyIndex() {
+            return NOTIFY_INDEX;
+        }
+
+        @Override
+        protected int getCallTargetIndex() {
+            return CALL_TARGET_INDEX;
+        }
+
+        @Override
+        protected int getFrameIndex() {
+            return FRAME_INDEX;
+        }
+
+        @Override
+        public CallTarget getCallTarget() {
+            return (CallTarget) stackFrame.getLocal(getCallTargetIndex());
+        }
+
+        @Override
+        public CallTarget getTargetCallTarget() {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,43 @@
+/*
+ * 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.hotspot;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.runtime.*;
+import com.oracle.graal.truffle.*;
+
+public final class HotSpotTruffleReplacements extends TruffleReplacements {
+
+    private HotSpotTruffleReplacements(Providers providers, SnippetReflectionProvider snippetReflection) {
+        super(providers, snippetReflection);
+    }
+
+    public static Replacements makeInstance() {
+        Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders();
+        SnippetReflectionProvider snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class);
+        return new HotSpotTruffleReplacements(providers, snippetReflection);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,343 @@
+/*
+ * 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.hotspot;
+
+import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.code.stack.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+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.java.*;
+import com.oracle.graal.lir.asm.*;
+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.phases.util.*;
+import com.oracle.graal.printer.*;
+import com.oracle.graal.runtime.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Implementation of the Truffle runtime when running on top of Graal.
+ */
+public final class HotSpotTruffleRuntime implements GraalTruffleRuntime {
+
+    public static HotSpotTruffleRuntime makeInstance() {
+        return new HotSpotTruffleRuntime();
+    }
+
+    private TruffleCompilerImpl truffleCompiler;
+    private Replacements truffleReplacements;
+    private StackIntrospection stackIntrospection;
+    private ArrayList<String> includes;
+    private ArrayList<String> excludes;
+    private Map<OptimizedCallTarget, Future<?>> compilations = new IdentityHashMap<>();
+    private final ThreadPoolExecutor compileQueue;
+
+    private final ResolvedJavaMethod[] callNodeMethod;
+    private final ResolvedJavaMethod[] callTargetMethod;
+    private final ResolvedJavaMethod[] anyFrameMethod;
+
+    private HotSpotTruffleRuntime() {
+        installOptimizedCallTargetCallMethod();
+
+        callNodeMethod = new ResolvedJavaMethod[]{getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CallNodeFrame.METHOD)};
+        callTargetMethod = new ResolvedJavaMethod[]{getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CallTargetFrame.METHOD)};
+        anyFrameMethod = new ResolvedJavaMethod[]{callNodeMethod[0], callTargetMethod[0]};
+
+        // Create compilation queue.
+        CompilerThreadFactory factory = new CompilerThreadFactory("TruffleCompilerThread", new CompilerThreadFactory.DebugConfigAccess() {
+            public GraalDebugConfig getDebugConfig() {
+                if (Debug.isEnabled()) {
+                    GraalDebugConfig debugConfig = DebugEnvironment.initialize(TTY.out().out());
+                    debugConfig.dumpHandlers().add(new TruffleTreeDumpHandler());
+                    return debugConfig;
+                } else {
+                    return null;
+                }
+            }
+        });
+        compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), factory);
+    }
+
+    public String getName() {
+        return "Graal Truffle Runtime";
+    }
+
+    public RootCallTarget createCallTarget(RootNode rootNode) {
+        CompilationPolicy compilationPolicy;
+        if (acceptForCompilation(rootNode)) {
+            compilationPolicy = new CounterBasedCompilationPolicy();
+        } else {
+            compilationPolicy = new InterpreterOnlyCompilationPolicy();
+        }
+        return new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, new HotSpotSpeculationLog());
+    }
+
+    public DirectCallNode createDirectCallNode(CallTarget target) {
+        if (target instanceof OptimizedCallTarget) {
+            return OptimizedDirectCallNode.create((OptimizedCallTarget) target);
+        } else {
+            return new DefaultDirectCallNode(target);
+        }
+    }
+
+    public IndirectCallNode createIndirectCallNode() {
+        return new OptimizedIndirectCallNode();
+    }
+
+    @Override
+    public VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
+        return OptimizedCallTarget.createFrame(frameDescriptor, arguments);
+    }
+
+    @Override
+    public MaterializedFrame createMaterializedFrame(Object[] arguments) {
+        return createMaterializedFrame(arguments, new FrameDescriptor());
+    }
+
+    @Override
+    public MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
+        return new FrameWithoutBoxing(frameDescriptor, arguments);
+    }
+
+    @Override
+    public Assumption createAssumption() {
+        return createAssumption(null);
+    }
+
+    @Override
+    public Assumption createAssumption(String name) {
+        return new OptimizedAssumption(name);
+    }
+
+    public Replacements getReplacements() {
+        if (truffleReplacements == null) {
+            truffleReplacements = HotSpotTruffleReplacements.makeInstance();
+        }
+        return truffleReplacements;
+    }
+
+    private boolean acceptForCompilation(RootNode rootNode) {
+        if (TruffleCompileOnly.getValue() != null) {
+            if (includes == null) {
+                parseCompileOnly();
+            }
+
+            String name = rootNode.toString();
+            boolean included = includes.isEmpty();
+            for (int i = 0; !included && i < includes.size(); i++) {
+                if (name.contains(includes.get(i))) {
+                    included = true;
+                }
+            }
+            if (!included) {
+                return false;
+            }
+            for (String exclude : excludes) {
+                if (name.contains(exclude)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private void parseCompileOnly() {
+        includes = new ArrayList<>();
+        excludes = new ArrayList<>();
+
+        String[] items = TruffleCompileOnly.getValue().split(",");
+        for (String item : items) {
+            if (item.startsWith("~")) {
+                excludes.add(item.substring(1));
+            } else {
+                includes.add(item);
+            }
+        }
+    }
+
+    public static void installOptimizedCallTargetCallMethod() {
+        Providers providers = getGraalProviders();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        ResolvedJavaType type = metaAccess.lookupJavaType(OptimizedCallTarget.class);
+        for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+            if (method.getAnnotation(TruffleCallBoundary.class) != null) {
+                CompilationResult compResult = compileMethod(method);
+                CodeCacheProvider codeCache = providers.getCodeCache();
+                try (Scope s = Debug.scope("CodeInstall", codeCache, method)) {
+                    codeCache.setDefaultMethod(method, compResult);
+                }
+            }
+        }
+    }
+
+    private static CompilationResultBuilderFactory getOptimizedCallTargetInstrumentationFactory(String arch, ResolvedJavaMethod method) {
+        for (OptimizedCallTargetInstrumentationFactory factory : ServiceLoader.loadInstalled(OptimizedCallTargetInstrumentationFactory.class)) {
+            if (factory.getArchitecture().equals(arch)) {
+                factory.setInstrumentedMethod(method);
+                return factory;
+            }
+        }
+        // No specialization of OptimizedCallTarget on this platform.
+        return CompilationResultBuilderFactory.Default;
+    }
+
+    private static CompilationResult compileMethod(ResolvedJavaMethod javaMethod) {
+        Providers providers = getGraalProviders();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites();
+        Suites suites = suitesProvider.createSuites();
+        suites.getHighTier().findPhase(InliningPhase.class).remove();
+        StructuredGraph graph = new StructuredGraph(javaMethod);
+        new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+        PhaseSuite<HighTierContext> graphBuilderSuite = suitesProvider.getDefaultGraphBuilderSuite();
+        CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
+        Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
+        CompilationResultBuilderFactory factory = getOptimizedCallTargetInstrumentationFactory(backend.getTarget().arch.getName(), javaMethod);
+        return compileGraph(graph, null, cc, javaMethod, providers, backend, providers.getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), null,
+                        suites, new CompilationResult(), factory);
+    }
+
+    private static Providers getGraalProviders() {
+        RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
+        return runtimeProvider.getHostBackend().getProviders();
+    }
+
+    @SlowPath
+    public Iterable<FrameInstance> getStackTrace() {
+        if (stackIntrospection == null) {
+            stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class);
+        }
+        final Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(anyFrameMethod, anyFrameMethod, 1).iterator();
+        class FrameIterator implements Iterator<FrameInstance> {
+
+            public boolean hasNext() {
+                return frames.hasNext();
+            }
+
+            public FrameInstance next() {
+                InspectedFrame frame = frames.next();
+                if (frame.getMethod().equals(callNodeMethod[0])) {
+                    assert frames.hasNext();
+                    InspectedFrame calltarget2 = frames.next();
+                    assert calltarget2.getMethod().equals(callTargetMethod[0]);
+                    return new HotSpotFrameInstance.CallNodeFrame(frame);
+                } else {
+                    assert frame.getMethod().equals(callTargetMethod[0]);
+                    return new HotSpotFrameInstance.CallTargetFrame(frame, false);
+                }
+            }
+        }
+        return new Iterable<FrameInstance>() {
+            public Iterator<FrameInstance> iterator() {
+                return new FrameIterator();
+            }
+        };
+    }
+
+    public FrameInstance getCurrentFrame() {
+        if (stackIntrospection == null) {
+            stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class);
+        }
+        Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(callTargetMethod, callTargetMethod, 0).iterator();
+        if (frames.hasNext()) {
+            return new HotSpotFrameInstance.CallTargetFrame(frames.next(), true);
+        } else {
+            System.out.println("no current frame found");
+            return null;
+        }
+    }
+
+    public void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous) {
+        if (truffleCompiler == null) {
+            truffleCompiler = new TruffleCompilerImpl();
+        }
+        Runnable r = new Runnable() {
+            @Override
+            public void run() {
+                try (Scope s = Debug.scope("Truffle", new TruffleDebugJavaMethod(optimizedCallTarget))) {
+                    truffleCompiler.compileMethodImpl(optimizedCallTarget);
+                    optimizedCallTarget.compilationFinished(null);
+                } catch (Throwable e) {
+                    optimizedCallTarget.compilationFinished(e);
+                }
+            }
+        };
+        if (mayBeAsynchronous) {
+            Future<?> future = compileQueue.submit(r);
+            this.compilations.put(optimizedCallTarget, future);
+        } else {
+            r.run();
+        }
+    }
+
+    public boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget) {
+        Future<?> codeTask = this.compilations.get(optimizedCallTarget);
+        if (codeTask != null && isCompiling(optimizedCallTarget)) {
+            this.compilations.remove(optimizedCallTarget);
+            return codeTask.cancel(true);
+        }
+        return false;
+    }
+
+    public boolean isCompiling(OptimizedCallTarget optimizedCallTarget) {
+        Future<?> codeTask = this.compilations.get(optimizedCallTarget);
+        if (codeTask != null) {
+            if (codeTask.isCancelled() || codeTask.isDone()) {
+                this.compilations.remove(optimizedCallTarget);
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget) {
+        HotSpotGraalRuntime.runtime().getCompilerToVM().invalidateInstalledCode(optimizedCallTarget);
+    }
+
+    public void reinstallStubs() {
+        installOptimizedCallTargetCallMethod();
+    }
+}
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.hotspot.meta.*;
@@ -55,7 +55,7 @@
         return mark;
     }
 
-    protected static int getFieldOffset(String name, Class declaringClass) {
+    protected static int getFieldOffset(String name, Class<?> declaringClass) {
         try {
             declaringClass.getDeclaredField(name).setAccessible(true);
             Field field = declaringClass.getDeclaredField(name);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/ReadOnlyFrame.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,134 @@
+/*
+ * 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.hotspot;
+
+import com.oracle.graal.compiler.common.*;
+import com.oracle.truffle.api.frame.*;
+
+class ReadOnlyFrame implements Frame {
+    private final Frame delegate;
+
+    public ReadOnlyFrame(Frame delegate) {
+        this.delegate = delegate;
+    }
+
+    public FrameDescriptor getFrameDescriptor() {
+        return delegate.getFrameDescriptor();
+    }
+
+    public Object[] getArguments() {
+        return delegate.getArguments().clone();
+    }
+
+    public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
+        return delegate.getObject(slot);
+    }
+
+    public void setObject(FrameSlot slot, Object value) {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public byte getByte(FrameSlot slot) throws FrameSlotTypeException {
+        return delegate.getByte(slot);
+    }
+
+    public void setByte(FrameSlot slot, byte value) {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
+        return delegate.getBoolean(slot);
+    }
+
+    public void setBoolean(FrameSlot slot, boolean value) {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public int getInt(FrameSlot slot) throws FrameSlotTypeException {
+        return delegate.getInt(slot);
+    }
+
+    public void setInt(FrameSlot slot, int value) {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public long getLong(FrameSlot slot) throws FrameSlotTypeException {
+        return delegate.getLong(slot);
+    }
+
+    public void setLong(FrameSlot slot, long value) {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
+        return delegate.getFloat(slot);
+    }
+
+    public void setFloat(FrameSlot slot, float value) {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
+        return delegate.getDouble(slot);
+    }
+
+    public void setDouble(FrameSlot slot, double value) {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public Object getValue(FrameSlot slot) {
+        return delegate.getValue(slot);
+    }
+
+    public MaterializedFrame materialize() {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public boolean isObject(FrameSlot slot) {
+        return delegate.isObject(slot);
+    }
+
+    public boolean isByte(FrameSlot slot) {
+        return delegate.isByte(slot);
+    }
+
+    public boolean isBoolean(FrameSlot slot) {
+        return delegate.isBoolean(slot);
+    }
+
+    public boolean isInt(FrameSlot slot) {
+        return delegate.isInt(slot);
+    }
+
+    public boolean isLong(FrameSlot slot) {
+        return delegate.isLong(slot);
+    }
+
+    public boolean isFloat(FrameSlot slot) {
+        return delegate.isFloat(slot);
+    }
+
+    public boolean isDouble(FrameSlot slot) {
+        return delegate.isDouble(slot);
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -51,7 +51,7 @@
 
     public PartialEvaluationTest() {
         // Make sure Truffle runtime is initialized.
-        Assert.assertTrue(Truffle.getRuntime() instanceof GraalTruffleRuntime);
+        Assert.assertTrue(Truffle.getRuntime() != null);
         this.truffleCompiler = new TruffleCompilerImpl();
 
         DebugEnvironment.initialize(System.out);
@@ -64,7 +64,8 @@
     protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, Object[] arguments) {
         Assumptions assumptions = new Assumptions(true);
         StructuredGraph actual = partialEval(root, arguments, assumptions, true);
-        InstalledCode result = truffleCompiler.compileMethodHelper(actual, assumptions, root.toString(), getSpeculationLog());
+        InstalledCode result = new InstalledCode();
+        truffleCompiler.compileMethodHelper(actual, assumptions, root.toString(), getSpeculationLog(), result);
         StructuredGraph expected = parseForComparison(methodName);
         removeFrameStates(actual);
         Assert.assertEquals(getCanonicalGraphString(expected, true, true), getCanonicalGraphString(actual, true, true));
@@ -85,7 +86,7 @@
     }
 
     protected StructuredGraph partialEval(RootNode root, Object[] arguments, final Assumptions assumptions, final boolean canonicalizeReads) {
-        final OptimizedCallTargetImpl compilable = (OptimizedCallTargetImpl) Truffle.getRuntime().createCallTarget(root);
+        final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root);
 
         // Executed AST so that all classes are loaded and initialized.
         compilable.call(arguments);
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,8 +28,8 @@
 
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.runtime.*;
-import com.oracle.graal.truffle.*;
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.impl.*;
 
 public class TruffleRuntimeTest {
 
@@ -46,6 +46,6 @@
     @Test
     public void testRuntimeIsGraalRuntime() {
         TruffleRuntime runtime = Truffle.getRuntime();
-        assertEquals(GraalTruffleRuntime.class, runtime.getClass());
+        assertTrue(runtime.getClass() != DefaultTruffleRuntime.class);
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,4 +26,6 @@
 
     boolean shouldCompile(CompilationProfile profile);
 
+    void recordCompilationFailure(Throwable t);
+
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Wed Apr 23 15:48:38 2014 +0200
@@ -40,8 +40,6 @@
 
     private long previousTimestamp;
 
-    private final String name;
-
     private int callCount;
     private int callAndLoopCount;
     private int compilationCallThreshold;
@@ -50,13 +48,17 @@
     private final int originalInvokeCounter;
     private final int originalCompilationThreshold;
 
-    public CompilationProfile(final int compilationThreshold, final int initialInvokeCounter, final String name) {
+    public CompilationProfile(final int compilationThreshold, final int initialInvokeCounter) {
         this.previousTimestamp = System.nanoTime();
         this.compilationCallThreshold = initialInvokeCounter;
         this.compilationCallAndLoopThreshold = compilationThreshold;
         this.originalInvokeCounter = initialInvokeCounter;
         this.originalCompilationThreshold = compilationThreshold;
-        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("CompilationProfile(callCount=%d/%d, callAndLoopCount=%d/%d)", callCount, compilationCallThreshold, callAndLoopCount, compilationCallAndLoopThreshold);
     }
 
     public Map<String, Object> getDebugProperties() {
@@ -81,10 +83,6 @@
         return previousTimestamp;
     }
 
-    public String getName() {
-        return this.name;
-    }
-
     public int getInvalidationCount() {
         return invalidationCount;
     }
@@ -126,7 +124,7 @@
         this.previousTimestamp = timestamp;
     }
 
-    void reportInvalidated() {
+    public void reportInvalidated() {
         invalidationCount++;
         int reprofile = TruffleInvalidationReprofileCount.getValue();
         ensureProfiling(reprofile, reprofile);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CounterBasedCompilationPolicy.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+public class CounterBasedCompilationPolicy implements CompilationPolicy {
+
+    private boolean compilationFailed;
+
+    public boolean shouldCompile(CompilationProfile profile) {
+        return !compilationFailed && profile.getCallCount() >= profile.getCompilationCallThreshold() && profile.getCallAndLoopCount() >= profile.getCompilationCallAndLoopThreshold();
+    }
+
+    public void recordCompilationFailure(Throwable t) {
+        compilationFailed = true;
+    }
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultCompilationPolicy.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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;
-
-public class DefaultCompilationPolicy implements CompilationPolicy {
-
-    public boolean shouldCompile(CompilationProfile profile) {
-        return profile.getCallCount() >= profile.getCompilationCallThreshold() && profile.getCallAndLoopCount() >= profile.getCompilationCallAndLoopThreshold();
-    }
-
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,29 +27,25 @@
 public class DefaultInliningPolicy implements TruffleInliningPolicy {
 
     private static final String REASON_RECURSION = "recursion";
-    private static final String REASON_MAXIMUM_NODE_COUNT = "nodeCount * callSites  > " + TruffleInliningMaxCallerSize.getValue();
+    private static final String REASON_MAXIMUM_NODE_COUNT = "deepNodeCount * callSites  > " + TruffleInliningMaxCallerSize.getValue();
     private static final String REASON_MAXIMUM_TOTAL_NODE_COUNT = "totalNodeCount > " + TruffleInliningMaxCallerSize.getValue();
 
     public double calculateScore(TruffleInliningProfile profile) {
         return profile.getFrequency() / profile.getDeepNodeCount();
     }
 
-    public boolean isAllowed(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget) {
-        TruffleCallPath callPath = profile.getCallPath();
-        OptimizedCallTarget inlineTarget = callPath.getCallTarget();
-        for (TruffleCallPath path : callPath.getParent().toList()) {
-            if (path.getCallTarget() == inlineTarget) {
-                // recursive call found
-                profile.setFailedReason(REASON_RECURSION);
-                return false;
-            }
+    public boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft) {
+        if (profile.isRecursiveCall()) {
+            // recursive call found
+            profile.setFailedReason(REASON_RECURSION);
+            return false;
         }
 
         if (profile.isForced()) {
             return true;
         }
 
-        if (nodeCountBudget - profile.getDeepNodeCount() < 0) {
+        if (currentBudgetLeft - profile.getDeepNodeCount() < 0) {
             profile.setFailedReason(REASON_MAXIMUM_TOTAL_NODE_COUNT);
             return false;
         }
@@ -62,9 +58,4 @@
 
         return true;
     }
-
-    public boolean isAllowedDeep(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget) {
-        return true;
-    }
-
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Wed Apr 23 15:48:38 2014 +0200
@@ -45,10 +45,11 @@
     public FrameWithoutBoxing(FrameDescriptor descriptor, Object[] arguments) {
         this.descriptor = descriptor;
         this.arguments = arguments;
-        this.locals = new Object[descriptor.getSize()];
+        int size = descriptor.getSize();
+        this.locals = new Object[size];
         Arrays.fill(locals, descriptor.getTypeConversion().getDefaultValue());
-        this.primitiveLocals = new long[descriptor.getSize()];
-        this.tags = new byte[descriptor.getSize()];
+        this.primitiveLocals = new long[size];
+        this.tags = new byte[size];
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,193 +22,20 @@
  */
 package com.oracle.graal.truffle;
 
-import static com.oracle.graal.api.code.CodeUtil.*;
-import static com.oracle.graal.compiler.GraalCompiler.*;
-import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-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.runtime.*;
-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.java.*;
-import com.oracle.graal.lir.asm.*;
-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.phases.util.*;
-import com.oracle.graal.runtime.*;
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.impl.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Implementation of the Truffle runtime when running on top of Graal.
- */
-public final class GraalTruffleRuntime implements TruffleRuntime {
-
-    public static GraalTruffleRuntime makeInstance() {
-        return new GraalTruffleRuntime();
-    }
-
-    private TruffleCompiler truffleCompiler;
-    private Replacements truffleReplacements;
-    private ArrayList<String> includes;
-    private ArrayList<String> excludes;
 
-    private GraalTruffleRuntime() {
-        installOptimizedCallTargetCallMethod();
-    }
-
-    public String getName() {
-        return "Graal Truffle Runtime";
-    }
-
-    public RootCallTarget createCallTarget(RootNode rootNode) {
-        if (truffleCompiler == null) {
-            truffleCompiler = new TruffleCompilerImpl();
-        }
-        return new OptimizedCallTargetImpl(rootNode, truffleCompiler, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), acceptForCompilation(rootNode));
-    }
-
-    public CallNode createCallNode(CallTarget target) {
-        if (target instanceof OptimizedCallTarget) {
-            return OptimizedCallNode.create((OptimizedCallTarget) target);
-        } else {
-            return new DefaultCallNode(target);
-        }
-    }
+public interface GraalTruffleRuntime extends TruffleRuntime {
 
-    @Override
-    public VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
-        return OptimizedCallTargetImpl.createFrame(frameDescriptor, arguments);
-    }
-
-    @Override
-    public MaterializedFrame createMaterializedFrame(Object[] arguments) {
-        return createMaterializedFrame(arguments, new FrameDescriptor());
-    }
+    Replacements getReplacements();
 
-    @Override
-    public MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
-        return new FrameWithoutBoxing(frameDescriptor, arguments);
-    }
-
-    @Override
-    public Assumption createAssumption() {
-        return createAssumption(null);
-    }
-
-    @Override
-    public Assumption createAssumption(String name) {
-        return new OptimizedAssumption(name);
-    }
+    void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous);
 
-    public Replacements getReplacements() {
-        if (truffleReplacements == null) {
-            truffleReplacements = TruffleReplacements.makeInstance();
-        }
-        return truffleReplacements;
-    }
-
-    private boolean acceptForCompilation(RootNode rootNode) {
-        if (TruffleCompileOnly.getValue() != null) {
-            if (includes == null) {
-                parseCompileOnly();
-            }
+    boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget);
 
-            String name = rootNode.toString();
-            boolean included = includes.isEmpty();
-            for (int i = 0; !included && i < includes.size(); i++) {
-                if (name.contains(includes.get(i))) {
-                    included = true;
-                }
-            }
-            if (!included) {
-                return false;
-            }
-            for (String exclude : excludes) {
-                if (name.contains(exclude)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private void parseCompileOnly() {
-        includes = new ArrayList<>();
-        excludes = new ArrayList<>();
-
-        String[] items = TruffleCompileOnly.getValue().split(",");
-        for (String item : items) {
-            if (item.startsWith("~")) {
-                excludes.add(item.substring(1));
-            } else {
-                includes.add(item);
-            }
-        }
-    }
+    boolean isCompiling(OptimizedCallTarget optimizedCallTarget);
 
-    public static void installOptimizedCallTargetCallMethod() {
-        Providers providers = getGraalProviders();
-        MetaAccessProvider metaAccess = providers.getMetaAccess();
-        CodeCacheProvider codeCache = providers.getCodeCache();
-        ResolvedJavaMethod resolvedCallMethod = metaAccess.lookupJavaMethod(getCallMethod());
-        CompilationResult compResult = compileMethod(resolvedCallMethod);
-        try (Scope s = Debug.scope("CodeInstall", codeCache, resolvedCallMethod)) {
-            codeCache.setDefaultMethod(resolvedCallMethod, compResult);
-        }
-    }
-
-    private static Method getCallMethod() {
-        Method method;
-        try {
-            method = OptimizedCallTargetImpl.class.getDeclaredMethod("call", new Class[]{Object[].class});
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-        return method;
-    }
+    void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget);
 
-    private static CompilationResultBuilderFactory getOptimizedCallTargetInstrumentationFactory(String arch, ResolvedJavaMethod method) {
-        for (OptimizedCallTargetInstrumentationFactory factory : ServiceLoader.loadInstalled(OptimizedCallTargetInstrumentationFactory.class)) {
-            if (factory.getArchitecture().equals(arch)) {
-                factory.setInstrumentedMethod(method);
-                return factory;
-            }
-        }
-        // No specialization of OptimizedCallTarget on this platform.
-        return CompilationResultBuilderFactory.Default;
-    }
-
-    private static CompilationResult compileMethod(ResolvedJavaMethod javaMethod) {
-        Providers providers = getGraalProviders();
-        MetaAccessProvider metaAccess = providers.getMetaAccess();
-        SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites();
-        Suites suites = suitesProvider.createSuites();
-        suites.getHighTier().findPhase(InliningPhase.class).remove();
-        StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
-        PhaseSuite<HighTierContext> graphBuilderSuite = suitesProvider.getDefaultGraphBuilderSuite();
-        CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
-        Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
-        CompilationResultBuilderFactory factory = getOptimizedCallTargetInstrumentationFactory(backend.getTarget().arch.getName(), javaMethod);
-        return compileGraph(graph, null, cc, javaMethod, providers, backend, providers.getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), null,
-                        suites, new CompilationResult(), factory);
-    }
-
-    private static Providers getGraalProviders() {
-        RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
-        return runtimeProvider.getHostBackend().getProviders();
-    }
+    void reinstallStubs();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/InterpreterOnlyCompilationPolicy.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+public class InterpreterOnlyCompilationPolicy implements CompilationPolicy {
+
+    public boolean shouldCompile(CompilationProfile profile) {
+        return false;
+    }
+
+    public void recordCompilationFailure(Throwable t) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/MaterializedFrameNotify.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+import com.oracle.truffle.api.frame.FrameInstance.*;
+
+public interface MaterializedFrameNotify {
+
+    FrameAccess getOutsideFrameAccess();
+
+    void setOutsideFrameAccess(FrameAccess outsideFrameAccess);
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.truffle;
 
 import java.lang.ref.*;
-import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.truffle.api.impl.*;
@@ -31,7 +30,13 @@
 
 public final class OptimizedAssumption extends AbstractAssumption {
 
-    List<WeakReference<InstalledCode>> dependentInstalledCode;
+    private static class Entry {
+        WeakReference<InstalledCode> installedCode;
+        long version;
+        Entry next;
+    }
+
+    private Entry first;
 
     public OptimizedAssumption(String name) {
         super(name);
@@ -47,25 +52,26 @@
     @Override
     public synchronized void invalidate() {
         if (isValid) {
-            if (dependentInstalledCode != null) {
-                for (WeakReference<InstalledCode> installedCodeReference : dependentInstalledCode) {
-                    InstalledCode installedCode = installedCodeReference.get();
-                    if (installedCode != null) {
-                        installedCode.invalidate();
-                    }
+            Entry e = first;
+            while (e != null) {
+                InstalledCode installedCode = e.installedCode.get();
+                if (installedCode != null && installedCode.getVersion() == e.version) {
+                    installedCode.invalidate();
                 }
-                dependentInstalledCode = null;
+                e = e.next;
             }
+            first = null;
             isValid = false;
         }
     }
 
     public synchronized void registerInstalledCode(InstalledCode installedCode) {
         if (isValid) {
-            if (dependentInstalledCode == null) {
-                dependentInstalledCode = new ArrayList<>();
-            }
-            dependentInstalledCode.add(new WeakReference<>(installedCode));
+            Entry e = new Entry();
+            e.installedCode = new WeakReference<>(installedCode);
+            e.version = installedCode.getVersion();
+            e.next = first;
+            first = e;
         } else {
             installedCode.invalidate();
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +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 java.util.concurrent.atomic.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.impl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter;
-
-/**
- * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
- */
-public final class OptimizedCallNode extends DefaultCallNode {
-
-    protected int callCount;
-    private boolean trySplit = true;
-    private boolean inliningForced;
-    @CompilationFinal private OptimizedCallTarget splitCallTarget;
-    private final AtomicInteger inliningCounter = new AtomicInteger(0);
-
-    private OptimizedCallNode(OptimizedCallTarget target) {
-        super(target);
-    }
-
-    @Override
-    public boolean isSplittable() {
-        return getCallTarget().getRootNode().isSplittable();
-    }
-
-    @Override
-    public OptimizedCallTarget getCallTarget() {
-        return (OptimizedCallTarget) super.getCallTarget();
-    }
-
-    public int getCallCount() {
-        return callCount;
-    }
-
-    @Override
-    public OptimizedCallTarget getCurrentCallTarget() {
-        return (OptimizedCallTarget) super.getCurrentCallTarget();
-    }
-
-    @Override
-    public OptimizedCallTarget getSplitCallTarget() {
-        return splitCallTarget;
-    }
-
-    public static OptimizedCallNode create(OptimizedCallTarget target) {
-        return new OptimizedCallNode(target);
-    }
-
-    @Override
-    public Object call(Object[] arguments) {
-        if (CompilerDirectives.inInterpreter()) {
-            interpreterCall();
-            if (inliningCounter.get() > 0 || inliningForced) {
-                return getCurrentCallTarget().callInlined(arguments);
-            }
-        }
-        return getCurrentCallTarget().call(arguments);
-    }
-
-    private void interpreterCall() {
-        callCount++;
-        if (trySplit) {
-            if (callCount == 1) {
-                // on first call
-                getCurrentCallTarget().incrementKnownCallSite();
-            }
-            if (callCount > 1) {
-                trySplit = false;
-                if (shouldSplit()) {
-                    splitImpl(true);
-                }
-            }
-        }
-    }
-
-    void notifyInlining() {
-        inliningCounter.incrementAndGet();
-    }
-
-    void notifyInliningDone() {
-        inliningCounter.decrementAndGet();
-    }
-
-    @Override
-    public void inline() {
-        inliningForced = true;
-    }
-
-    @Override
-    public boolean isInlined() {
-        return inliningForced;
-    }
-
-    private void splitImpl(boolean heuristic) {
-        CompilerAsserts.neverPartOfCompilation();
-
-        OptimizedCallTarget splitTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(getCallTarget().getRootNode().split());
-        splitTarget.setSplitSource(getCallTarget());
-        if (heuristic) {
-            OptimizedCallTarget.logSplit(this, getCallTarget(), splitTarget);
-        }
-        if (callCount >= 1) {
-            getCallTarget().decrementKnownCallSite();
-            splitTarget.incrementKnownCallSite();
-        }
-        this.splitCallTarget = splitTarget;
-    }
-
-    private boolean shouldSplit() {
-        if (splitCallTarget != null) {
-            return false;
-        }
-        if (!TruffleCompilerOptions.TruffleSplittingEnabled.getValue()) {
-            return false;
-        }
-        if (!isSplittable()) {
-            return false;
-        }
-        OptimizedCallTarget splitTarget = getCallTarget();
-        int nodeCount = OptimizedCallUtils.countNonTrivialNodes(null, new TruffleCallPath(splitTarget));
-        if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) {
-            return false;
-        }
-
-        // disable recursive splitting for now
-        OptimizedCallTarget root = (OptimizedCallTarget) getRootNode().getCallTarget();
-        if (root == splitTarget || root.getSplitSource() == splitTarget) {
-            // recursive call found
-            return false;
-        }
-
-        // max one child call and callCount > 2 and kind of small number of nodes
-        if (isMaxSingleCall()) {
-            return true;
-        }
-        return countPolymorphic() >= 1;
-    }
-
-    private boolean isMaxSingleCall() {
-        return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() {
-            public boolean isCounted(Node node) {
-                return node instanceof CallNode;
-            }
-        }) <= 1;
-    }
-
-    private int countPolymorphic() {
-        return NodeUtil.countNodes(getCallTarget().getRootNode(), new NodeCountFilter() {
-            public boolean isCounted(Node node) {
-                NodeCost cost = node.getCost();
-                boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC;
-                return polymorphic;
-            }
-        });
-    }
-
-    @SuppressWarnings("unused")
-    public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) {
-        if (!isSplit() && isSplittable()) {
-            trySplit = true;
-        }
-    }
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.truffle;
 
+import static com.oracle.graal.truffle.OptimizedCallTargetLog.*;
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
 import java.io.*;
@@ -30,56 +31,177 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.truffle.OptimizedCallUtils.InlinedNodeCountFilter;
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
 
 /**
  * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
  */
-public abstract class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, ReplaceObserver {
+public class OptimizedCallTarget extends InstalledCode implements RootCallTarget, LoopCountReceiver, ReplaceObserver {
 
     protected static final PrintStream OUT = TTY.out().out();
 
-    protected InstalledCode installedCode;
-    protected boolean compilationEnabled;
+    protected final GraalTruffleRuntime runtime;
+    private SpeculationLog speculationLog;
     protected int callCount;
-    protected TruffleInliningResult inliningResult;
+    protected boolean inliningPerformed;
     protected final CompilationProfile compilationProfile;
     protected final CompilationPolicy compilationPolicy;
-    private final SpeculationLog speculationLog = new SpeculationLog();
     private OptimizedCallTarget splitSource;
+    private final AtomicInteger callSitesKnown = new AtomicInteger(0);
+    @CompilationFinal private Class<?>[] profiledArgumentTypes;
+    @CompilationFinal private Assumption profiledArgumentTypesAssumption;
+    @CompilationFinal private Class<?> profiledReturnType;
+    @CompilationFinal private Assumption profiledReturnTypeAssumption;
 
-    private final AtomicInteger callSitesKnown = new AtomicInteger(0);
+    private final RootNode rootNode;
 
-    public OptimizedCallTarget(RootNode rootNode, int invokeCounter, int compilationThreshold, boolean compilationEnabled, CompilationPolicy compilationPolicy) {
-        super(rootNode);
-        this.compilationEnabled = compilationEnabled;
+    public final RootNode getRootNode() {
+        return rootNode;
+    }
+
+    public OptimizedCallTarget(RootNode rootNode, GraalTruffleRuntime runtime, int invokeCounter, int compilationThreshold, CompilationPolicy compilationPolicy, SpeculationLog speculationLog) {
+        this.runtime = runtime;
+        this.speculationLog = speculationLog;
+        this.rootNode = rootNode;
+        this.rootNode.adoptChildren();
+        this.rootNode.setCallTarget(this);
         this.compilationPolicy = compilationPolicy;
-        this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter, rootNode.toString());
+        this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter);
         if (TruffleCallTargetProfiling.getValue()) {
             registerCallTarget(this);
         }
     }
 
+    public SpeculationLog getSpeculationLog() {
+        return speculationLog;
+    }
+
+    @Override
+    public Object call(Object... args) {
+        return callBoundary(args);
+    }
+
+    public Object callDirect(Object... args) {
+        if (profiledArgumentTypesAssumption == null) {
+            CompilerDirectives.transferToInterpreter();
+            profiledArgumentTypesAssumption = Truffle.getRuntime().createAssumption("Profiled Argument Types");
+            profiledArgumentTypes = new Class<?>[args.length];
+        } else if (profiledArgumentTypes != null) {
+            if (profiledArgumentTypes.length != args.length) {
+                CompilerDirectives.transferToInterpreter();
+                profiledArgumentTypesAssumption.invalidate();
+                profiledArgumentTypes = null;
+            }
+        }
+
+        Object result = callBoundary(args);
+        Class<?> klass = profiledReturnType;
+        if (klass != null && CompilerDirectives.inCompiledCode() && profiledReturnTypeAssumption.isValid()) {
+            result = CompilerDirectives.unsafeCast(result, klass, true, true);
+        }
+        return result;
+    }
+
+    @TruffleCallBoundary
+    private Object callBoundary(Object[] args) {
+        if (CompilerDirectives.inInterpreter()) {
+            // We are called and we are still in Truffle interpreter mode.
+            CompilerDirectives.transferToInterpreter();
+            interpreterCall();
+        } else {
+            // We come here from compiled code (i.e., we have been inlined).
+        }
+
+        return callRoot(args);
+    }
+
+    @Override
+    public void invalidate() {
+        this.runtime.invalidateInstalledCode(this);
+    }
+
+    protected void invalidate(Node oldNode, Node newNode, CharSequence reason) {
+        if (isValid()) {
+            CompilerAsserts.neverPartOfCompilation();
+            invalidate();
+            compilationProfile.reportInvalidated();
+            logOptimizedInvalidated(this, oldNode, newNode, reason);
+        }
+        cancelInstalledTask(oldNode, newNode, reason);
+    }
+
+    private void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) {
+        if (this.runtime.cancelInstalledTask(this)) {
+            logOptimizingUnqueued(this, oldNode, newNode, reason);
+            compilationProfile.reportInvalidated();
+        }
+    }
+
+    private void interpreterCall() {
+        CompilerAsserts.neverPartOfCompilation();
+        if (this.isValid()) {
+            // Stubs were deoptimized => reinstall.
+            this.runtime.reinstallStubs();
+        } else {
+            compilationProfile.reportInterpreterCall();
+            if (TruffleCallTargetProfiling.getValue()) {
+                callCount++;
+            }
+            if (compilationPolicy.shouldCompile(compilationProfile)) {
+                compile();
+            }
+        }
+    }
+
+    public void compile() {
+        if (!runtime.isCompiling(this)) {
+            performInlining();
+            logOptimizingQueued(this);
+            runtime.compile(this, TruffleBackgroundCompilation.getValue());
+        }
+    }
+
+    public void compilationFinished(Throwable t) {
+        if (t == null) {
+            // Compilation was successful.
+        } else {
+            compilationPolicy.recordCompilationFailure(t);
+            logOptimizingFailed(this, t.getMessage());
+            if (t instanceof BailoutException) {
+                // Bailout => move on.
+            } else {
+                if (TruffleCompilationExceptionsAreFatal.getValue()) {
+                    t.printStackTrace(OUT);
+                    System.exit(-1);
+                }
+            }
+        }
+    }
+
+    protected final Object callProxy(VirtualFrame frame) {
+        try {
+            return getRootNode().execute(frame);
+        } finally {
+            // this assertion is needed to keep the values from being cleared as non-live locals
+            assert frame != null && this != null;
+        }
+    }
+
     public final int getKnownCallSiteCount() {
         return callSitesKnown.get();
     }
 
-    public final void incrementKnownCallSite() {
+    public final void incrementKnownCallSites() {
         callSitesKnown.incrementAndGet();
     }
 
-    public final void decrementKnownCallSite() {
+    public final void decrementKnownCallSites() {
         callSitesKnown.decrementAndGet();
     }
 
-    public final TruffleInliningResult getInliningResult() {
-        return inliningResult;
-    }
-
     public final OptimizedCallTarget getSplitSource() {
         return splitSource;
     }
@@ -90,8 +212,8 @@
 
     @Override
     public String toString() {
-        String superString = super.toString();
-        if (installedCode != null) {
+        String superString = rootNode.toString();
+        if (isValid()) {
             superString += " <compiled>";
         }
         if (splitSource != null) {
@@ -104,66 +226,68 @@
         return compilationProfile;
     }
 
-    @Override
-    public abstract Object call(Object[] args);
-
-    public abstract InstalledCode compile();
-
     public final Object callInlined(Object[] arguments) {
         if (CompilerDirectives.inInterpreter()) {
             compilationProfile.reportInlinedCall();
         }
-        return executeHelper(arguments);
+        VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), arguments);
+        return callProxy(frame);
     }
 
     public final void performInlining() {
-        if (!shouldInline()) {
+        if (!TruffleFunctionInlining.getValue()) {
+            return;
+        }
+        if (inliningPerformed) {
             return;
         }
-
-        if (inliningResult != null) {
-            return;
-        }
-
-        TruffleInliningHandler handler = new TruffleInliningHandler(this, new DefaultInliningPolicy(), new HashMap<OptimizedCallTarget, TruffleInliningResult>());
-        int startNodeCount = OptimizedCallUtils.countNonTrivialNodes(null, new TruffleCallPath(this));
-        this.inliningResult = handler.inline(startNodeCount);
-        logInliningDecision(this, inliningResult, handler);
+        inliningPerformed = true;
+        TruffleInliningHandler handler = new TruffleInliningHandler(new DefaultInliningPolicy());
+        TruffleInliningResult result = handler.decideInlining(this, 0);
+        performInlining(result);
+        logInliningDecision(result);
     }
 
-    protected boolean shouldCompile() {
-        return compilationPolicy.shouldCompile(compilationProfile);
-    }
-
-    protected static boolean shouldInline() {
-        return TruffleFunctionInlining.getValue();
-    }
-
-    protected final void cancelInlinedCallOptimization() {
-        if (getInliningResult() != null) {
-            for (TruffleCallPath path : getInliningResult()) {
-                OptimizedCallNode top = path.getCallNode();
-                top.notifyInlining();
-                top.getCurrentCallTarget().cancelInstalledTask(top, top, "Inlined");
+    private static void performInlining(TruffleInliningResult result) {
+        for (TruffleInliningProfile profile : result) {
+            profile.getCallNode().inline();
+            TruffleInliningResult recursiveResult = profile.getRecursiveResult();
+            if (recursiveResult != null) {
+                performInlining(recursiveResult);
             }
         }
     }
 
-    protected final void onCompilationDone() {
-        if (inliningResult != null) {
-            for (TruffleCallPath path : inliningResult) {
-                path.getCallNode().notifyInliningDone();
+    public final Object callRoot(Object[] originalArguments) {
+
+        Object[] args = originalArguments;
+        if (this.profiledArgumentTypesAssumption != null && CompilerDirectives.inCompiledCode() && profiledArgumentTypesAssumption.isValid()) {
+            args = CompilerDirectives.unsafeCast(castArrayFixedLength(args, profiledArgumentTypes.length), Object[].class, true, true);
+        }
+
+        VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args);
+        Object result = callProxy(frame);
+
+        // Profile call return type
+        if (profiledReturnTypeAssumption == null) {
+            if (TruffleReturnTypeSpeculation.getValue()) {
+                CompilerDirectives.transferToInterpreter();
+                profiledReturnType = result.getClass();
+                profiledReturnTypeAssumption = Truffle.getRuntime().createAssumption("Profiled Return Type");
+            }
+        } else if (profiledReturnType != null) {
+            if (result == null || profiledReturnType != result.getClass()) {
+                CompilerDirectives.transferToInterpreter();
+                profiledReturnType = null;
+                profiledReturnTypeAssumption.invalidate();
             }
         }
+
+        return result;
     }
 
-    protected abstract void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason);
-
-    protected abstract void invalidate(Node oldNode, Node newNode, CharSequence reason);
-
-    public final Object executeHelper(Object[] args) {
-        VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args);
-        return getRootNode().execute(frame);
+    private static Object castArrayFixedLength(Object[] args, @SuppressWarnings("unused") int length) {
+        return args;
     }
 
     public static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) {
@@ -181,244 +305,11 @@
         invalidate(oldNode, newNode, reason);
     }
 
-    public SpeculationLog getSpeculationLog() {
-        return speculationLog;
-    }
-
     public Map<String, Object> getDebugProperties() {
         Map<String, Object> properties = new LinkedHashMap<>();
-        addASTSizeProperty(getInliningResult(), new TruffleCallPath(this), properties);
+        addASTSizeProperty(this, properties);
         properties.putAll(getCompilationProfile().getDebugProperties());
         return properties;
 
     }
-
-    private static void logInliningDecision(OptimizedCallTarget target, TruffleInliningResult result, TruffleInliningHandler handler) {
-        if (!TraceTruffleInlining.getValue()) {
-            return;
-        }
-
-        List<TruffleInliningProfile> profiles = handler.lookupProfiles(result, new TruffleCallPath(target));
-
-        Collections.sort(profiles); // sorts by hierarchy and source section
-
-        logInliningStart(target);
-        for (TruffleInliningProfile profile : profiles) {
-            TruffleCallPath path = profile.getCallPath();
-            if (path.getRootCallTarget() == target) {
-                String msg = result.isInlined(path) ? "inline success" : "inline failed";
-                logInlinedImpl(msg, result, handler.getProfiles().get(path), path);
-            }
-        }
-        logInliningDone(target);
-    }
-
-    private static void logInlinedImpl(String status, TruffleInliningResult result, TruffleInliningProfile profile, TruffleCallPath path) {
-        Map<String, Object> properties = new LinkedHashMap<>();
-        addASTSizeProperty(result, path, properties);
-        if (profile != null) {
-            properties.putAll(profile.getDebugProperties());
-        }
-        log((path.getDepth() * 2), status, path.getCallTarget().toString(), properties);
-    }
-
-    private static void logInliningStart(OptimizedCallTarget target) {
-        if (TraceTruffleInlining.getValue()) {
-            log(0, "inline start", target.toString(), target.getDebugProperties());
-        }
-    }
-
-    private static void logInliningDone(OptimizedCallTarget target) {
-        if (TraceTruffleInlining.getValue()) {
-            log(0, "inline done", target.toString(), target.getDebugProperties());
-        }
-    }
-
-    protected static void logOptimizingQueued(OptimizedCallTarget target) {
-        if (TraceTruffleCompilationDetails.getValue()) {
-            log(0, "opt queued", target.toString(), target.getDebugProperties());
-        }
-    }
-
-    protected static void logOptimizingUnqueued(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) {
-        if (TraceTruffleCompilationDetails.getValue()) {
-            Map<String, Object> properties = new LinkedHashMap<>();
-            addReplaceProperties(properties, oldNode, newNode);
-            properties.put("Reason", reason);
-            log(0, "opt unqueued", target.toString(), properties);
-        }
-    }
-
-    private static void addReplaceProperties(Map<String, Object> properties, Node oldNode, Node newNode) {
-        if (oldNode != null && newNode != null) {
-            properties.put("OldClass", oldNode.getClass().getSimpleName());
-            properties.put("NewClass", newNode.getClass().getSimpleName());
-            properties.put("Node", newNode);
-        }
-    }
-
-    static void logOptimizingStart(OptimizedCallTarget target) {
-        if (TraceTruffleCompilationDetails.getValue()) {
-            log(0, "opt start", target.toString(), target.getDebugProperties());
-        }
-    }
-
-    protected static void logOptimizedInvalidated(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) {
-        if (TraceTruffleCompilation.getValue()) {
-            Map<String, Object> properties = new LinkedHashMap<>();
-            addReplaceProperties(properties, oldNode, newNode);
-            properties.put("Reason", reason);
-            log(0, "opt invalidated", target.toString(), properties);
-        }
-    }
-
-    protected static void logOptimizingFailed(OptimizedCallTarget callSite, CharSequence reason) {
-        Map<String, Object> properties = new LinkedHashMap<>();
-        properties.put("Reason", reason);
-        log(0, "opt fail", callSite.toString(), properties);
-    }
-
-    static void logOptimizingDone(OptimizedCallTarget target, Map<String, Object> properties) {
-        if (TraceTruffleCompilationDetails.getValue() || TraceTruffleCompilation.getValue()) {
-            log(0, "opt done", target.toString(), properties);
-        }
-        if (TraceTruffleCompilationPolymorphism.getValue()) {
-
-            target.getRootNode().accept(new NodeVisitor() {
-                public boolean visit(Node node) {
-                    NodeCost kind = node.getCost();
-                    if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) {
-                        Map<String, Object> props = new LinkedHashMap<>();
-                        props.put("simpleName", node.getClass().getSimpleName());
-                        String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic";
-                        log(0, msg, node.toString(), props);
-                    }
-                    if (node instanceof CallNode) {
-                        CallNode callNode = (CallNode) node;
-                        if (callNode.isInlined()) {
-                            callNode.getCurrentRootNode().accept(this);
-                        }
-                    }
-                    return true;
-                }
-            });
-
-        }
-    }
-
-    private static int splitCount = 0;
-
-    static void logSplit(OptimizedCallNode callNode, OptimizedCallTarget target, OptimizedCallTarget newTarget) {
-        if (TraceTruffleSplitting.getValue()) {
-            Map<String, Object> properties = new LinkedHashMap<>();
-            addASTSizeProperty(target.getInliningResult(), new TruffleCallPath(target), properties);
-            properties.put("Split#", ++splitCount);
-            properties.put("Source", callNode.getEncapsulatingSourceSection());
-            log(0, "split", newTarget.toString(), properties);
-        }
-    }
-
-    static void addASTSizeProperty(TruffleInliningResult inliningResult, TruffleCallPath countedPath, Map<String, Object> properties) {
-        int polymorphicCount = OptimizedCallUtils.countNodes(inliningResult, countedPath, new InlinedNodeCountFilter() {
-            public boolean isCounted(TruffleCallPath path, Node node) {
-                return node.getCost() == NodeCost.POLYMORPHIC;
-            }
-        });
-
-        int megamorphicCount = OptimizedCallUtils.countNodes(inliningResult, countedPath, new InlinedNodeCountFilter() {
-            public boolean isCounted(TruffleCallPath path, Node node) {
-                return node.getCost() == NodeCost.MEGAMORPHIC;
-            }
-        });
-
-        String value = String.format("%4d (%d/%d)", OptimizedCallUtils.countNonTrivialNodes(inliningResult, countedPath), polymorphicCount, megamorphicCount);
-        properties.put("ASTSize", value);
-    }
-
-    static void log(int indent, String msg, String details, Map<String, Object> properties) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(String.format("[truffle] %-16s ", msg));
-        for (int i = 0; i < indent; i++) {
-            sb.append(' ');
-        }
-        sb.append(String.format("%-" + (60 - indent) + "s", details));
-        if (properties != null) {
-            for (String property : properties.keySet()) {
-                Object value = properties.get(property);
-                if (value == null) {
-                    continue;
-                }
-                sb.append('|');
-                sb.append(property);
-
-                StringBuilder propertyBuilder = new StringBuilder();
-                if (value instanceof Integer) {
-                    propertyBuilder.append(String.format("%6d", value));
-                } else if (value instanceof Double) {
-                    propertyBuilder.append(String.format("%8.2f", value));
-                } else {
-                    propertyBuilder.append(value);
-                }
-
-                int length = Math.max(1, 20 - property.length());
-                sb.append(String.format(" %" + length + "s ", propertyBuilder.toString()));
-            }
-        }
-        OUT.println(sb.toString());
-    }
-
-    private static void printProfiling() {
-        List<OptimizedCallTarget> sortedCallTargets = new ArrayList<>(OptimizedCallTarget.callTargets.keySet());
-        Collections.sort(sortedCallTargets, new Comparator<OptimizedCallTarget>() {
-
-            @Override
-            public int compare(OptimizedCallTarget o1, OptimizedCallTarget o2) {
-                return o2.callCount - o1.callCount;
-            }
-        });
-
-        int totalCallCount = 0;
-        int totalInlinedCallSiteCount = 0;
-        int totalNodeCount = 0;
-        int totalInvalidationCount = 0;
-
-        OUT.println();
-        OUT.printf("%-50s | %-10s | %s / %s | %s | %s\n", "Call Target", "Call Count", "Calls Sites Inlined", "Not Inlined", "Node Count", "Inv");
-        for (OptimizedCallTarget callTarget : sortedCallTargets) {
-            if (callTarget.callCount == 0) {
-                continue;
-            }
-
-            int nodeCount = OptimizedCallUtils.countNonTrivialNodes(callTarget.getInliningResult(), new TruffleCallPath(callTarget));
-            String comment = callTarget.installedCode == null ? " int" : "";
-            comment += callTarget.compilationEnabled ? "" : " fail";
-            OUT.printf("%-50s | %10d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, nodeCount, nodeCount, callTarget.getCompilationProfile().getInvalidationCount(), comment);
-
-            totalCallCount += callTarget.callCount;
-            totalInlinedCallSiteCount += nodeCount;
-            totalNodeCount += nodeCount;
-            totalInvalidationCount += callTarget.getCompilationProfile().getInvalidationCount();
-        }
-        OUT.printf("%-50s | %10d | %15d | %10d | %3d\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNodeCount, totalInvalidationCount);
-    }
-
-    private static void registerCallTarget(OptimizedCallTarget callTarget) {
-        callTargets.put(callTarget, 0);
-    }
-
-    private static Map<OptimizedCallTarget, Integer> callTargets;
-    static {
-        if (TruffleCallTargetProfiling.getValue()) {
-            callTargets = new WeakHashMap<>();
-
-            Runtime.getRuntime().addShutdownHook(new Thread() {
-
-                @Override
-                public void run() {
-                    printProfiling();
-                }
-            });
-        }
-    }
-
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +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 static com.oracle.graal.truffle.TruffleCompilerOptions.*;
-
-import java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Call target for running truffle on a standard VM (and not in SubstrateVM).
- */
-public final class OptimizedCallTargetImpl extends OptimizedCallTarget {
-
-    protected final TruffleCompiler compiler;
-    private Future<InstalledCode> installedCodeTask;
-
-    OptimizedCallTargetImpl(RootNode rootNode, TruffleCompiler compiler, int invokeCounter, int compilationThreshold, boolean compilationEnabled) {
-        super(rootNode, invokeCounter, compilationThreshold, compilationEnabled, TruffleUseTimeForCompilationDecision.getValue() ? new TimedCompilationPolicy() : new DefaultCompilationPolicy());
-        this.compiler = compiler;
-    }
-
-    public boolean isOptimized() {
-        return installedCode != null || installedCodeTask != null;
-    }
-
-    @CompilerDirectives.SlowPath
-    @Override
-    public Object call(Object[] args) {
-        return CompilerDirectives.inInterpreter() ? callHelper(args) : executeHelper(args);
-    }
-
-    private Object callHelper(Object[] args) {
-        if (installedCode != null && installedCode.isValid()) {
-            reinstallCallMethodShortcut();
-        }
-        if (TruffleCallTargetProfiling.getValue()) {
-            callCount++;
-        }
-        if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, installedCode != null)) {
-            try {
-                return installedCode.executeVarargs(new Object[]{this, args});
-            } catch (InvalidInstalledCodeException ex) {
-                return compiledCodeInvalidated(args);
-            }
-        } else {
-            return interpreterCall(args);
-        }
-    }
-
-    private static void reinstallCallMethodShortcut() {
-        if (TraceTruffleCompilation.getValue()) {
-            OUT.println("[truffle] reinstall OptimizedCallTarget.call code with frame prolog shortcut.");
-        }
-        GraalTruffleRuntime.installOptimizedCallTargetCallMethod();
-    }
-
-    private Object compiledCodeInvalidated(Object[] args) {
-        invalidate(null, null, "Compiled code invalidated");
-        return call(args);
-    }
-
-    @Override
-    protected void invalidate(Node oldNode, Node newNode, CharSequence reason) {
-        InstalledCode m = this.installedCode;
-        if (m != null) {
-            CompilerAsserts.neverPartOfCompilation();
-            installedCode = null;
-            inliningResult = null;
-            compilationProfile.reportInvalidated();
-            logOptimizedInvalidated(this, oldNode, newNode, reason);
-        }
-        cancelInstalledTask(oldNode, newNode, reason);
-    }
-
-    @Override
-    protected void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) {
-        Future<InstalledCode> task = this.installedCodeTask;
-        if (task != null) {
-            task.cancel(true);
-            this.installedCodeTask = null;
-            logOptimizingUnqueued(this, oldNode, newNode, reason);
-            compilationProfile.reportInvalidated();
-        }
-    }
-
-    private Object interpreterCall(Object[] args) {
-        CompilerAsserts.neverPartOfCompilation();
-        compilationProfile.reportInterpreterCall();
-
-        if (compilationEnabled && compilationPolicy.shouldCompile(compilationProfile)) {
-            InstalledCode code = compile();
-            if (code != null && code.isValid()) {
-                this.installedCode = code;
-                try {
-                    return code.executeVarargs(new Object[]{this, args});
-                } catch (InvalidInstalledCodeException ex) {
-                    return compiledCodeInvalidated(args);
-                }
-            }
-        }
-        return executeHelper(args);
-    }
-
-    private boolean isCompiling() {
-        Future<InstalledCode> codeTask = this.installedCodeTask;
-        if (codeTask != null) {
-            if (codeTask.isCancelled()) {
-                installedCodeTask = null;
-                return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public InstalledCode compile() {
-        if (isCompiling()) {
-            if (installedCodeTask.isDone()) {
-                return receiveInstalledCode();
-            }
-            return null;
-        } else {
-            performInlining();
-            cancelInlinedCallOptimization();
-            logOptimizingQueued(this);
-            this.installedCodeTask = compiler.compile(this);
-            if (!TruffleBackgroundCompilation.getValue()) {
-                return receiveInstalledCode();
-            }
-            return null;
-        }
-    }
-
-    private InstalledCode receiveInstalledCode() {
-        try {
-            return installedCodeTask.get();
-        } catch (InterruptedException | ExecutionException e) {
-            compilationEnabled = false;
-            logOptimizingFailed(this, e.getMessage());
-            if (e.getCause() instanceof BailoutException) {
-                // Bailout => move on.
-            } else {
-                if (TraceTruffleCompilationExceptions.getValue()) {
-                    e.printStackTrace(OUT);
-                }
-                if (TruffleCompilationExceptionsAreFatal.getValue()) {
-                    System.exit(-1);
-                }
-            }
-            return null;
-        } finally {
-            onCompilationDone();
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,284 @@
+/*
+ * 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 static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter;
+
+public final class OptimizedCallTargetLog {
+
+    protected static final PrintStream OUT = TTY.out().out();
+
+    private static Map<OptimizedCallTarget, Integer> callTargets;
+    static {
+        if (TruffleCallTargetProfiling.getValue()) {
+            callTargets = new WeakHashMap<>();
+
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+
+                @Override
+                public void run() {
+                    printProfiling();
+                }
+            });
+        }
+    }
+
+    private OptimizedCallTargetLog() {
+    }
+
+    public static void logInliningDecision(TruffleInliningResult result) {
+        if (!TraceTruffleInlining.getValue()) {
+            return;
+        }
+
+        logInliningStart(result.getCallTarget());
+        logInliningDecisionRecursive(result, 0);
+        logInliningDone(result.getCallTarget());
+    }
+
+    private static void logInliningDecisionRecursive(TruffleInliningResult result, int depth) {
+        List<OptimizedDirectCallNode> callNodes = searchCallNodes(result.getCallTarget());
+        for (OptimizedDirectCallNode callNode : callNodes) {
+            TruffleInliningProfile profile = result.getProfiles().get(callNode);
+            boolean inlined = result.isInlined(callNode);
+            String msg = inlined ? "inline success" : "inline failed";
+            logInlinedImpl(msg, callNode, profile, depth);
+            if (profile.getRecursiveResult() != null && inlined) {
+                logInliningDecisionRecursive(profile.getRecursiveResult(), depth + 1);
+            }
+        }
+    }
+
+    private static List<OptimizedDirectCallNode> searchCallNodes(final OptimizedCallTarget target) {
+        final List<OptimizedDirectCallNode> callNodes = new ArrayList<>();
+        target.getRootNode().accept(new NodeVisitor() {
+            public boolean visit(Node node) {
+                if (node instanceof OptimizedDirectCallNode) {
+                    callNodes.add((OptimizedDirectCallNode) node);
+                }
+                return true;
+            }
+        });
+        return callNodes;
+    }
+
+    private static void logInlinedImpl(String status, OptimizedDirectCallNode callNode, TruffleInliningProfile profile, int depth) {
+        Map<String, Object> properties = new LinkedHashMap<>();
+        addASTSizeProperty(callNode.getCurrentCallTarget(), properties);
+        if (profile != null) {
+            properties.putAll(profile.getDebugProperties());
+        }
+        log((depth * 2), status, callNode.getCurrentCallTarget().toString(), properties);
+    }
+
+    private static void logInliningStart(OptimizedCallTarget target) {
+        if (TraceTruffleInlining.getValue()) {
+            log(0, "inline start", target.toString(), target.getDebugProperties());
+        }
+    }
+
+    private static void logInliningDone(OptimizedCallTarget target) {
+        if (TraceTruffleInlining.getValue()) {
+            log(0, "inline done", target.toString(), target.getDebugProperties());
+        }
+    }
+
+    public static void logOptimizingQueued(OptimizedCallTarget target) {
+        if (TraceTruffleCompilationDetails.getValue()) {
+            log(0, "opt queued", target.toString(), target.getDebugProperties());
+        }
+    }
+
+    public static void logOptimizingUnqueued(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) {
+        if (TraceTruffleCompilationDetails.getValue()) {
+            Map<String, Object> properties = new LinkedHashMap<>();
+            addReplaceProperties(properties, oldNode, newNode);
+            properties.put("Reason", reason);
+            log(0, "opt unqueued", target.toString(), properties);
+        }
+    }
+
+    private static void addReplaceProperties(Map<String, Object> properties, Node oldNode, Node newNode) {
+        if (oldNode != null && newNode != null) {
+            properties.put("OldClass", oldNode.getClass().getSimpleName());
+            properties.put("NewClass", newNode.getClass().getSimpleName());
+            properties.put("Node", newNode);
+        }
+    }
+
+    static void logOptimizingStart(OptimizedCallTarget target) {
+        if (TraceTruffleCompilationDetails.getValue()) {
+            log(0, "opt start", target.toString(), target.getDebugProperties());
+        }
+    }
+
+    public static void logOptimizedInvalidated(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) {
+        if (TraceTruffleCompilation.getValue()) {
+            Map<String, Object> properties = new LinkedHashMap<>();
+            addReplaceProperties(properties, oldNode, newNode);
+            properties.put("Reason", reason);
+            log(0, "opt invalidated", target.toString(), properties);
+        }
+    }
+
+    public static void logOptimizingFailed(OptimizedCallTarget callSite, CharSequence reason) {
+        Map<String, Object> properties = new LinkedHashMap<>();
+        properties.put("Reason", reason);
+        log(0, "opt fail", callSite.toString(), properties);
+    }
+
+    static void logOptimizingDone(OptimizedCallTarget target, Map<String, Object> properties) {
+        if (TraceTruffleCompilationDetails.getValue() || TraceTruffleCompilation.getValue()) {
+            log(0, "opt done", target.toString(), properties);
+        }
+        if (TraceTruffleCompilationPolymorphism.getValue()) {
+
+            target.getRootNode().accept(new NodeVisitor() {
+                public boolean visit(Node node) {
+                    NodeCost kind = node.getCost();
+                    if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) {
+                        Map<String, Object> props = new LinkedHashMap<>();
+                        props.put("simpleName", node.getClass().getSimpleName());
+                        String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic";
+                        log(0, msg, node.toString(), props);
+                    }
+                    if (node instanceof DirectCallNode) {
+                        DirectCallNode callNode = (DirectCallNode) node;
+                        if (callNode.isInlined()) {
+                            callNode.getCurrentRootNode().accept(this);
+                        }
+                    }
+                    return true;
+                }
+            });
+
+        }
+    }
+
+    private static int splitCount = 0;
+
+    static void logSplit(OptimizedDirectCallNode callNode, OptimizedCallTarget target, OptimizedCallTarget newTarget) {
+        if (TraceTruffleSplitting.getValue()) {
+            Map<String, Object> properties = new LinkedHashMap<>();
+            addASTSizeProperty(target, properties);
+            properties.put("Split#", ++splitCount);
+            properties.put("Source", callNode.getEncapsulatingSourceSection());
+            log(0, "split", newTarget.toString(), properties);
+        }
+    }
+
+    static void addASTSizeProperty(OptimizedCallTarget target, Map<String, Object> properties) {
+        int polymorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                return node.getCost() == NodeCost.POLYMORPHIC;
+            }
+        }, true);
+
+        int megamorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                return node.getCost() == NodeCost.MEGAMORPHIC;
+            }
+        }, true);
+
+        String value = String.format("%4d (%d/%d)", OptimizedCallUtils.countNonTrivialNodes(target, true), polymorphicCount, megamorphicCount);
+        properties.put("ASTSize", value);
+    }
+
+    static void log(int indent, String msg, String details, Map<String, Object> properties) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(String.format("[truffle] %-16s ", msg));
+        for (int i = 0; i < indent; i++) {
+            sb.append(' ');
+        }
+        sb.append(String.format("%-" + (60 - indent) + "s", details));
+        if (properties != null) {
+            for (String property : properties.keySet()) {
+                Object value = properties.get(property);
+                if (value == null) {
+                    continue;
+                }
+                sb.append('|');
+                sb.append(property);
+
+                StringBuilder propertyBuilder = new StringBuilder();
+                if (value instanceof Integer) {
+                    propertyBuilder.append(String.format("%6d", value));
+                } else if (value instanceof Double) {
+                    propertyBuilder.append(String.format("%8.2f", value));
+                } else {
+                    propertyBuilder.append(value);
+                }
+
+                int length = Math.max(1, 20 - property.length());
+                sb.append(String.format(" %" + length + "s ", propertyBuilder.toString()));
+            }
+        }
+        OUT.println(sb.toString());
+    }
+
+    private static void printProfiling() {
+        List<OptimizedCallTarget> sortedCallTargets = new ArrayList<>(callTargets.keySet());
+        Collections.sort(sortedCallTargets, new Comparator<OptimizedCallTarget>() {
+
+            @Override
+            public int compare(OptimizedCallTarget o1, OptimizedCallTarget o2) {
+                return o2.callCount - o1.callCount;
+            }
+        });
+
+        int totalCallCount = 0;
+        int totalInlinedCallSiteCount = 0;
+        int totalNodeCount = 0;
+        int totalInvalidationCount = 0;
+
+        OUT.println();
+        OUT.printf("%-50s | %-10s | %s / %s | %s | %s\n", "Call Target", "Call Count", "Calls Sites Inlined", "Not Inlined", "Node Count", "Inv");
+        for (OptimizedCallTarget callTarget : sortedCallTargets) {
+            if (callTarget.callCount == 0) {
+                continue;
+            }
+
+            int nodeCount = OptimizedCallUtils.countNonTrivialNodes(callTarget, true);
+            String comment = callTarget.isValid() ? "" : " int";
+            OUT.printf("%-50s | %10d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, nodeCount, nodeCount, callTarget.getCompilationProfile().getInvalidationCount(), comment);
+
+            totalCallCount += callTarget.callCount;
+            totalInlinedCallSiteCount += nodeCount;
+            totalNodeCount += nodeCount;
+            totalInvalidationCount += callTarget.getCompilationProfile().getInvalidationCount();
+        }
+        OUT.printf("%-50s | %10d | %15d | %10d | %3d\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNodeCount, totalInvalidationCount);
+    }
+
+    public static void registerCallTarget(OptimizedCallTarget callTarget) {
+        callTargets.put(callTarget, 0);
+    }
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,98 +23,35 @@
 package com.oracle.graal.truffle;
 
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter;
 
 class OptimizedCallUtils {
 
-    public abstract static class InlinedCallVisitor implements NodeVisitor {
-
-        private TruffleCallPath currentPath;
-        private final TruffleInliningResult inliningDecision;
-
-        public InlinedCallVisitor(TruffleInliningResult inliningDecision, TruffleCallPath initialPath) {
-            this.inliningDecision = inliningDecision;
-            this.currentPath = initialPath;
-        }
-
-        public final TruffleInliningResult getInliningDecision() {
-            return inliningDecision;
-        }
-
-        public final boolean visit(Node node) {
-            if (node instanceof OptimizedCallNode) {
-                OptimizedCallNode callNode = ((OptimizedCallNode) node);
-                this.currentPath = new TruffleCallPath(this.currentPath, callNode);
-                try {
-                    boolean result = visit(currentPath, node);
-                    TruffleInliningResult decision = inliningDecision;
-                    if (decision != null && decision.isInlined(currentPath)) {
-                        callNode.getCurrentRootNode().accept(this);
-                    }
-                    return result;
-                } finally {
-                    this.currentPath = this.currentPath.getParent();
-                }
-            } else {
-                return visit(currentPath, node);
+    public static int countCalls(OptimizedCallTarget target) {
+        return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                return node instanceof DirectCallNode;
             }
-        }
-
-        public abstract boolean visit(TruffleCallPath path, Node node);
-
+        }, true);
     }
 
-    public static int countNodes(TruffleInliningResult decision, TruffleCallPath path, InlinedNodeCountFilter filter) {
-        InlinedNodeCountVisitor nodeCount = new InlinedNodeCountVisitor(decision, path, filter);
-        path.getCallTarget().getRootNode().accept(nodeCount);
-        return nodeCount.nodeCount;
-    }
-
-    public static int countCalls(TruffleInliningResult decision, TruffleCallPath path) {
-        InlinedNodeCountVisitor nodeCount = new InlinedNodeCountVisitor(decision, path, new InlinedNodeCountFilter() {
-            public boolean isCounted(TruffleCallPath p, Node node) {
-                return node instanceof CallNode;
+    public static int countCallsInlined(OptimizedCallTarget target) {
+        return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                return (node instanceof OptimizedDirectCallNode) && ((OptimizedDirectCallNode) node).isInlined();
             }
-        });
-        path.getCallTarget().getRootNode().accept(nodeCount);
-        return nodeCount.nodeCount;
-    }
-
-    public interface InlinedNodeCountFilter {
-
-        boolean isCounted(TruffleCallPath path, Node node);
+        }, true);
     }
 
-    private static final class InlinedNodeCountVisitor extends InlinedCallVisitor {
-
-        private final InlinedNodeCountFilter filter;
-        int nodeCount;
-
-        private InlinedNodeCountVisitor(TruffleInliningResult decision, TruffleCallPath initialPath, InlinedNodeCountFilter filter) {
-            super(decision, initialPath);
-            this.filter = filter;
-        }
-
-        @Override
-        public boolean visit(TruffleCallPath path, Node node) {
-            if (filter == null || filter.isCounted(path, node)) {
-                nodeCount++;
-            }
-            return true;
-        }
-
-    }
-
-    static int countNonTrivialNodes(TruffleInliningResult state, TruffleCallPath path) {
-        return countNodes(state, path, new InlinedNodeCountFilter() {
-
-            public boolean isCounted(TruffleCallPath p, Node node) {
+    public static int countNonTrivialNodes(final OptimizedCallTarget target, final boolean inlined) {
+        return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
                 NodeCost cost = node.getCost();
                 if (cost != null && cost != NodeCost.NONE && cost != NodeCost.UNINITIALIZED) {
                     return true;
                 }
                 return false;
             }
-        });
+        }, inlined);
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,222 @@
+/*
+ * 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.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter;
+
+/**
+ * A call node with a constant {@link CallTarget} that can be optimized by Graal.
+ */
+public final class OptimizedDirectCallNode extends DirectCallNode implements MaterializedFrameNotify {
+
+    private int callCount;
+    private boolean trySplit = true;
+    private boolean inliningForced;
+
+    @CompilationFinal private boolean inlined;
+    @CompilationFinal private OptimizedCallTarget splitCallTarget;
+    @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE;
+
+    private OptimizedDirectCallNode(OptimizedCallTarget target) {
+        super(target);
+    }
+
+    @Override
+    public Object call(VirtualFrame frame, Object[] arguments) {
+        if (CompilerDirectives.inInterpreter()) {
+            onInterpreterCall();
+        }
+        return callProxy(this, getCurrentCallTarget(), frame, arguments, inlined, true);
+    }
+
+    public static Object callProxy(MaterializedFrameNotify notify, CallTarget callTarget, VirtualFrame frame, Object[] arguments, boolean inlined, boolean direct) {
+        try {
+            if (notify.getOutsideFrameAccess() != FrameAccess.NONE) {
+                CompilerDirectives.materialize(frame);
+            }
+            if (inlined) {
+                return ((OptimizedCallTarget) callTarget).callInlined(arguments);
+            } else if (direct) {
+                return ((OptimizedCallTarget) callTarget).callDirect(arguments);
+            } else {
+                return callTarget.call(arguments);
+            }
+        } finally {
+            // this assertion is needed to keep the values from being cleared as non-live locals
+            assert notify != null & callTarget != null & frame != null;
+        }
+    }
+
+    @Override
+    public boolean isInlinable() {
+        return true;
+    }
+
+    @Override
+    public void forceInlining() {
+        inliningForced = true;
+    }
+
+    @Override
+    public boolean isInliningForced() {
+        return inliningForced;
+    }
+
+    @Override
+    public FrameAccess getOutsideFrameAccess() {
+        return outsideFrameAccess;
+    }
+
+    @Override
+    public void setOutsideFrameAccess(FrameAccess outsideFrameAccess) {
+        this.outsideFrameAccess = outsideFrameAccess;
+    }
+
+    @Override
+    public boolean isSplittable() {
+        return getCallTarget().getRootNode().isSplittable();
+    }
+
+    @Override
+    public OptimizedCallTarget getCallTarget() {
+        return (OptimizedCallTarget) super.getCallTarget();
+    }
+
+    public int getCallCount() {
+        return callCount;
+    }
+
+    @Override
+    public OptimizedCallTarget getCurrentCallTarget() {
+        return (OptimizedCallTarget) super.getCurrentCallTarget();
+    }
+
+    @Override
+    public OptimizedCallTarget getSplitCallTarget() {
+        return splitCallTarget;
+    }
+
+    private void onInterpreterCall() {
+        callCount++;
+        if (trySplit) {
+            if (callCount == 1) {
+                // on first call
+                getCurrentCallTarget().incrementKnownCallSites();
+            }
+            if (callCount > 1 && !inlined) {
+                trySplit = false;
+                if (shouldSplit()) {
+                    splitImpl(true);
+                }
+            }
+        }
+    }
+
+    /* Called by the runtime system if this CallNode is really going to be inlined. */
+    void inline() {
+        inlined = true;
+    }
+
+    @Override
+    public boolean isInlined() {
+        return inlined;
+    }
+
+    @Override
+    public boolean split() {
+        splitImpl(false);
+        return true;
+    }
+
+    private void splitImpl(boolean heuristic) {
+        CompilerAsserts.neverPartOfCompilation();
+
+        OptimizedCallTarget splitTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(getCallTarget().getRootNode().split());
+        splitTarget.setSplitSource(getCallTarget());
+        if (heuristic) {
+            OptimizedCallTargetLog.logSplit(this, getCallTarget(), splitTarget);
+        }
+        if (callCount >= 1) {
+            getCallTarget().decrementKnownCallSites();
+            splitTarget.incrementKnownCallSites();
+        }
+        this.splitCallTarget = splitTarget;
+    }
+
+    private boolean shouldSplit() {
+        if (splitCallTarget != null) {
+            return false;
+        }
+        if (!TruffleCompilerOptions.TruffleSplittingEnabled.getValue()) {
+            return false;
+        }
+        if (!isSplittable()) {
+            return false;
+        }
+        OptimizedCallTarget splitTarget = getCallTarget();
+        int nodeCount = OptimizedCallUtils.countNonTrivialNodes(splitTarget, false);
+        if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) {
+            return false;
+        }
+
+        // disable recursive splitting for now
+        OptimizedCallTarget root = (OptimizedCallTarget) getRootNode().getCallTarget();
+        if (root == splitTarget || root.getSplitSource() == splitTarget) {
+            // recursive call found
+            return false;
+        }
+
+        // max one child call and callCount > 2 and kind of small number of nodes
+        if (isMaxSingleCall()) {
+            return true;
+        }
+        return countPolymorphic() >= 1;
+    }
+
+    private boolean isMaxSingleCall() {
+        return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                return node instanceof DirectCallNode;
+            }
+        }) <= 1;
+    }
+
+    private int countPolymorphic() {
+        return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                NodeCost cost = node.getCost();
+                boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC;
+                return polymorphic;
+            }
+        });
+    }
+
+    public static OptimizedDirectCallNode create(OptimizedCallTarget target) {
+        return new OptimizedDirectCallNode(target);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A call node with a constant {@link CallTarget} that can be optimized by Graal.
+ */
+public final class OptimizedIndirectCallNode extends IndirectCallNode implements MaterializedFrameNotify {
+
+    @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE;
+
+    @Override
+    public Object call(VirtualFrame frame, CallTarget target, Object[] arguments) {
+        return OptimizedDirectCallNode.callProxy(this, target, frame, arguments, false, false);
+    }
+
+    @Override
+    public FrameAccess getOutsideFrameAccess() {
+        return outsideFrameAccess;
+    }
+
+    @Override
+    public void setOutsideFrameAccess(FrameAccess outsideFrameAccess) {
+        this.outsideFrameAccess = outsideFrameAccess;
+    }
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,19 +22,20 @@
  */
 package com.oracle.graal.truffle;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.loop.*;
@@ -42,7 +43,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
@@ -67,14 +67,12 @@
     private final CanonicalizerPhase canonicalizer;
     private Set<Constant> constantReceivers;
     private final TruffleCache truffleCache;
-    private final ResolvedJavaType frameType;
 
     public PartialEvaluator(Providers providers, TruffleCache truffleCache) {
         this.providers = providers;
         CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(providers.getMetaAccess(), providers.getConstantReflection());
         this.canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue(), customCanonicalizer);
         this.truffleCache = truffleCache;
-        this.frameType = providers.getMetaAccess().lookupJavaType(FrameWithoutBoxing.class);
     }
 
     public StructuredGraph createGraph(final OptimizedCallTarget callTarget, final Assumptions assumptions) {
@@ -84,18 +82,25 @@
             throw Debug.handle(e);
         }
 
-        if (TraceTruffleCompilationHistogram.getValue()) {
+        if (TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) {
             constantReceivers = new HashSet<>();
         }
 
-        final StructuredGraph graph = truffleCache.createRootGraph();
+        final StructuredGraph graph = truffleCache.createRootGraph(callTarget.toString());
         assert graph != null : "no graph for root method";
 
         try (Scope s = Debug.scope("CreateGraph", graph); Indent indent = Debug.logAndIndent("createGraph %s", graph.method())) {
 
             // Replace thisNode with constant.
             ParameterNode thisNode = graph.getParameter(0);
-            thisNode.replaceAndDelete(ConstantNode.forObject(callTarget, providers.getMetaAccess(), graph));
+
+            /*
+             * Converting the call target to a Constant using the SnippetReflectionProvider is a
+             * workaround, we should think about a better solution. Since object constants are
+             * VM-specific, only the hosting VM knows how to do the conversion.
+             */
+            SnippetReflectionProvider snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class);
+            thisNode.replaceAndDelete(ConstantNode.forConstant(snippetReflection.forObject(callTarget), providers.getMetaAccess(), graph));
 
             // Canonicalize / constant propagate.
             PhaseContext baseContext = new PhaseContext(providers, assumptions);
@@ -104,15 +109,10 @@
             // Intrinsify methods.
             new ReplaceIntrinsicsPhase(providers.getReplacements()).apply(graph);
 
-            NewFrameNode newFrameNode = graph.getNodes(NewFrameNode.class).first();
-            if (newFrameNode == null) {
-                throw GraalInternalError.shouldNotReachHere("frame not found");
-            }
-
             Debug.dump(graph, "Before inlining");
 
             // Make sure frame does not escape.
-            expandTree(callTarget, graph, assumptions);
+            expandTree(graph, assumptions);
 
             if (Thread.currentThread().isInterrupted()) {
                 return null;
@@ -123,7 +123,16 @@
             if (TraceTruffleCompilationHistogram.getValue() && constantReceivers != null) {
                 DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes");
                 for (Constant c : constantReceivers) {
-                    histogram.add(c.asObject().getClass().getSimpleName());
+                    String javaName = MetaUtil.toJavaName(providers.getMetaAccess().lookupJavaType(c), false);
+
+                    // The DSL uses nested classes with redundant names - only show the inner class
+                    int index = javaName.indexOf('$');
+                    if (index != -1) {
+                        javaName = javaName.substring(index + 1);
+                    }
+
+                    histogram.add(javaName);
+
                 }
                 new DebugHistogramAsciiPrinter(TTY.out().out()).print(histogram);
             }
@@ -166,25 +175,23 @@
         return graph;
     }
 
-    private void expandTree(OptimizedCallTarget target, StructuredGraph graph, Assumptions assumptions) {
+    private void expandTree(StructuredGraph graph, Assumptions assumptions) {
         PhaseContext phaseContext = new PhaseContext(providers, assumptions);
         TruffleExpansionLogger expansionLogger = null;
         if (TraceTruffleExpansion.getValue()) {
-            expansionLogger = new TruffleExpansionLogger(graph);
+            expansionLogger = new TruffleExpansionLogger(providers, graph);
         }
-        boolean inliningEnabled = target.getInliningResult() != null && target.getInliningResult().size() > 0;
-        Map<Node, TruffleCallPath> methodTargetToStack = new HashMap<>();
         boolean changed;
         do {
             changed = false;
             for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class)) {
                 InvokeKind kind = methodCallTargetNode.invokeKind();
                 try (Indent id1 = Debug.logAndIndent("try inlining %s, kind = %s", methodCallTargetNode.targetMethod(), kind)) {
-                    if (kind == InvokeKind.Static || (kind == InvokeKind.Special && (methodCallTargetNode.receiver().isConstant() || isFrame(methodCallTargetNode.receiver())))) {
-                        if (TraceTruffleCompilationHistogram.getValue() && kind == InvokeKind.Special) {
-                            ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first();
-                            constantReceivers.add(constantNode.asConstant());
+                    if (kind == InvokeKind.Static || kind == InvokeKind.Special) {
+                        if ((TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) && kind == InvokeKind.Special && methodCallTargetNode.receiver().isConstant()) {
+                            constantReceivers.add(methodCallTargetNode.receiver().asConstant());
                         }
+
                         Replacements replacements = providers.getReplacements();
                         Class<? extends FixedWithNextNode> macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod());
                         if (macroSubstitution != null) {
@@ -193,41 +200,25 @@
                             continue;
                         }
 
-                        if (TraceTruffleCompilationDetails.getValue() && kind == InvokeKind.Special) {
-                            ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first();
-                            constantReceivers.add(constantNode.asConstant());
-                        }
-
                         StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
-                        if (inliningEnabled && inlineGraph == null) {
-                            inlineGraph = expandInlinableCallNode(target, methodTargetToStack, assumptions, phaseContext, methodCallTargetNode);
-                        }
-
-                        if (inlineGraph == null && !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers())) {
+                        if (inlineGraph == null && !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().canBeInlined()) {
                             inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, false);
                         }
 
                         if (inlineGraph != null) {
                             try (Indent indent = Debug.logAndIndent("inline graph %s", methodCallTargetNode.targetMethod())) {
-                                if (inliningEnabled) {
-                                    preExpandTruffleCallPath(inlineGraph, methodTargetToStack, methodTargetToStack.get(methodCallTargetNode));
-                                }
+
                                 int nodeCountBefore = graph.getNodeCount();
                                 Mark mark = graph.getMark();
                                 if (TraceTruffleExpansion.getValue()) {
                                     expansionLogger.preExpand(methodCallTargetNode, inlineGraph);
                                 }
                                 List<Node> invokeUsages = methodCallTargetNode.invoke().asNode().usages().snapshot();
-                                // try (Indent in2 = Debug.logAndIndent(false, "do inlining")) {
                                 Map<Node, Node> inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false);
                                 if (TraceTruffleExpansion.getValue()) {
                                     expansionLogger.postExpand(inlined);
                                 }
-                                if (inliningEnabled) {
-                                    postExpandTruffleCallPath(methodTargetToStack, inlined);
-                                }
                                 if (Debug.isDumpEnabled()) {
-                                    Debug.log("dump enabled");
                                     int nodeCountAfter = graph.getNodeCount();
                                     Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter);
                                 }
@@ -250,73 +241,6 @@
         }
     }
 
-    private static void preExpandTruffleCallPath(StructuredGraph inlineGraph, Map<Node, TruffleCallPath> methodTargetToCallPath, TruffleCallPath truffleCallPath) {
-        for (MethodCallTargetNode methodTargetNode : inlineGraph.getNodes(MethodCallTargetNode.class)) {
-            methodTargetToCallPath.put(methodTargetNode, truffleCallPath);
-        }
-    }
-
-    private static void postExpandTruffleCallPath(Map<Node, TruffleCallPath> methodCallTargetToCallPath, Map<Node, Node> nodeUpdates) {
-        for (Object key : methodCallTargetToCallPath.keySet().toArray()) {
-            if (nodeUpdates.containsKey(key)) {
-                methodCallTargetToCallPath.put(nodeUpdates.get(key), methodCallTargetToCallPath.get(key));
-                methodCallTargetToCallPath.remove(key);
-            }
-        }
-    }
-
-    private StructuredGraph expandInlinableCallNode(OptimizedCallTarget target, Map<Node, TruffleCallPath> methodCallToCallPath, Assumptions assumptions, PhaseContext phaseContext,
-                    MethodCallTargetNode methodCallTargetNode) {
-
-        ValueNode receiverNode = methodCallTargetNode.receiver();
-        if (receiverNode == null || !receiverNode.isConstant() || !receiverNode.asConstant().getKind().isObject()) {
-            return null;
-        }
-
-        ResolvedJavaMethod method = methodCallTargetNode.targetMethod();
-        if (!method.getName().equals("call") || method.getSignature().getParameterCount(false) != 1) {
-            return null;
-        }
-
-        Object receiverValue = receiverNode.asConstant().asObject();
-        if (receiverValue instanceof OptimizedCallNode) {
-            OptimizedCallNode callNode = (OptimizedCallNode) receiverValue;
-            TruffleCallPath callPath = methodCallToCallPath.get(methodCallTargetNode);
-            if (callPath == null) {
-                callPath = new TruffleCallPath(target);
-            }
-            callPath = new TruffleCallPath(callPath, callNode);
-            methodCallToCallPath.put(methodCallTargetNode, callPath);
-            // let the normal expansion do the work
-            return null;
-        } else if (receiverValue instanceof OptimizedCallTarget) {
-            TruffleCallPath path = methodCallToCallPath.get(methodCallTargetNode);
-            // path unknown. direct call to OptimizedCallTarget without OptimizedCallNode?
-            if (path == null) {
-                return null;
-            }
-
-            TruffleInliningResult decision = target.getInliningResult();
-            if (decision == null) { // no inlining decision. inlining disabled?
-                return null;
-            }
-
-            if (!decision.isInlined(path)) {
-                // the OptimizedCallTarget has decided not to inline this call path
-                return null;
-            }
-
-            // inline truffle call
-            return parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, true);
-        }
-
-        return null;
-    }
-
-    private boolean isFrame(ValueNode receiver) {
-        return receiver instanceof NewFrameNode || Objects.equals(ObjectStamp.typeOrNull(receiver.stamp()), frameType);
-    }
-
     private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final PhaseContext phaseContext,
                     boolean ignoreSlowPath) {
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,6 @@
  */
 package com.oracle.graal.truffle;
 
-import java.lang.reflect.*;
-
-import sun.misc.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.nodes.*;
@@ -44,14 +40,12 @@
         this.constantReflection = constantReflection;
     }
 
-    private static final Unsafe unsafe = Unsafe.getUnsafe();
-
     @Override
     public Node canonicalize(Node node) {
         if (node instanceof LoadFieldNode) {
             LoadFieldNode loadFieldNode = (LoadFieldNode) node;
             if (!loadFieldNode.isStatic() && loadFieldNode.object().isConstant() && !loadFieldNode.object().isNullConstant()) {
-                if (Modifier.isFinal(loadFieldNode.field().getModifiers()) || (loadFieldNode.getKind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) ||
+                if (loadFieldNode.field().isFinal() || (loadFieldNode.getKind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) ||
                                 loadFieldNode.field().getAnnotation(CompilerDirectives.CompilationFinal.class) != null) {
                     Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant());
                     assert verifyFieldValue(loadFieldNode.field(), constant);
@@ -60,14 +54,11 @@
             }
         } else if (node instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node;
-            if (loadIndexedNode.array().isConstant() && !loadIndexedNode.array().isNullConstant() && loadIndexedNode.index().isConstant()) {
-                Object array = loadIndexedNode.array().asConstant().asObject();
-                long index = loadIndexedNode.index().asConstant().asLong();
-                if (index >= 0 && index < Array.getLength(array)) {
-                    int arrayBaseOffset = unsafe.arrayBaseOffset(array.getClass());
-                    int arrayIndexScale = unsafe.arrayIndexScale(array.getClass());
-                    Constant constant = constantReflection.readUnsafeConstant(loadIndexedNode.elementKind(), array, arrayBaseOffset + index * arrayIndexScale,
-                                    loadIndexedNode.elementKind() == Kind.Object);
+            if (loadIndexedNode.array().isConstant() && loadIndexedNode.index().isConstant()) {
+                int index = loadIndexedNode.index().asConstant().asInt();
+
+                Constant constant = constantReflection.readArrayElement(loadIndexedNode.array().asConstant(), index);
+                if (constant != null) {
                     return ConstantNode.forConstant(constant, metaAccess, loadIndexedNode.graph());
                 }
             }
@@ -75,9 +66,10 @@
         return node;
     }
 
-    private static boolean verifyFieldValue(ResolvedJavaField field, Constant constant) {
-        assert field.getAnnotation(Child.class) == null || constant.isNull() || constant.asObject() instanceof com.oracle.truffle.api.nodes.Node : "@Child field value must be a Node: " + field +
-                        ", but was: " + constant.asObject();
+    private boolean verifyFieldValue(ResolvedJavaField field, Constant constant) {
+        assert field.getAnnotation(Child.class) == null || constant.isNull() ||
+                        metaAccess.lookupJavaType(com.oracle.truffle.api.nodes.Node.class).isAssignableFrom(metaAccess.lookupJavaType(constant)) : "@Child field value must be a Node: " + field +
+                        ", but was: " + constant;
         return true;
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +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 static com.oracle.graal.truffle.TruffleCompilerOptions.*;
-
-import java.io.*;
-
-public class TimedCompilationPolicy extends DefaultCompilationPolicy {
-
-    @Override
-    public boolean shouldCompile(CompilationProfile profile) {
-        if (super.shouldCompile(profile)) {
-            long timestamp = System.nanoTime();
-            long prevTimestamp = profile.getPreviousTimestamp();
-            long timespan = (timestamp - prevTimestamp);
-            if (timespan < (TruffleCompilationDecisionTime.getValue())) {
-                return true;
-            }
-            // TODO shouldCompile should not modify the compilation profile
-            // maybe introduce another method?
-            profile.reportTiminingFailed(timestamp);
-            if (TruffleCompilationDecisionTimePrintFail.getValue()) {
-                PrintStream out = System.out;
-                out.println(profile.getName() + ": timespan  " + (timespan / 1000000) + " ms  larger than threshold");
-            }
-        }
-        return false;
-    }
-
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,9 +31,9 @@
 public interface TruffleCache {
 
     /**
-     * Creates the graph for the root method, i.e. {@link OptimizedCallTarget#executeHelper}.
+     * Creates the graph for the root method, i.e. {@link OptimizedCallTarget#callBoundary}.
      */
-    StructuredGraph createRootGraph();
+    StructuredGraph createRootGraph(String name);
 
     /**
      * Returns a cached graph for a method with given arguments.
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,8 @@
  */
 package com.oracle.graal.truffle;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.Map.Entry;
 
@@ -65,7 +64,7 @@
     private final HashMap<List<Object>, Long> lastUsed = new HashMap<>();
     private final StructuredGraph markerGraph = new StructuredGraph();
     private final ResolvedJavaType stringBuilderClass;
-    private final ResolvedJavaMethod executeHelperMethod;
+    private final ResolvedJavaMethod callBoundaryMethod;
     private long counter;
 
     public TruffleCacheImpl(Providers providers, GraphBuilderConfiguration config, GraphBuilderConfiguration configForRootGraph, OptimisticOptimizations optimisticOptimizations) {
@@ -75,14 +74,14 @@
         this.optimisticOptimizations = optimisticOptimizations;
         this.stringBuilderClass = providers.getMetaAccess().lookupJavaType(StringBuilder.class);
         try {
-            executeHelperMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("executeHelper", Object[].class));
+            callBoundaryMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("callRoot", Object[].class));
         } catch (NoSuchMethodException ex) {
             throw new RuntimeException(ex);
         }
     }
 
-    public StructuredGraph createRootGraph() {
-        StructuredGraph graph = new StructuredGraph(executeHelperMethod);
+    public StructuredGraph createRootGraph(String name) {
+        StructuredGraph graph = new StructuredGraph(name, callBoundaryMethod);
         new GraphBuilderPhase.Instance(providers.getMetaAccess(), configForRootGraph, TruffleCompilerImpl.Optimizations).apply(graph);
         return graph;
     }
@@ -251,7 +250,7 @@
         if (methodCallTargetNode.targetMethod().isConstructor()) {
             ResolvedJavaType runtimeException = providers.getMetaAccess().lookupJavaType(RuntimeException.class);
             ResolvedJavaType controlFlowException = providers.getMetaAccess().lookupJavaType(ControlFlowException.class);
-            ResolvedJavaType exceptionType = Objects.requireNonNull(ObjectStamp.typeOrNull(methodCallTargetNode.receiver().stamp()));
+            ResolvedJavaType exceptionType = Objects.requireNonNull(StampTool.typeOrNull(methodCallTargetNode.receiver().stamp()));
             if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass()) && !controlFlowException.isAssignableFrom(exceptionType)) {
                 DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode));
                 FixedNode invokeNode = methodCallTargetNode.invoke().asNode();
@@ -264,9 +263,10 @@
     }
 
     private boolean shouldInline(final MethodCallTargetNode methodCallTargetNode) {
-        return (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) &&
-                        !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null &&
+        boolean result = (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && methodCallTargetNode.targetMethod().canBeInlined() &&
+                        !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null &&
                         methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null &&
                         !methodCallTargetNode.targetMethod().getDeclaringClass().equals(stringBuilderClass);
+        return result;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallBoundary.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,31 @@
+/*
+ * 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.truffle;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface TruffleCallBoundary {
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallPath.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +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 java.util.*;
-
-import com.oracle.truffle.api.*;
-
-public final class TruffleCallPath implements Iterable<TruffleCallPath>, Comparable<TruffleCallPath> {
-
-    private final OptimizedCallNode callNode;
-    private final TruffleCallPath parent;
-    private final OptimizedCallTarget rootCallTarget;
-
-    public TruffleCallPath(OptimizedCallTarget parent) {
-        this.rootCallTarget = Objects.requireNonNull(parent);
-        this.callNode = null;
-        this.parent = null;
-    }
-
-    public TruffleCallPath(TruffleCallPath parent, OptimizedCallNode node) {
-        this.parent = Objects.requireNonNull(parent);
-        assert !parent.containsPath(this) : "cyclic path detected";
-        this.callNode = Objects.requireNonNull(node);
-        this.rootCallTarget = parent.getRootCallTarget();
-    }
-
-    public boolean isRoot() {
-        return parent == null && rootCallTarget != null;
-    }
-
-    private boolean containsPath(TruffleCallPath p) {
-        return p == this || (getParent() != null && this.getParent().containsPath(p));
-    }
-
-    public OptimizedCallTarget getRootCallTarget() {
-        return rootCallTarget;
-    }
-
-    @Override
-    public String toString() {
-        return (parent != null ? (parent.toString() + " -> ") : "") + getCallTarget().toString();
-    }
-
-    public Iterator<TruffleCallPath> iterator() {
-        return toList().iterator();
-    }
-
-    public OptimizedCallTarget getCallTarget() {
-        return parent == null ? rootCallTarget : callNode.getCurrentCallTarget();
-    }
-
-    public List<TruffleCallPath> toList() {
-        List<TruffleCallPath> list = new ArrayList<>();
-        toListImpl(list);
-        return list;
-    }
-
-    private void toListImpl(List<TruffleCallPath> list) {
-        if (parent != null) {
-            parent.toListImpl(list);
-        }
-        list.add(this);
-    }
-
-    public TruffleCallPath getParent() {
-        return parent;
-    }
-
-    public OptimizedCallNode getCallNode() {
-        return callNode;
-    }
-
-    public int getDepth() {
-        return parent == null ? 0 : (parent.getDepth() + 1);
-    }
-
-    public int compareTo(TruffleCallPath o) {
-        return Objects.compare(this, o, new PathComparator());
-    }
-
-    private static class PathComparator implements Comparator<TruffleCallPath> {
-        public int compare(TruffleCallPath c1, TruffleCallPath c2) {
-            if (c1 == c2) {
-                return 0;
-            }
-
-            Iterator<TruffleCallPath> p1 = c1.toList().iterator();
-            Iterator<TruffleCallPath> p2 = c2.toList().iterator();
-
-            int cmp = 0;
-            while (cmp == 0 && (p1.hasNext() || p2.hasNext())) {
-                TruffleCallPath o1;
-                TruffleCallPath o2;
-                if (p1.hasNext()) {
-                    o1 = p1.next();
-                } else {
-                    return -1;
-                }
-                if (p2.hasNext()) {
-                    o2 = p2.next();
-                } else {
-                    return 1;
-                }
-
-                if (o1 == o2) {
-                    continue;
-                }
-
-                SourceSection s1;
-                if (o1.callNode != null) {
-                    s1 = o1.callNode.getEncapsulatingSourceSection();
-                } else {
-                    s1 = o1.getCallTarget().getRootNode().getSourceSection();
-                }
-
-                SourceSection s2;
-                if (o2.callNode != null) {
-                    s2 = o2.callNode.getEncapsulatingSourceSection();
-                } else {
-                    s2 = o2.getCallTarget().getRootNode().getSourceSection();
-                }
-                cmp = compareSourceSection(s2, s1);
-
-                if (cmp == 0) {
-                    cmp = o1.getCallTarget().toString().compareTo(o2.getCallTarget().toString());
-                }
-            }
-            return cmp;
-        }
-    }
-
-    private static int compareSourceSection(SourceSection s1, SourceSection s2) {
-        return Objects.compare(s1, s2, new Comparator<SourceSection>() {
-            public int compare(SourceSection o1, SourceSection o2) {
-                if (o1 == o2) {
-                    return 0;
-                }
-                if (o1 == null || o2 == null) {
-                    return 0;
-                }
-                int cmp = 0;
-                if (o1.getSource() != null && o2.getSource() != null && !Objects.equals(o1.getSource().getName(), o2.getSource().getName())) {
-                    cmp = o2.getSource().getName().compareTo(o1.getSource().getName());
-                }
-                if (cmp == 0) {
-                    cmp = o2.getStartLine() - o1.getStartLine();
-                }
-                if (cmp == 0) {
-                    cmp = o2.getStartColumn() - o1.getStartColumn();
-                }
-                return cmp;
-            }
-        });
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((callNode == null) ? 0 : callNode.hashCode());
-        result = prime * result + ((parent == null) ? 0 : parent.hashCode());
-        result = prime * result + ((rootCallTarget == null) ? 0 : rootCallTarget.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof TruffleCallPath) {
-            TruffleCallPath other = (TruffleCallPath) obj;
-            if (other.callNode != callNode) {
-                return false;
-            }
-            if (!Objects.equals(other.parent, parent)) {
-                return false;
-            }
-            if (!Objects.equals(other.rootCallTarget, rootCallTarget)) {
-                return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public TruffleCallPath append(TruffleCallPath path) {
-        if (getCallTarget() != path.getRootCallTarget()) {
-            throw new IllegalArgumentException("Pathes are not compatible and can therfore not be appended.");
-        }
-
-        TruffleCallPath append = this;
-        for (TruffleCallPath childPath : path) {
-            if (!childPath.isRoot()) {
-                append = new TruffleCallPath(append, childPath.getCallNode());
-            }
-        }
-        return append;
-    }
-
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java	Wed Apr 23 15:22:20 2014 +0200
+++ /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 java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-
-/**
- * Interface of the Truffle compiler producing an {@link InstalledCode} object from the partial
- * evaluation starting with the AST represented by the given {@link OptimizedCallTarget} node.
- */
-public interface TruffleCompiler {
-
-    Future<InstalledCode> compile(OptimizedCallTarget node);
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,14 +27,12 @@
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
 import java.util.*;
-import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.Assumptions.Assumption;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -55,7 +53,7 @@
 /**
  * Implementation of the Truffle compiler using Graal.
  */
-public class TruffleCompilerImpl implements TruffleCompiler {
+public class TruffleCompilerImpl {
 
     private final Providers providers;
     private final Suites suites;
@@ -64,9 +62,8 @@
     private final GraphBuilderConfiguration config;
     private final RuntimeProvider runtime;
     private final TruffleCache truffleCache;
-    private final ThreadPoolExecutor compileQueue;
 
-    private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class};
+    private static final Class<?>[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class};
 
     public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability,
                     OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints);
@@ -78,20 +75,6 @@
         this.providers = backend.getProviders().copyWith(truffleReplacements);
         this.suites = backend.getSuites().getDefaultSuites();
 
-        // Create compilation queue.
-        CompilerThreadFactory factory = new CompilerThreadFactory("TruffleCompilerThread", new CompilerThreadFactory.DebugConfigAccess() {
-            public GraalDebugConfig getDebugConfig() {
-                if (Debug.isEnabled()) {
-                    GraalDebugConfig debugConfig = DebugEnvironment.initialize(TTY.out().out());
-                    debugConfig.dumpHandlers().add(new TruffleTreeDumpHandler());
-                    return debugConfig;
-                } else {
-                    return null;
-                }
-            }
-        });
-        compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), factory);
-
         ResolvedJavaType[] skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess());
         GraphBuilderConfiguration eagerConfig = GraphBuilderConfiguration.getEagerDefault();
         eagerConfig.setSkippedExceptionTypes(skippedExceptionTypes);
@@ -115,28 +98,15 @@
         return skippedExceptionTypes;
     }
 
-    public Future<InstalledCode> compile(final OptimizedCallTarget compilable) {
-        return compileQueue.submit(new Callable<InstalledCode>() {
-            @Override
-            public InstalledCode call() throws Exception {
-                try (Scope s = Debug.scope("Truffle", new TruffleDebugJavaMethod(compilable))) {
-                    return compileMethodImpl((OptimizedCallTargetImpl) compilable);
-                } catch (Throwable e) {
-                    throw Debug.handle(e);
-                }
-            }
-        });
-    }
-
     public static final DebugTimer PartialEvaluationTime = Debug.timer("PartialEvaluationTime");
     public static final DebugTimer CompilationTime = Debug.timer("CompilationTime");
     public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation");
 
-    private InstalledCode compileMethodImpl(final OptimizedCallTargetImpl compilable) {
+    public void compileMethodImpl(final OptimizedCallTarget compilable) {
         final StructuredGraph graph;
 
         if (TraceTruffleCompilation.getValue()) {
-            OptimizedCallTargetImpl.logOptimizingStart(compilable);
+            OptimizedCallTargetLog.logOptimizingStart(compilable);
         }
 
         long timeCompilationStarted = System.nanoTime();
@@ -146,49 +116,39 @@
         }
 
         if (Thread.currentThread().isInterrupted()) {
-            return null;
+            return;
         }
 
         long timePartialEvaluationFinished = System.nanoTime();
         int nodeCountPartialEval = graph.getNodeCount();
-        InstalledCode compiledMethod = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog());
+        CompilationResult compilationResult = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog(), compilable);
         long timeCompilationFinished = System.nanoTime();
         int nodeCountLowered = graph.getNodeCount();
 
-        if (compiledMethod == null) {
-            throw new BailoutException("Could not install method, code cache is full!");
-        }
-
-        if (!compiledMethod.isValid()) {
-            return null;
-        }
-
         if (TraceTruffleCompilation.getValue()) {
-            byte[] code = compiledMethod.getCode();
-            int calls = OptimizedCallUtils.countCalls(compilable.getInliningResult(), new TruffleCallPath(compilable));
-            int inlinedCalls = (compilable.getInliningResult() != null ? compilable.getInliningResult().size() : 0);
+            int calls = OptimizedCallUtils.countCalls(compilable);
+            int inlinedCalls = OptimizedCallUtils.countCallsInlined(compilable);
             int dispatchedCalls = calls - inlinedCalls;
             Map<String, Object> properties = new LinkedHashMap<>();
-            OptimizedCallTarget.addASTSizeProperty(compilable.getInliningResult(), new TruffleCallPath(compilable), properties);
+            OptimizedCallTargetLog.addASTSizeProperty(compilable, properties);
             properties.put("Time", String.format("%5.0f(%4.0f+%-4.0f)ms", //
                             (timeCompilationFinished - timeCompilationStarted) / 1e6, //
                             (timePartialEvaluationFinished - timeCompilationStarted) / 1e6, //
                             (timeCompilationFinished - timePartialEvaluationFinished) / 1e6));
             properties.put("CallNodes", String.format("I %5d/D %5d", inlinedCalls, dispatchedCalls));
             properties.put("GraalNodes", String.format("%5d/%5d", nodeCountPartialEval, nodeCountLowered));
-            properties.put("CodeSize", code != null ? code.length : 0);
+            properties.put("CodeSize", compilationResult.getTargetCodeSize());
             properties.put("Source", formatSourceSection(compilable.getRootNode().getSourceSection()));
 
-            OptimizedCallTargetImpl.logOptimizingDone(compilable, properties);
+            OptimizedCallTargetLog.logOptimizingDone(compilable, properties);
         }
-        return compiledMethod;
     }
 
     private static String formatSourceSection(SourceSection sourceSection) {
         return sourceSection != null ? sourceSection.toString() : "n/a";
     }
 
-    public InstalledCode compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog) {
+    public CompilationResult compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode) {
         try (Scope s = Debug.scope("TruffleFinal")) {
             Debug.dump(graph, "After TruffleTier");
         } catch (Throwable e) {
@@ -224,7 +184,7 @@
 
         InstalledCode installedCode;
         try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); TimerCloseable a = CodeInstallationTime.start()) {
-            installedCode = providers.getCodeCache().addMethod(graph.method(), result, speculationLog);
+            installedCode = providers.getCodeCache().addMethod(graph.method(), result, speculationLog, predefinedInstalledCode);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
@@ -236,7 +196,7 @@
         if (Debug.isLogEnabled()) {
             Debug.log(providers.getCodeCache().disassemble(result, installedCode));
         }
-        return installedCode;
+        return result;
     }
 
     private PhaseSuite<HighTierContext> createGraphBuilderSuite() {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -72,15 +72,15 @@
     @Option(help = "Enable asynchronous truffle compilation in background thread")
     public static final OptionValue<Boolean> TruffleBackgroundCompilation = new OptionValue<>(true);
     @Option(help = "")
-    public static final OptionValue<Boolean> TruffleUseTimeForCompilationDecision = new OptionValue<>(false);
-    @Option(help = "")
     public static final OptionValue<Integer> TruffleCompilationDecisionTime = new OptionValue<>(100);
     @Option(help = "")
     public static final OptionValue<Boolean> TruffleCompilationDecisionTimePrintFail = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleReturnTypeSpeculation = new OptionValue<>(true);
 
     // tracing
     @Option(help = "")
-    public static final OptionValue<Boolean> TraceTruffleCompilation = new OptionValue<>(true);
+    public static final OptionValue<Boolean> TraceTruffleCompilation = new OptionValue<>(false);
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleCompilationDetails = new OptionValue<>(false);
     @Option(help = "")
@@ -94,9 +94,7 @@
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleCacheDetails = new OptionValue<>(false);
     @Option(help = "")
-    public static final OptionValue<Boolean> TraceTruffleCompilationExceptions = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> TruffleCompilationExceptionsAreFatal = new OptionValue<>(true);
+    public static final OptionValue<Boolean> TruffleCompilationExceptionsAreFatal = new OptionValue<>(false);
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleInlining = new OptionValue<>(false);
     @Option(help = "")
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.truffle;
 
 import java.io.*;
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.Map.Entry;
 
@@ -31,13 +30,16 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.util.*;
 
 public class TruffleExpansionLogger {
 
+    private final Providers providers;
     private final ExpansionTree root;
     private final Map<MethodCallTargetNode, ExpansionTree> callToParentTree = new HashMap<>();
 
-    public TruffleExpansionLogger(StructuredGraph graph) {
+    public TruffleExpansionLogger(Providers providers, StructuredGraph graph) {
+        this.providers = providers;
         root = new ExpansionTree(null, null, graph.method(), -1);
         registerParentInCalls(root, graph);
     }
@@ -47,16 +49,16 @@
 
         int sourceMethodBci = callTarget.invoke().bci();
         ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-        Object targetReceiver = null;
-        if (!Modifier.isStatic(sourceMethod.getModifiers()) && callTarget.receiver().isConstant()) {
-            targetReceiver = callTarget.receiver().asConstant().asObject();
+        ResolvedJavaType targetReceiverType = null;
+        if (!sourceMethod.isStatic() && callTarget.receiver().isConstant()) {
+            targetReceiverType = providers.getMetaAccess().lookupJavaType(callTarget.arguments().first().asConstant());
         }
 
-        if (targetReceiver != null) {
+        if (targetReceiverType != null) {
             ExpansionTree parent = callToParentTree.get(callTarget);
             assert parent != null;
             callToParentTree.remove(callTarget);
-            ExpansionTree tree = new ExpansionTree(parent, targetReceiver, targetMethod, sourceMethodBci);
+            ExpansionTree tree = new ExpansionTree(parent, targetReceiverType, targetMethod, sourceMethodBci);
             registerParentInCalls(tree, inliningGraph);
         }
     }
@@ -94,14 +96,14 @@
     private static final class ExpansionTree implements Comparable<ExpansionTree> {
 
         private final ExpansionTree parent;
-        private final Object targetReceiver;
+        private final ResolvedJavaType targetReceiverType;
         private final ResolvedJavaMethod targetMethod;
         private final int parentBci;
         private final List<ExpansionTree> children = new ArrayList<>();
 
-        public ExpansionTree(ExpansionTree parent, Object receiver, ResolvedJavaMethod targetMethod, int parentBci) {
+        public ExpansionTree(ExpansionTree parent, ResolvedJavaType targetReceiverType, ResolvedJavaMethod targetMethod, int parentBci) {
             this.parent = parent;
-            this.targetReceiver = receiver;
+            this.targetReceiverType = targetReceiverType;
             this.targetMethod = targetMethod;
             this.parentBci = parentBci;
             if (parent != null) {
@@ -141,9 +143,9 @@
             }
 
             String constantType = "";
-            if (targetReceiver != null) {
-                if (!targetReceiver.getClass().getSimpleName().equals(className)) {
-                    constantType = "<" + targetReceiver.getClass().getSimpleName() + ">";
+            if (targetReceiverType != null) {
+                if (!targetReceiverType.getName().equals(className)) {
+                    constantType = "<" + targetReceiverType.getName() + ">";
                 }
             }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,164 +24,103 @@
 
 import java.util.*;
 
-import com.oracle.graal.truffle.OptimizedCallUtils.InlinedCallVisitor;
 import com.oracle.truffle.api.nodes.*;
 
 public final class TruffleInliningHandler {
 
-    private final ProfileScoreComparator inliningOrder = new ProfileScoreComparator();
-
-    private final OptimizedCallTarget callTarget;
+    private static final int MAXIMUM_RECURSIVE_DEPTH = 15;
+    private static final ProfileScoreComparator INLINING_SCORE = new ProfileScoreComparator();
     private final TruffleInliningPolicy policy;
-    private final Map<TruffleCallPath, TruffleInliningProfile> profiles;
-    private final Map<OptimizedCallTarget, TruffleInliningResult> inliningResultCache;
+    private final Map<OptimizedCallTarget, TruffleInliningResult> resultCache;
 
-    public TruffleInliningHandler(OptimizedCallTarget callTarget, TruffleInliningPolicy policy, Map<OptimizedCallTarget, TruffleInliningResult> inliningResultCache) {
-        this.callTarget = callTarget;
+    public TruffleInliningHandler(TruffleInliningPolicy policy) {
         this.policy = policy;
-        this.profiles = new HashMap<>();
-        this.inliningResultCache = inliningResultCache;
+        this.resultCache = new HashMap<>();
     }
 
-    public TruffleInliningResult inline(int originalTotalNodeCount) {
-        Set<TruffleCallPath> inlinedPathes = new HashSet<>();
-        TruffleInliningResult result = new TruffleInliningResult(callTarget, inlinedPathes);
-        TruffleCallPath startPath = new TruffleCallPath(callTarget);
-
-        PriorityQueue<TruffleInliningProfile> queue = new PriorityQueue<>(10, inliningOrder);
-        queueCallSitesForInlining(result, startPath, queue);
-
-        int budget = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - originalTotalNodeCount;
-        int index = 0;
-        while (!queue.isEmpty()) {
-            TruffleInliningProfile profile = queue.poll();
-            profile.setQueryIndex(index);
-            budget = tryInline(queue, result, inlinedPathes, profile, budget);
-            profiles.put(profile.getCallPath(), profile);
-            index++;
+    public TruffleInliningResult decideInlining(OptimizedCallTarget target, int depth) {
+        if (resultCache.containsKey(target)) {
+            return resultCache.get(target);
         }
+        resultCache.put(target, null);
+        TruffleInliningResult result = decideInliningImpl(target, depth);
+        resultCache.put(target, result);
         return result;
     }
 
-    private int tryInline(PriorityQueue<TruffleInliningProfile> queue, TruffleInliningResult result, Set<TruffleCallPath> inlinedPathes, TruffleInliningProfile profile, int budget) {
-
-        if (policy.isAllowed(result, profile, budget)) {
-            int remainingBudget;
-            inlinedPathes.add(profile.getCallPath());
-            if (policy.isAllowedDeep(result, profile, budget)) {
-                if (profile.getRecursiveResult() != null) {
-                    TruffleInliningResult inliningResult = profile.getRecursiveResult();
-                    for (TruffleCallPath recursiveInlinedPath : inliningResult) {
-                        inlinedPathes.add(profile.getCallPath().append(recursiveInlinedPath));
-                    }
-                }
-                remainingBudget = budget - profile.getDeepNodeCount();
-            } else {
-                remainingBudget = budget - profile.getNodeCount();
+    private TruffleInliningResult decideInliningImpl(OptimizedCallTarget target, int depth) {
+        List<TruffleInliningProfile> profiles = lookupProfiles(target, depth);
+        Set<TruffleInliningProfile> inlined = new HashSet<>();
+        Collections.sort(profiles, INLINING_SCORE);
+        int budget = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - OptimizedCallUtils.countNonTrivialNodes(target, true);
+        int index = 0;
+        for (TruffleInliningProfile profile : profiles) {
+            profile.setQueryIndex(index++);
+            if (policy.isAllowed(profile, budget)) {
+                inlined.add(profile);
+                budget -= profile.getDeepNodeCount();
             }
-
-            queueCallSitesForInlining(result, profile.getCallPath(), queue);
-            return remainingBudget;
         }
 
-        return budget;
+        int deepNodeCount = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - budget;
+        return new TruffleInliningResult(target, profiles, inlined, deepNodeCount);
+    }
+
+    private List<TruffleInliningProfile> lookupProfiles(final OptimizedCallTarget target, int depth) {
+        final List<OptimizedDirectCallNode> callNodes = new ArrayList<>();
+        target.getRootNode().accept(new NodeVisitor() {
+            public boolean visit(Node node) {
+                if (node instanceof OptimizedDirectCallNode) {
+                    callNodes.add((OptimizedDirectCallNode) node);
+                }
+                return true;
+            }
+        });
+        final List<TruffleInliningProfile> profiles = new ArrayList<>();
+        for (OptimizedDirectCallNode callNode : callNodes) {
+            profiles.add(lookupProfile(target, callNode, depth));
+        }
+        return profiles;
+    }
+
+    public TruffleInliningProfile lookupProfile(OptimizedCallTarget parentTarget, OptimizedDirectCallNode ocn, int depth) {
+        OptimizedCallTarget target = ocn.getCurrentCallTarget();
+
+        int callSites = ocn.getCurrentCallTarget().getKnownCallSiteCount();
+        int nodeCount = OptimizedCallUtils.countNonTrivialNodes(target, false);
+        double frequency = calculateFrequency(parentTarget, ocn);
+        boolean forced = ocn.isInliningForced();
+
+        int deepNodeCount;
+        TruffleInliningResult recursiveResult;
+        boolean recursiveCall = false;
+        if (depth > MAXIMUM_RECURSIVE_DEPTH) {
+            deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(target, true);
+            recursiveResult = null;
+        } else {
+            recursiveResult = decideInlining(ocn.getCurrentCallTarget(), depth + 1);
+            if (recursiveResult == null) {
+                recursiveCall = true;
+                deepNodeCount = Integer.MAX_VALUE;
+            } else {
+                deepNodeCount = recursiveResult.getNodeCount();
+            }
+        }
+
+        TruffleInliningProfile profile = new TruffleInliningProfile(ocn, callSites, nodeCount, deepNodeCount, frequency, forced, recursiveCall, recursiveResult);
+        profile.setScore(policy.calculateScore(profile));
+        return profile;
     }
 
     public TruffleInliningPolicy getPolicy() {
         return policy;
     }
 
-    public Map<TruffleCallPath, TruffleInliningProfile> getProfiles() {
-        return profiles;
-    }
-
-    private void queueCallSitesForInlining(final TruffleInliningResult currentDecision, TruffleCallPath fromPath, final Collection<TruffleInliningProfile> queue) {
-        fromPath.getCallTarget().getRootNode().accept(new InlinedCallVisitor(currentDecision, fromPath) {
-            @Override
-            public boolean visit(TruffleCallPath path, Node node) {
-                if (node instanceof OptimizedCallNode) {
-                    if (!currentDecision.isInlined(path)) {
-                        addToQueue(queue, currentDecision, path);
-                    }
-                }
-                return true;
-            }
-        });
-    }
-
-    private void addToQueue(final Collection<TruffleInliningProfile> queue, final TruffleInliningResult currentDecision, TruffleCallPath path) {
-        queue.add(lookupProfile(currentDecision, path));
-    }
-
-    public List<TruffleInliningProfile> lookupProfiles(final TruffleInliningResult currentDecision, TruffleCallPath fromPath) {
-        final List<TruffleInliningProfile> pathes = new ArrayList<>();
-        fromPath.getCallTarget().getRootNode().accept(new InlinedCallVisitor(currentDecision, fromPath) {
-            @Override
-            public boolean visit(TruffleCallPath path, Node node) {
-                if (node instanceof OptimizedCallNode) {
-                    pathes.add(lookupProfile(currentDecision, path));
-                }
-                return true;
-            }
-        });
-        return pathes;
+    private static double calculateFrequency(OptimizedCallTarget target, OptimizedDirectCallNode ocn) {
+        return (double) Math.max(1, ocn.getCallCount()) / (double) Math.max(1, target.getCompilationProfile().getCallCount());
     }
 
-    public TruffleInliningProfile lookupProfile(TruffleInliningResult state, TruffleCallPath callPath) {
-        TruffleInliningProfile profile = profiles.get(callPath);
-        if (profile != null) {
-            return profile;
-        }
-
-        int callSites = callPath.getCallTarget().getKnownCallSiteCount();
-        int nodeCount = OptimizedCallUtils.countNonTrivialNodes(state, callPath);
-        double frequency = calculatePathFrequency(callPath);
-        boolean forced = callPath.getCallNode().isInlined();
-        TruffleInliningResult recursiveResult = lookupChildResult(callPath, nodeCount);
-        int deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(recursiveResult, new TruffleCallPath(callPath.getCallTarget()));
-
-        profile = new TruffleInliningProfile(callPath, callSites, nodeCount, deepNodeCount, frequency, forced, recursiveResult);
-        profile.setScore(policy.calculateScore(profile));
-        profiles.put(callPath, profile);
-
-        return profile;
-    }
-
-    private TruffleInliningResult lookupChildResult(TruffleCallPath callPath, int nodeCount) {
-        OptimizedCallTarget target = callPath.getCallTarget();
-
-        TruffleInliningResult recursiveResult = target.getInliningResult();
-
-        if (recursiveResult == null) {
-            recursiveResult = inliningResultCache.get(callPath.getCallTarget());
-
-            if (recursiveResult == null) {
-                if (inliningResultCache.containsKey(target)) {
-                    // cancel on recursion
-                    return new TruffleInliningResult(target, new HashSet<TruffleCallPath>());
-                }
-                inliningResultCache.put(target, null);
-                TruffleInliningHandler handler = new TruffleInliningHandler(target, policy, inliningResultCache);
-                recursiveResult = handler.inline(nodeCount);
-                inliningResultCache.put(callPath.getCallTarget(), recursiveResult);
-            }
-        }
-        return recursiveResult;
-    }
-
-    private static double calculatePathFrequency(TruffleCallPath callPath) {
-        int parentCallCount = -1;
-        double f = 1.0d;
-        for (TruffleCallPath path : callPath.toList()) {
-            if (parentCallCount != -1) {
-                f *= path.getCallNode().getCallCount() / (double) parentCallCount;
-            }
-            parentCallCount = path.getCallTarget().getCompilationProfile().getCallCount();
-        }
-        return f;
-    }
-
-    private final class ProfileScoreComparator implements Comparator<TruffleInliningProfile> {
+    private final static class ProfileScoreComparator implements Comparator<TruffleInliningProfile> {
 
         public int compare(TruffleInliningProfile o1, TruffleInliningProfile o2) {
             return Double.compare(o2.getScore(), o1.getScore());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,9 +24,7 @@
 
 public interface TruffleInliningPolicy {
 
-    boolean isAllowed(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget);
-
-    boolean isAllowedDeep(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget);
+    boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft);
 
     double calculateScore(TruffleInliningProfile profile);
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,34 +24,41 @@
 
 import java.util.*;
 
-public class TruffleInliningProfile implements Comparable<TruffleInliningProfile> {
+public class TruffleInliningProfile {
 
-    private final TruffleCallPath callPath;
-
+    private final OptimizedDirectCallNode callNode;
     private final int nodeCount;
     private final int deepNodeCount;
     private final int callSites;
     private final double frequency;
     private final boolean forced;
+    private final boolean recursiveCall;
     private final TruffleInliningResult recursiveResult;
 
     private String failedReason;
     private int queryIndex = -1;
     private double score;
 
-    public TruffleInliningProfile(TruffleCallPath callPath, int callSites, int nodeCount, int deepNodeCount, double frequency, boolean forced, TruffleInliningResult recursiveResult) {
-        if (callPath.isRoot()) {
-            throw new IllegalArgumentException("Root call path not profilable.");
-        }
+    public TruffleInliningProfile(OptimizedDirectCallNode callNode, int callSites, int nodeCount, int deepNodeCount, double frequency, boolean forced, boolean recursiveCall,
+                    TruffleInliningResult recursiveResult) {
+        this.callNode = callNode;
         this.callSites = callSites;
-        this.callPath = callPath;
         this.nodeCount = nodeCount;
         this.deepNodeCount = deepNodeCount;
         this.frequency = frequency;
+        this.recursiveCall = recursiveCall;
         this.forced = forced;
         this.recursiveResult = recursiveResult;
     }
 
+    public boolean isRecursiveCall() {
+        return recursiveCall;
+    }
+
+    public OptimizedDirectCallNode getCallNode() {
+        return callNode;
+    }
+
     public int getCallSites() {
         return callSites;
     }
@@ -100,21 +107,12 @@
         return deepNodeCount;
     }
 
-    public TruffleCallPath getCallPath() {
-        return callPath;
-    }
-
-    public int compareTo(TruffleInliningProfile o) {
-        return callPath.compareTo(o.callPath);
-    }
-
     public Map<String, Object> getDebugProperties() {
         Map<String, Object> properties = new LinkedHashMap<>();
-        properties.put("callSites", callSites);
-        properties.put("nodeCount", nodeCount);
+        properties.put("nodeCount", String.format("%5d/%5d", deepNodeCount, nodeCount));
         properties.put("frequency", frequency);
-        properties.put("score", score);
-        properties.put(String.format("index=%3d, force=%s", queryIndex, (forced ? "Y" : "N")), "");
+        properties.put("score", String.format("%8.4f", getScore()));
+        properties.put(String.format("index=%3d, force=%s, callSites=%2d", queryIndex, (forced ? "Y" : "N"), callSites), "");
         properties.put("reason", failedReason);
         return properties;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,34 +24,49 @@
 
 import java.util.*;
 
-public final class TruffleInliningResult implements Iterable<TruffleCallPath> {
+public final class TruffleInliningResult implements Iterable<TruffleInliningProfile> {
 
     private final OptimizedCallTarget callTarget;
-    private final Set<TruffleCallPath> inlinedPathes;
+    private final Map<OptimizedDirectCallNode, TruffleInliningProfile> profiles;
+    private final Set<TruffleInliningProfile> inlined;
+    private final int nodeCount;
 
-    public TruffleInliningResult(OptimizedCallTarget callTarget, Set<TruffleCallPath> pathes) {
+    public TruffleInliningResult(OptimizedCallTarget callTarget, List<TruffleInliningProfile> profiles, Set<TruffleInliningProfile> inlined, int nodeCount) {
         this.callTarget = callTarget;
-        this.inlinedPathes = pathes;
+        this.profiles = new HashMap<>();
+        for (TruffleInliningProfile profile : profiles) {
+            this.profiles.put(profile.getCallNode(), profile);
+        }
+        this.nodeCount = nodeCount;
+        this.inlined = inlined;
+    }
+
+    public Map<OptimizedDirectCallNode, TruffleInliningProfile> getProfiles() {
+        return profiles;
+    }
+
+    public int getNodeCount() {
+        return nodeCount;
     }
 
     public OptimizedCallTarget getCallTarget() {
         return callTarget;
     }
 
-    public boolean isInlined(TruffleCallPath path) {
-        return inlinedPathes.contains(path);
+    public boolean isInlined(OptimizedDirectCallNode path) {
+        return inlined.contains(profiles.get(path));
     }
 
     public int size() {
-        return inlinedPathes.size();
+        return inlined.size();
     }
 
-    public Iterator<TruffleCallPath> iterator() {
-        return Collections.unmodifiableSet(inlinedPathes).iterator();
+    public Iterator<TruffleInliningProfile> iterator() {
+        return Collections.unmodifiableSet(inlined).iterator();
     }
 
     @Override
     public String toString() {
-        return inlinedPathes.toString();
+        return inlined.toString();
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,39 +26,33 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.substitutions.*;
 
 /**
  * Custom {@link Replacements} for Truffle compilation.
  */
-public final class TruffleReplacements extends ReplacementsImpl {
+public abstract class TruffleReplacements extends ReplacementsImpl {
 
     private final Replacements graalReplacements;
 
-    private TruffleReplacements(Providers providers) {
-        super(providers, providers.getReplacements().getAssumptions(), providers.getCodeCache().getTarget());
+    protected TruffleReplacements(Providers providers, SnippetReflectionProvider snippetReflection) {
+        super(providers, snippetReflection, providers.getReplacements().getAssumptions(), providers.getCodeCache().getTarget());
         this.graalReplacements = providers.getReplacements();
+
+        registerTruffleSubstitutions();
     }
 
-    public static Replacements makeInstance() {
-        Providers graalProviders = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders();
-        Replacements truffleReplacements = new TruffleReplacements(graalProviders);
-
-        truffleReplacements.registerSubstitutions(CompilerAssertsSubstitutions.class);
-        truffleReplacements.registerSubstitutions(CompilerDirectivesSubstitutions.class);
-        truffleReplacements.registerSubstitutions(ExactMathSubstitutions.class);
-        truffleReplacements.registerSubstitutions(OptimizedAssumptionSubstitutions.class);
-        truffleReplacements.registerSubstitutions(OptimizedCallTargetSubstitutions.class);
-        truffleReplacements.registerSubstitutions(OptimizedCallTargetImplSubstitutions.class);
-
-        return truffleReplacements;
+    protected void registerTruffleSubstitutions() {
+        registerSubstitutions(CompilerAssertsSubstitutions.class);
+        registerSubstitutions(CompilerDirectivesSubstitutions.class);
+        registerSubstitutions(ExactMathSubstitutions.class);
+        registerSubstitutions(OptimizedAssumptionSubstitutions.class);
+        registerSubstitutions(OptimizedCallTargetSubstitutions.class);
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.truffle;
 
-import java.util.*;
-
 import com.oracle.graal.debug.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.*;
@@ -46,7 +44,6 @@
             final OptimizedCallTarget oct = (OptimizedCallTarget) callTarget;
 
             visitor.beginGroup(callTarget.toString());
-            dumpInlinedCalls(visitor, oct);
             dumpFullTree(visitor, message, oct);
             visitor.printToNetwork(false);
         }
@@ -54,22 +51,17 @@
 
     private static void dumpFullTree(final GraphPrintVisitor visitor, final String message, final OptimizedCallTarget oct) {
         visitor.setChildSupplier(new ChildSupplier() {
-            private TruffleCallPath currentPath = new TruffleCallPath(oct);
 
             public Object startNode(Object callNode) {
-                if (callNode instanceof OptimizedCallNode) {
-                    currentPath = new TruffleCallPath(currentPath, (OptimizedCallNode) callNode);
-                    if (oct.getInliningResult() != null && oct.getInliningResult().isInlined(currentPath)) {
-                        return ((OptimizedCallNode) callNode).getCurrentRootNode();
+                if (callNode instanceof OptimizedDirectCallNode) {
+                    if (((OptimizedDirectCallNode) callNode).isInlined()) {
+                        return ((OptimizedDirectCallNode) callNode).getCurrentRootNode();
                     }
                 }
                 return null;
             }
 
             public void endNode(Object callNode) {
-                if (callNode instanceof OptimizedCallNode) {
-                    currentPath = currentPath.getParent();
-                }
             }
         });
 
@@ -77,23 +69,6 @@
         visitor.setChildSupplier(null);
     }
 
-    private static void dumpInlinedCalls(final GraphPrintVisitor visitor, final OptimizedCallTarget oct) {
-        final Set<OptimizedCallTarget> visitedRoots = new HashSet<>();
-        oct.getRootNode().accept(new OptimizedCallUtils.InlinedCallVisitor(oct.getInliningResult(), new TruffleCallPath(oct)) {
-            @Override
-            public boolean visit(TruffleCallPath path, Node node) {
-                if (node instanceof OptimizedCallNode) {
-                    OptimizedCallTarget target = ((OptimizedCallNode) node).getCurrentCallTarget();
-                    if (!visitedRoots.contains(target)) {
-                        visitor.beginGraph("inlined " + target.toString()).visit(target.getRootNode());
-                        visitedRoots.add(target);
-                    }
-                }
-                return true;
-            }
-        });
-    }
-
     public void close() {
         // nothing to do
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.truffle.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -39,13 +41,21 @@
         return arguments.first();
     }
 
+    private static SnippetReflectionProvider getSnippetReflection() {
+        /*
+         * This class requires access to the objects encapsulated in Constants, and therefore breaks
+         * the compiler-VM separation of object constants.
+         */
+        return Graal.getRequiredCapability(SnippetReflectionProvider.class);
+    }
+
     @Override
     public void simplify(SimplifierTool tool) {
         ValueNode assumption = getAssumption();
         if (tool.assumptions() != null && assumption.isConstant()) {
             Constant c = assumption.asConstant();
             assert c.getKind() == Kind.Object;
-            Object object = c.asObject();
+            Object object = getSnippetReflection().asObject(c);
             OptimizedAssumption assumptionObject = (OptimizedAssumption) object;
             StructuredGraph graph = graph();
             if (assumptionObject.isValid()) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -40,7 +40,7 @@
         ValueNode arg = arguments.get(0);
         String message = "";
         if (arg.isConstant()) {
-            message = (String) arg.asConstant().asObject();
+            message = arg.asConstant().toValueString();
         }
         throw new BailoutException(message);
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,11 +22,8 @@
  */
 package com.oracle.graal.truffle.nodes;
 
-import java.lang.reflect.*;
-
-import sun.misc.*;
-
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -52,13 +49,9 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (array().isConstant() && !array().isNullConstant() && index().isConstant()) {
-            Object array = array().asConstant().asObject();
-            long index = index().asConstant().asLong();
-            if (index >= 0 && index < Array.getLength(array)) {
-                int arrayBaseOffset = Unsafe.getUnsafe().arrayBaseOffset(array.getClass());
-                int arrayIndexScale = Unsafe.getUnsafe().arrayIndexScale(array.getClass());
-                Constant constant = tool.getConstantReflection().readUnsafeConstant(elementKind(), array().asConstant(), arrayBaseOffset + index * arrayIndexScale, elementKind() == Kind.Object);
+        if (array().isConstant() && index().isConstant()) {
+            Constant constant = tool.getConstantReflection().readArrayElement(array().asConstant(), index().asConstant().asInt());
+            if (constant != null) {
                 return ConstantNode.forConstant(constant, tool.getMetaAccess(), graph());
             }
         }
@@ -66,7 +59,7 @@
     }
 
     private static Stamp createStamp(ValueNode array, Kind kind) {
-        ResolvedJavaType type = ObjectStamp.typeOrNull(array);
+        ResolvedJavaType type = StampTool.typeOrNull(array);
         if (kind == Kind.Object && type != null) {
             return StampFactory.declared(type.getComponentType());
         } else {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/ObjectLocationIdentity.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 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.nodes;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * A {@link LocationIdentity} wrapping an object.
+ */
+public final class ObjectLocationIdentity implements LocationIdentity {
+
+    private static HashMap<Constant, LocationIdentity> map = new HashMap<>();
+
+    private Constant object;
+
+    public static LocationIdentity create(Constant object) {
+        assert object.getKind() == Kind.Object && object.isNonNull();
+        synchronized (map) {
+            if (map.containsKey(object)) {
+                return map.get(object);
+            } else {
+                ObjectLocationIdentity locationIdentity = new ObjectLocationIdentity(object);
+                map.put(object, locationIdentity);
+                return locationIdentity;
+            }
+        }
+    }
+
+    private ObjectLocationIdentity(Constant object) {
+        this.object = object;
+    }
+
+    @Override
+    public String toString() {
+        return "Identity(" + object + ")";
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.truffle.nodes.arithmetic;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -77,7 +78,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
         return graph().add(new IntegerAddExactSplitNode(stamp(), x(), y(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,13 +23,13 @@
 package com.oracle.graal.truffle.nodes.arithmetic;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+    public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -28,5 +28,5 @@
 
 interface IntegerExactArithmeticNode extends Lowerable, IterableNodeType {
 
-    IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt);
+    IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt);
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,19 +23,19 @@
 package com.oracle.graal.truffle.nodes.arithmetic;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable {
 
-    @Successor private AbstractBeginNode overflowSuccessor;
-    @Successor private AbstractBeginNode next;
+    @Successor private BeginNode overflowSuccessor;
+    @Successor private BeginNode next;
     @Input private ValueNode x;
     @Input private ValueNode y;
 
-    public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+    public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp);
         this.x = x;
         this.y = y;
@@ -44,20 +44,20 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         return successor == next ? 1 : 0;
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         assert probability(successor) == value;
     }
 
-    public AbstractBeginNode getNext() {
+    public BeginNode getNext() {
         return next;
     }
 
-    public AbstractBeginNode getOverflowSuccessor() {
+    public BeginNode getOverflowSuccessor() {
         return overflowSuccessor;
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,12 @@
 package com.oracle.graal.truffle.nodes.arithmetic;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 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.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.truffle.api.*;
 
 /**
@@ -74,7 +74,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
         return graph().add(new IntegerMulExactSplitNode(stamp(), x(), y(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,13 +23,13 @@
 package com.oracle.graal.truffle.nodes.arithmetic;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+    public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.truffle.nodes.arithmetic;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -77,7 +78,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
         return graph().add(new IntegerSubExactSplitNode(stamp(), x(), y(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,13 +23,13 @@
 package com.oracle.graal.truffle.nodes.arithmetic;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+    public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * 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.frame;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+
+public class ForceMaterializeNode extends FixedWithNextNode implements LIRGenLowerable {
+
+    @Input private ValueNode object;
+
+    public ForceMaterializeNode(ValueNode object) {
+        super(StampFactory.forVoid());
+        this.object = object;
+    }
+
+    public void generate(NodeLIRBuilder generator) {
+        // nothing to do
+    }
+
+    @NodeIntrinsic
+    public native static void force(Object object);
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -25,12 +25,15 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.truffle.*;
@@ -64,9 +67,17 @@
         return arguments;
     }
 
+    private static SnippetReflectionProvider getSnippetReflection() {
+        /*
+         * This class requires access to the objects encapsulated in Constants, and therefore breaks
+         * the compiler-VM separation of object constants.
+         */
+        return Graal.getRequiredCapability(SnippetReflectionProvider.class);
+    }
+
     private FrameDescriptor getConstantFrameDescriptor() {
         assert descriptor.isConstant() && !descriptor.isNullConstant();
-        return (FrameDescriptor) descriptor.asConstant().asObject();
+        return (FrameDescriptor) getSnippetReflection().asObject(descriptor.asConstant());
     }
 
     private int getFrameSize() {
@@ -151,7 +162,7 @@
 
         if (frameSize > 0) {
             FrameDescriptor frameDescriptor = getConstantFrameDescriptor();
-            ConstantNode objectDefault = ConstantNode.forObject(frameDescriptor.getTypeConversion().getDefaultValue(), tool.getMetaAccessProvider(), graph());
+            ConstantNode objectDefault = ConstantNode.forConstant(getSnippetReflection().forObject(frameDescriptor.getTypeConversion().getDefaultValue()), tool.getMetaAccessProvider(), graph());
             ConstantNode tagDefault = ConstantNode.forByte((byte) 0, graph());
             for (int i = 0; i < frameSize; i++) {
                 objectArrayEntryState[i] = objectDefault;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,13 +23,15 @@
 package com.oracle.graal.truffle.nodes.typesystem;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 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.graal.truffle.nodes.*;
 import com.oracle.truffle.api.*;
 
 /**
@@ -40,8 +42,8 @@
 public class CustomizedUnsafeLoadFinalNode extends FixedWithNextNode implements Canonicalizable, Virtualizable, Lowerable {
     @Input private ValueNode object;
     @Input private ValueNode offset;
-    @Input(InputType.Condition) private ValueNode condition;
-    @Input(InputType.Association) private ValueNode location;
+    @Input private ValueNode condition;
+    @Input private ValueNode location;
     private final Kind accessKind;
 
     public CustomizedUnsafeLoadFinalNode(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) {
@@ -56,7 +58,7 @@
     @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);
+            Constant constant = tool.getConstantReflection().readUnsafeConstant(accessKind, object.asConstant(), offset.asConstant().asLong());
             return ConstantNode.forConstant(constant, tool.getMetaAccess(), graph());
         }
         return this;
@@ -86,12 +88,11 @@
     @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) {
+        if (!location.isConstant() || location.asConstant().isNull()) {
             locationIdentity = LocationIdentity.ANY_LOCATION;
         } else {
-            locationIdentity = ObjectLocationIdentity.create(locationIdentityObject);
+            locationIdentity = ObjectLocationIdentity.create(location.asConstant());
         }
         UnsafeLoadNode result = graph().add(new UnsafeLoadNode(object, offset, accessKind, locationIdentity, compare));
         graph().replaceFixedWithFixed(this, result);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,13 @@
 package com.oracle.graal.truffle.nodes.typesystem;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
 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.truffle.nodes.*;
 import com.oracle.graal.truffle.nodes.asserts.*;
 import com.oracle.truffle.api.*;
 
@@ -54,12 +56,11 @@
             ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX);
             ValueNode offsetArgument = arguments.get(OFFSET_ARGUMENT_INDEX);
             ValueNode conditionArgument = arguments.get(CONDITION_ARGUMENT_INDEX);
-            Object locationIdentityObject = locationArgument.asConstant().asObject();
             LocationIdentity locationIdentity;
-            if (locationIdentityObject == null) {
+            if (locationArgument.asConstant().isNull()) {
                 locationIdentity = LocationIdentity.ANY_LOCATION;
             } else {
-                locationIdentity = ObjectLocationIdentity.create(locationIdentityObject);
+                locationIdentity = ObjectLocationIdentity.create(locationArgument.asConstant());
             }
             CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()));
             Kind returnKind = this.getTargetMethod().getSignature().getReturnKind();
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.truffle.nodes.*;
 import com.oracle.graal.truffle.nodes.asserts.*;
 import com.oracle.truffle.api.*;
 
@@ -53,12 +54,11 @@
             ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX);
             ValueNode offsetArgument = arguments.get(OFFSET_ARGUMENT_INDEX);
             ValueNode valueArgument = arguments.get(VALUE_ARGUMENT_INDEX);
-            Object locationIdentityObject = locationArgument.asConstant().asObject();
             LocationIdentity locationIdentity;
-            if (locationIdentityObject == null) {
+            if (locationArgument.asConstant().isNull()) {
                 locationIdentity = LocationIdentity.ANY_LOCATION;
             } else {
-                locationIdentity = ObjectLocationIdentity.create(locationIdentityObject);
+                locationIdentity = ObjectLocationIdentity.create(locationArgument.asConstant());
             }
 
             UnsafeStoreNode unsafeStoreNode = graph().add(
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.truffle.nodes.typesystem;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 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.type.*;
 import com.oracle.graal.truffle.nodes.asserts.*;
 import com.oracle.truffle.api.*;
 
@@ -55,11 +56,10 @@
         if (classArgument.isConstant() && nonNullArgument.isConstant()) {
             ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX);
             ValueNode conditionArgument = arguments.get(CONDITION_ARGUMENT_INDEX);
-            Class c = (Class) classArgument.asConstant().asObject();
-            if (c == null) {
+            ResolvedJavaType lookupJavaType = tool.getConstantReflection().asJavaType(classArgument.asConstant());
+            if (lookupJavaType == null) {
                 return objectArgument;
             }
-            ResolvedJavaType lookupJavaType = tool.getMetaAccess().lookupJavaType(c);
             Stamp stamp = StampFactory.declared(lookupJavaType, nonNullArgument.asConstant().asInt() != 0);
             ConditionAnchorNode valueAnchorNode = graph().add(new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()))));
             UnsafeCastNode piCast = graph().unique(new UnsafeCastNode(objectArgument, stamp, valueAnchorNode));
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.truffle.*;
 import com.oracle.graal.truffle.nodes.*;
+import com.oracle.graal.truffle.nodes.frame.*;
 import com.oracle.graal.truffle.nodes.typesystem.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
@@ -54,6 +55,11 @@
     }
 
     @MethodSubstitution
+    public static boolean inCompiledCode() {
+        return true;
+    }
+
+    @MethodSubstitution
     public static void interpreterOnly(@SuppressWarnings("unused") Runnable runnable) {
     }
 
@@ -71,7 +77,7 @@
     public static native void bailout(String reason);
 
     @MacroSubstitution(macro = UnsafeTypeCastMacroNode.class, isStatic = true)
-    public static native Object unsafeCast(Object value, Class clazz, boolean condition, boolean nonNull);
+    public static native Object unsafeCast(Object value, Class<?> clazz, boolean condition, boolean nonNull);
 
     @MethodSubstitution
     private static Class<? extends MaterializedFrame> getUnsafeFrameType() {
@@ -165,4 +171,10 @@
     public static Object unsafeGetFinalObject(Object receiver, long offset, boolean condition, Object locationIdentity) {
         return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Object);
     }
+
+    @MethodSubstitution
+    public static void materialize(Object obj) {
+        ForceMaterializeNode.force(obj);
+    }
+
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetImplSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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.*;
-import com.oracle.graal.truffle.nodes.asserts.*;
-
-@ClassSubstitution(OptimizedCallTargetImpl.class)
-public class OptimizedCallTargetImplSubstitutions {
-
-    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
-    public static native Object callHelper(OptimizedCallTarget target, Object[] args);
-
-    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
-    public static native Object interpreterCall(OptimizedCallTarget target, Object[] args);
-
-    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
-    public static native Object compiledCodeInvalidated(OptimizedCallTarget target, Object[] args);
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.truffle.substitutions;
 
 import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.truffle.*;
 import com.oracle.graal.truffle.nodes.frame.*;
 import com.oracle.truffle.api.frame.*;
@@ -34,4 +36,9 @@
     private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) {
         return NewFrameNode.allocate(FrameWithoutBoxing.class, descriptor, args);
     }
+
+    @MethodSubstitution
+    private static Object castArrayFixedLength(Object[] args, int length) {
+        return PiArrayNode.piArrayCast(args, length, StampFactory.forNodeIntrinsic());
+    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,10 +22,12 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -43,7 +45,7 @@
 
     protected final NodeMap<ValueNode> aliases;
     protected final BlockMap<GraphEffectList> blockEffects;
-    private final IdentityHashMap<Loop, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
+    private final IdentityHashMap<Loop<Block>, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
     private final IdentityHashMap<LoopBeginNode, BlockT> loopEntryStates = new IdentityHashMap<>();
 
     private boolean changed;
@@ -105,7 +107,7 @@
             }
 
             @Override
-            protected List<Void> processLoop(Loop loop, Void initialState) {
+            protected List<Void> processLoop(Loop<Block> loop, Void initialState) {
                 LoopInfo<Void> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
                 apply(loopMergeEffects.get(loop), loop);
                 return info.exitStates;
@@ -150,7 +152,7 @@
     }
 
     @Override
-    protected final List<BlockT> processLoop(Loop loop, BlockT initialState) {
+    protected final List<BlockT> processLoop(Loop<Block> loop, BlockT initialState) {
         BlockT loopEntryState = initialState;
         BlockT lastMergedState = cloneState(initialState);
         MergeProcessor mergeProcessor = createMergeProcessor(loop.header);
@@ -174,7 +176,7 @@
                 loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects);
 
                 assert info.exitStates.size() == loop.exits.size();
-                loopEntryStates.put(loop.loopBegin(), loopEntryState);
+                loopEntryStates.put((LoopBeginNode) loop.header.getBeginNode(), loopEntryState);
                 for (int i = 0; i < loop.exits.size(); i++) {
                     assert info.exitStates.get(i) != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header;
                 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -90,7 +90,9 @@
                         listener.getChangedNodes().add(node);
                     }
                 }
-                canonicalizer.applyIncremental(graph, context, listener.getChangedNodes());
+                if (canonicalizer != null) {
+                    canonicalizer.applyIncremental(graph, context, listener.getChangedNodes());
+                }
             }
             changed = true;
         }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.debug.Debug.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationBlockState.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationBlockState.java	Wed Apr 23 15:48:38 2014 +0200
@@ -34,10 +34,10 @@
 
     static class ReadCacheEntry {
 
-        public final ResolvedJavaField identity;
+        public final LocationIdentity identity;
         public final ValueNode object;
 
-        public ReadCacheEntry(ResolvedJavaField identity, ValueNode object) {
+        public ReadCacheEntry(LocationIdentity identity, ValueNode object) {
             this.identity = identity;
             this.object = object;
         }
@@ -95,7 +95,7 @@
         return super.equivalentTo(other);
     }
 
-    public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value, PartialEscapeClosure<?> closure) {
+    public void addReadCache(ValueNode object, LocationIdentity identity, ValueNode value, PartialEscapeClosure<?> closure) {
         ValueNode cacheObject;
         ObjectState obj = closure.getObjectState(this, object);
         if (obj != null) {
@@ -107,7 +107,7 @@
         readCache.put(new ReadCacheEntry(identity, cacheObject), value);
     }
 
-    public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity, PartialEscapeClosure<?> closure) {
+    public ValueNode getReadCache(ValueNode object, LocationIdentity identity, PartialEscapeClosure<?> closure) {
         ValueNode cacheObject;
         ObjectState obj = closure.getObjectState(this, object);
         if (obj != null) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Wed Apr 23 15:48:38 2014 +0200
@@ -39,8 +39,8 @@
 
 public class PEReadEliminationClosure extends PartialEscapeClosure<PEReadEliminationBlockState> {
 
-    public PEReadEliminationClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
-        super(schedule, metaAccess, assumptions);
+    public PEReadEliminationClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) {
+        super(schedule, metaAccess, constantReflection, assumptions);
     }
 
     @Override
@@ -83,6 +83,17 @@
                 } else {
                     processIdentity(state, ANY_LOCATION);
                 }
+            } else if (node instanceof ArrayLengthNode) {
+                ArrayLengthNode length = (ArrayLengthNode) node;
+                ValueNode array = GraphUtil.unproxify(length.array());
+                ValueNode cachedValue = state.getReadCache(array, ARRAY_LENGTH_LOCATION, this);
+                if (cachedValue != null) {
+                    effects.replaceAtUsages(length, cachedValue);
+                    addScalarAlias(length, cachedValue);
+                    deleted = true;
+                } else {
+                    state.addReadCache(array, ARRAY_LENGTH_LOCATION, length, this);
+                }
             } else if (node instanceof MemoryCheckpoint.Single) {
                 METRIC_MEMORYCHECKPOINT.increment();
                 LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
@@ -183,7 +194,7 @@
             }
         }
 
-        private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List<PEReadEliminationBlockState> states) {
+        private void mergeReadCachePhi(PhiNode phi, LocationIdentity identity, List<PEReadEliminationBlockState> states) {
             ValueNode[] values = new ValueNode[phi.valueCount()];
             for (int i = 0; i < phi.valueCount(); i++) {
                 ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity, PEReadEliminationClosure.this);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Apr 23 15:48:38 2014 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -35,7 +36,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.util.*;
@@ -63,8 +63,8 @@
      */
     public static final class Final extends PartialEscapeClosure<PartialEscapeBlockState.Final> {
 
-        public Final(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
-            super(schedule, metaAccess, assumptions);
+        public Final(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) {
+            super(schedule, metaAccess, constantReflection, assumptions);
         }
 
         @Override
@@ -78,10 +78,10 @@
         }
     }
 
-    public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
+    public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) {
         super(schedule);
         this.usages = schedule.getCFG().graph.createNodeBitMap();
-        this.tool = new VirtualizerToolImpl(metaAccess, assumptions, this);
+        this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, assumptions, this);
     }
 
     public Map<Invoke, Double> getHints() {
@@ -132,78 +132,75 @@
     }
 
     private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) {
-        for (Node input : nodeWithState.asNode().inputs()) {
-            if (input instanceof FrameState) {
-                FrameState frameState = (FrameState) input;
-                if (frameState.usages().count() > 1) {
-                    FrameState copy = (FrameState) frameState.copyWithInputs();
-                    nodeWithState.asNode().replaceFirstInput(frameState, copy);
-                    frameState = copy;
-                }
-                final Set<ObjectState> virtual = new ArraySet<>();
-                frameState.applyToNonVirtual(new NodeClosure<ValueNode>() {
+        for (FrameState frameState : nodeWithState.states()) {
+            if (frameState.usages().count() > 1) {
+                FrameState copy = (FrameState) frameState.copyWithInputs();
+                nodeWithState.asNode().replaceFirstInput(frameState, copy);
+                frameState = copy;
+            }
+            final Set<ObjectState> virtual = new ArraySet<>();
+            frameState.applyToNonVirtual(new NodeClosure<ValueNode>() {
 
-                    @Override
-                    public void apply(Node usage, ValueNode value) {
-                        ObjectState valueObj = getObjectState(state, value);
-                        if (valueObj != null) {
-                            virtual.add(valueObj);
-                            effects.replaceFirstInput(usage, value, valueObj.virtual);
-                        } else if (value instanceof VirtualObjectNode) {
-                            ObjectState virtualObj = null;
-                            for (ObjectState obj : state.getStates()) {
-                                if (value == obj.virtual) {
-                                    virtualObj = obj;
-                                    break;
-                                }
-                            }
-                            if (virtualObj != null) {
-                                virtual.add(virtualObj);
+                @Override
+                public void apply(Node usage, ValueNode value) {
+                    ObjectState valueObj = getObjectState(state, value);
+                    if (valueObj != null) {
+                        virtual.add(valueObj);
+                        effects.replaceFirstInput(usage, value, valueObj.virtual);
+                    } else if (value instanceof VirtualObjectNode) {
+                        ObjectState virtualObj = null;
+                        for (ObjectState obj : state.getStates()) {
+                            if (value == obj.virtual) {
+                                virtualObj = obj;
+                                break;
                             }
                         }
-                    }
-                });
-                for (ObjectState obj : state.getStates()) {
-                    if (obj.isVirtual() && obj.hasLocks()) {
-                        virtual.add(obj);
+                        if (virtualObj != null) {
+                            virtual.add(virtualObj);
+                        }
                     }
                 }
+            });
+            for (ObjectState obj : state.getStates()) {
+                if (obj.isVirtual() && obj.hasLocks()) {
+                    virtual.add(obj);
+                }
+            }
 
-                ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
-                while (!queue.isEmpty()) {
-                    ObjectState obj = queue.removeLast();
-                    if (obj.isVirtual()) {
-                        for (ValueNode field : obj.getEntries()) {
-                            if (field instanceof VirtualObjectNode) {
-                                ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
-                                if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
-                                    virtual.add(fieldObj);
-                                    queue.addLast(fieldObj);
-                                }
+            ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
+            while (!queue.isEmpty()) {
+                ObjectState obj = queue.removeLast();
+                if (obj.isVirtual()) {
+                    for (ValueNode field : obj.getEntries()) {
+                        if (field instanceof VirtualObjectNode) {
+                            ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
+                            if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
+                                virtual.add(fieldObj);
+                                queue.addLast(fieldObj);
                             }
                         }
                     }
                 }
-                for (ObjectState obj : virtual) {
-                    EscapeObjectState v;
-                    if (obj.isVirtual()) {
-                        ValueNode[] fieldState = obj.getEntries().clone();
-                        for (int i = 0; i < fieldState.length; i++) {
-                            ObjectState valueObj = getObjectState(state, fieldState[i]);
-                            if (valueObj != null) {
-                                if (valueObj.isVirtual()) {
-                                    fieldState[i] = valueObj.virtual;
-                                } else {
-                                    fieldState[i] = valueObj.getMaterializedValue();
-                                }
+            }
+            for (ObjectState obj : virtual) {
+                EscapeObjectState v;
+                if (obj.isVirtual()) {
+                    ValueNode[] fieldState = obj.getEntries().clone();
+                    for (int i = 0; i < fieldState.length; i++) {
+                        ObjectState valueObj = getObjectState(state, fieldState[i]);
+                        if (valueObj != null) {
+                            if (valueObj.isVirtual()) {
+                                fieldState[i] = valueObj.virtual;
+                            } else {
+                                fieldState[i] = valueObj.getMaterializedValue();
                             }
                         }
-                        v = new VirtualObjectState(obj.virtual, fieldState);
-                    } else {
-                        v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
                     }
-                    effects.addVirtualMapping(frameState, v);
+                    v = new VirtualObjectState(obj.virtual, fieldState);
+                } else {
+                    v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
                 }
+                effects.addVirtualMapping(frameState, v);
             }
         }
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.virtual.phases.ea.PartialEscapePhase.Options.*;
 
 import java.util.*;
@@ -72,9 +72,9 @@
     @Override
     protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule) {
         if (readElimination) {
-            return new PEReadEliminationClosure(schedule, context.getMetaAccess(), context.getAssumptions());
+            return new PEReadEliminationClosure(schedule, context.getMetaAccess(), context.getConstantReflection(), context.getAssumptions());
         } else {
-            return new PartialEscapeClosure.Final(schedule, context.getMetaAccess(), context.getAssumptions());
+            return new PartialEscapeClosure.Final(schedule, context.getMetaAccess(), context.getConstantReflection(), context.getAssumptions());
         }
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,12 +27,12 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
@@ -40,11 +40,13 @@
 class VirtualizerToolImpl implements VirtualizerTool {
 
     private final MetaAccessProvider metaAccess;
+    private final ConstantReflectionProvider constantReflection;
     private final Assumptions assumptions;
     private final PartialEscapeClosure<?> closure;
 
-    VirtualizerToolImpl(MetaAccessProvider metaAccess, Assumptions assumptions, PartialEscapeClosure<?> closure) {
+    VirtualizerToolImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions, PartialEscapeClosure<?> closure) {
         this.metaAccess = metaAccess;
+        this.constantReflection = constantReflection;
         this.assumptions = assumptions;
         this.closure = closure;
     }
@@ -60,12 +62,16 @@
         return metaAccess;
     }
 
+    public ConstantReflectionProvider getConstantReflectionProvider() {
+        return constantReflection;
+    }
+
     @Override
     public Assumptions getAssumptions() {
         return assumptions;
     }
 
-    public void reset(PartialEscapeBlockState newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) {
+    public void reset(PartialEscapeBlockState<?> newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) {
         deleted = false;
         state = newState;
         current = newCurrent;
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.word;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.lang.annotation.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2013, 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.word.nodes;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Location node that can be used inside a snippet without having the elements (including the
+ * location identity and kind) as a snippet constant. Can represent locations in the form of [base +
+ * index * scale + disp]. When the location is created, all elements (base, index, scale, disp) are
+ * nodes. Both scale and disp must eventually canonicalize to {@link ConstantNode constants} so that
+ * this node can be canonicalized to a {@link IndexedLocationNode} or {@link ConstantLocationNode}.
+ */
+public final class SnippetLocationNode extends LocationNode implements Canonicalizable {
+
+    private final SnippetReflectionProvider snippetReflection;
+
+    @Input private ValueNode valueKind;
+    @Input(InputType.Association) private ValueNode locationIdentity;
+    @Input private ValueNode displacement;
+    @Input private ValueNode index;
+    @Input private ValueNode indexScaling;
+
+    public static SnippetLocationNode create(SnippetReflectionProvider snippetReflection, ValueNode identity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling,
+                    Graph graph) {
+        return graph.unique(new SnippetLocationNode(snippetReflection, identity, kind, displacement, index, indexScaling));
+    }
+
+    private SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) {
+        this(snippetReflection, locationIdentity, kind, displacement, null, null);
+    }
+
+    private SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index,
+                    ValueNode indexScaling) {
+        super(StampFactory.object());
+        this.snippetReflection = snippetReflection;
+        this.valueKind = kind;
+        this.locationIdentity = locationIdentity;
+        this.displacement = displacement;
+        this.index = index;
+        this.indexScaling = indexScaling;
+    }
+
+    @Override
+    public Kind getValueKind() {
+        if (valueKind.isConstant()) {
+            return (Kind) snippetReflection.asObject(valueKind.asConstant());
+        }
+        throw new GraalInternalError("Cannot access kind yet because it is not constant: " + valueKind);
+    }
+
+    @Override
+    public LocationIdentity getLocationIdentity() {
+        if (locationIdentity.isConstant()) {
+            return (LocationIdentity) snippetReflection.asObject(locationIdentity.asConstant());
+        }
+        // We do not know our actual location identity yet, so be conservative.
+        return ANY_LOCATION;
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        if (valueKind.isConstant() && locationIdentity.isConstant() && displacement.isConstant() && (indexScaling == null || indexScaling.isConstant())) {
+            Kind constKind = (Kind) snippetReflection.asObject(valueKind.asConstant());
+            LocationIdentity constLocation = (LocationIdentity) snippetReflection.asObject(locationIdentity.asConstant());
+            long constDisplacement = displacement.asConstant().asLong();
+            int constIndexScaling = indexScaling == null ? 0 : indexScaling.asConstant().asInt();
+
+            if (index == null || constIndexScaling == 0) {
+                return ConstantLocationNode.create(constLocation, constKind, constDisplacement, graph());
+            } else if (index.isConstant()) {
+                return ConstantLocationNode.create(constLocation, constKind, index.asConstant().asLong() * constIndexScaling + constDisplacement, graph());
+            } else {
+                return IndexedLocationNode.create(constLocation, constKind, constDisplacement, index, graph(), constIndexScaling);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        throw new GraalInternalError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity);
+    }
+
+    @NodeIntrinsic
+    public static native Location constantLocation(LocationIdentity identity, Kind kind, long displacement);
+
+    @NodeIntrinsic
+    public static native Location indexedLocation(LocationIdentity identity, Kind kind, long displacement, int index, int indexScaling);
+}
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.word.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.phases.*;
 
 /**
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,6 +27,10 @@
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
@@ -49,13 +53,15 @@
 public class WordTypeRewriterPhase extends Phase {
 
     protected final MetaAccessProvider metaAccess;
+    protected final SnippetReflectionProvider snippetReflection;
     protected final ResolvedJavaType wordBaseType;
     protected final ResolvedJavaType wordImplType;
     protected final ResolvedJavaType objectAccessType;
     protected final Kind wordKind;
 
-    public WordTypeRewriterPhase(MetaAccessProvider metaAccess, Kind wordKind) {
+    public WordTypeRewriterPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, Kind wordKind) {
         this.metaAccess = metaAccess;
+        this.snippetReflection = snippetReflection;
         this.wordKind = wordKind;
         this.wordBaseType = metaAccess.lookupJavaType(WordBase.class);
         this.wordImplType = metaAccess.lookupJavaType(Word.class);
@@ -86,7 +92,7 @@
             if (node.isConstant()) {
                 ConstantNode oldConstant = (ConstantNode) node;
                 assert oldConstant.getValue().getKind() == Kind.Object;
-                WordBase value = (WordBase) oldConstant.getValue().asObject();
+                WordBase value = (WordBase) snippetReflection.asObject(oldConstant.getValue());
                 ConstantNode newConstant = ConstantNode.forIntegerKind(wordKind, value.rawValue(), node.graph());
                 graph.replaceFloating(oldConstant, newConstant);
 
@@ -138,7 +144,7 @@
      * own and not in the stamp, {@link #changeToWord} does not perform all necessary changes.
      */
     protected void rewriteAccessIndexed(StructuredGraph graph, AccessIndexedNode node) {
-        ResolvedJavaType arrayType = ObjectStamp.typeOrNull(node.array());
+        ResolvedJavaType arrayType = StampTool.typeOrNull(node.array());
         /*
          * There are cases where the array does not have a known type yet, i.e., the type is null.
          * In that case we assume it is not a word type.
@@ -221,14 +227,14 @@
                 assert arguments.size() == 3;
                 Kind readKind = asKind(callTargetNode.returnType());
                 LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
-                BarrierType barrierType = (BarrierType) arguments.get(2).asConstant().asObject();
+                BarrierType barrierType = (BarrierType) snippetReflection.asObject(arguments.get(2).asConstant());
                 replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, true));
                 break;
             }
             case WRITE:
             case INITIALIZE: {
                 assert arguments.size() == 3 || arguments.size() == 4;
-                Kind writeKind = asKind(targetMethod.getSignature().getParameterType(Modifier.isStatic(targetMethod.getModifiers()) ? 2 : 1, targetMethod.getDeclaringClass()));
+                Kind writeKind = asKind(targetMethod.getSignature().getParameterType(targetMethod.isStatic() ? 2 : 1, targetMethod.getDeclaringClass()));
                 LocationNode location;
                 if (arguments.size() == 3) {
                     location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION);
@@ -359,10 +365,10 @@
 
     private LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, ValueNode locationIdentity) {
         if (locationIdentity.isConstant()) {
-            return makeLocation(graph, offset, readKind, (LocationIdentity) locationIdentity.asConstant().asObject());
+            return makeLocation(graph, offset, readKind, (LocationIdentity) snippetReflection.asObject(locationIdentity.asConstant()));
         }
-        return SnippetLocationNode.create(locationIdentity, ConstantNode.forObject(readKind, metaAccess, graph), ConstantNode.forLong(0, graph), fromSigned(graph, offset),
-                        ConstantNode.forInt(1, graph), graph);
+        return SnippetLocationNode.create(snippetReflection, locationIdentity, ConstantNode.forConstant(snippetReflection.forObject(readKind), metaAccess, graph), ConstantNode.forLong(0, graph),
+                        fromSigned(graph, offset), ConstantNode.forInt(1, graph), graph);
     }
 
     protected LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, LocationIdentity locationIdentity) {
@@ -376,7 +382,7 @@
          * The read must not float outside its block otherwise it may float above an explicit zero
          * check on its base address.
          */
-        read.setGuard(AbstractBeginNode.prevBegin(invoke.asNode()));
+        read.setGuard(BeginNode.prevBegin(invoke.asNode()));
         return read;
     }
 
@@ -397,7 +403,7 @@
     }
 
     protected boolean isWord(ValueNode node) {
-        return isWord(ObjectStamp.typeOrNull(node));
+        return isWord(StampTool.typeOrNull(node));
     }
 
     protected boolean isWord(ResolvedJavaType type) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.word.phases;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.*;
@@ -44,8 +44,8 @@
 
     private final WordTypeRewriterPhase wordAccess;
 
-    public WordTypeVerificationPhase(MetaAccessProvider metaAccess, Kind wordKind) {
-        this.wordAccess = new WordTypeRewriterPhase(metaAccess, wordKind);
+    public WordTypeVerificationPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, Kind wordKind) {
+        this.wordAccess = new WordTypeRewriterPhase(metaAccess, snippetReflection, wordKind);
     }
 
     @Override
@@ -108,7 +108,7 @@
         if (method.getAnnotation(NodeIntrinsic.class) == null) {
             Invoke invoke = (Invoke) callTarget.usages().first();
             NodeInputList<ValueNode> arguments = callTarget.arguments();
-            boolean isStatic = Modifier.isStatic(method.getModifiers());
+            boolean isStatic = method.isStatic();
             int argc = 0;
             if (!isStatic) {
                 ValueNode receiver = arguments.get(argc);
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java	Wed Apr 23 15:48:38 2014 +0200
@@ -61,12 +61,12 @@
  *
  * {@literal @}TypeSystem(types = {boolean.class, int.class, double.class})
  * public abstract class ExampleTypeSystem {
- *
+ * 
  *     {@literal @}TypeCheck
  *     public boolean isInteger(Object value) {
  *         return value instanceof Integer || value instanceof Double;
  *     }
- *
+ * 
  *     {@literal @}TypeCast
  *     public double asInteger(Object value) {
  *         return ((Number)value).doubleValue();
@@ -85,6 +85,6 @@
     /**
      * The list of types as child elements of the {@link TypeSystem}. Each precedes its super type.
      */
-    Class[] value();
+    Class<?>[] value();
 
 }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,7 +30,7 @@
 
 /**
  * <h3>Creating a Root Node</h3>
- * 
+ *
  * <p>
  * A Truffle root node is the entry point into a Truffle tree that represents a guest language
  * method. It contains a {@link RootNode#execute(VirtualFrame)} method that can return a
@@ -38,9 +38,9 @@
  * must however never be called directly. Instead, the Truffle runtime must be used to create a
  * {@link CallTarget} object from a root node using the
  * {@link TruffleRuntime#createCallTarget(RootNode)} method. This call target object can then be
- * executed using the {@link CallTarget#call()} method or one of its overloads.
+ * executed using the {@link CallTarget#call(Object...)} method or one of its overloads.
  * </p>
- * 
+ *
  * <p>
  * The next part of the Truffle API introduction is at
  * {@link com.oracle.truffle.api.test.ChildNodeTest}.
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,7 +24,6 @@
 
 import static org.junit.Assert.*;
 
-import java.io.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
@@ -50,7 +49,7 @@
         RecursiveCallNode callNode = new RecursiveCallNode(new ConstNode(42));
         TestRootNode rootNode2 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(callNode))))));
         final CallTarget target2 = runtime.createCallTarget(rootNode2);
-        callNode.setCallNode(runtime.createCallNode(target2));
+        callNode.setCallNode(runtime.createDirectCallNode(target2));
         NodeUtil.verify(rootNode2);
 
         testTarget(target1, 47, 1_000_000);
@@ -68,8 +67,7 @@
                         assertEquals(expectedResult, result);
                         ai.incrementAndGet();
                     } catch (Throwable t) {
-                        PrintStream out = System.out;
-                        out.println(t);
+                        t.printStackTrace(System.out);
                     }
                 }
             });
@@ -165,7 +163,7 @@
     }
 
     static class RecursiveCallNode extends ValueNode {
-        @Child CallNode callNode;
+        @Child DirectCallNode callNode;
         @Child private ValueNode valueNode;
 
         RecursiveCallNode(ValueNode value) {
@@ -176,13 +174,13 @@
         int execute(VirtualFrame frame) {
             int arg = (Integer) frame.getArguments()[0];
             if (arg > 0) {
-                return (int) callNode.call(new Object[]{(arg - 1)});
+                return (int) callNode.call(frame, new Object[]{(arg - 1)});
             } else {
                 return valueNode.execute(frame);
             }
         }
 
-        void setCallNode(CallNode callNode) {
+        void setCallNode(DirectCallNode callNode) {
             this.callNode = insert(callNode);
         }
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Wed Apr 23 15:48:38 2014 +0200
@@ -27,9 +27,7 @@
 /**
  * Represents the target of a call.
  */
-public abstract class CallTarget {
-
-    public static final Object[] NO_ARGUMENTS = new Object[0];
+public interface CallTarget {
 
     /**
      * Calls this target as a root method..
@@ -37,9 +35,5 @@
      * @param arguments passed arguments as an object array
      * @return the return result of the call
      */
-    public abstract Object call(Object[] arguments);
-
-    public final Object call() {
-        return call(NO_ARGUMENTS);
-    }
+    Object call(Object... arguments);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Wed Apr 23 15:48:38 2014 +0200
@@ -84,6 +84,15 @@
     }
 
     /**
+     * Returns a boolean value indicating whether the method is executed in the compiled code.
+     *
+     * @return {@code false} when executed in the interpreter, {@code true} in compiled code.
+     */
+    public static boolean inCompiledCode() {
+        return false;
+    }
+
+    /**
      * Directive for the compiler that the given runnable should only be executed in the interpreter
      * and ignored in the compiled code.
      *
@@ -619,4 +628,13 @@
     @Target({ElementType.TYPE})
     public @interface ValueType {
     }
+
+    /**
+     * Ensures that the given object is not virtual, i.e., not removed by Escape Analysis at the
+     * point of this call.
+     *
+     * @param obj the object to exclude from Escape Analysis
+     */
+    public static void materialize(Object obj) {
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Wed Apr 23 15:48:38 2014 +0200
@@ -24,11 +24,12 @@
  */
 package com.oracle.truffle.api;
 
-import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.source.*;
 
 /**
- * Information about the runtime context of a Truffle program.
+ * Access to information and basic services in the runtime context for a Truffle-implemented guest
+ * language.
  * <p>
  * <strong>Disclaimer:</strong> this interface is under development and will change.
  */
@@ -46,8 +47,20 @@
     SourceManager getSourceManager();
 
     /**
-     * Gets access to debugging services. Returns an inert instance if no services installed.
+     * Gets access to AST instrumentation services.
+     */
+    Instrumentation instrumentation();
+
+    /**
+     * Access to information visualization services for the specific language.
      */
-    DebugContext getDebugContext();
+    Visualizer visualizer();
 
+    /**
+     * Add instrumentation to subsequently constructed Truffle ASTs for the guest language; every
+     * one added will have the opportunity to add instrumentation.
+     *
+     * @throws IllegalArgumentException if prober not usable for the guest language.
+     */
+    void addNodeProber(ASTNodeProber nodeProber);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Wed Apr 23 15:48:38 2014 +0200
@@ -30,22 +30,7 @@
  * Represents the target of a call to a {@link RootNode}, i.e., to another tree of nodes. Instances
  * of this class can be created using {@link TruffleRuntime#createCallTarget(RootNode)}.
  */
-public abstract class RootCallTarget extends CallTarget {
-
-    private final RootNode rootNode;
-
-    public RootCallTarget(RootNode function) {
-        this.rootNode = function;
-        this.rootNode.setCallTarget(this);
-        this.rootNode.adoptChildren();
-    }
+public interface RootCallTarget extends CallTarget {
 
-    @Override
-    public String toString() {
-        return rootNode.toString();
-    }
-
-    public final RootNode getRootNode() {
-        return rootNode;
-    }
+    RootNode getRootNode();
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Wed Apr 23 15:48:38 2014 +0200
@@ -50,7 +50,20 @@
      */
     RootCallTarget createCallTarget(RootNode rootNode);
 
-    CallNode createCallNode(CallTarget target);
+    /**
+     * Creates a new runtime specific version of {@link DirectCallNode}.
+     *
+     * @param target the direct {@link CallTarget} to call
+     * @return the new call node
+     */
+    DirectCallNode createDirectCallNode(CallTarget target);
+
+    /**
+     * Creates a new runtime specific version of {@link IndirectCallNode}.
+     *
+     * @return the new call node
+     */
+    IndirectCallNode createIndirectCallNode();
 
     /**
      * Creates a new assumption object that can be checked and invalidated.
@@ -90,4 +103,19 @@
      * @return the newly created materialized frame object
      */
     MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor);
+
+    /**
+     * Accesses the current stack, i.e., the contents of the {@link Frame}s and the associated
+     * {@link CallTarget}s.
+     *
+     * @return a lazy collection of {@link FrameInstance}.
+     */
+    Iterable<FrameInstance> getStackTrace();
+
+    /**
+     * Accesses the current frame, i.e., the frame of the closest {@link CallTarget}. It is
+     * important to note that this {@link FrameInstance} supports only slow path access.
+     */
+    FrameInstance getCurrentFrame();
+
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ASTPrinter.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +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.  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.debug;
-
-import java.io.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Language-agnostic access to AST-based debugging support.
- * <p>
- * <strong>WARNING:</strong> this interface is under development and will change substantially.
- */
-public interface ASTPrinter {
-
-    /**
-     * Prints a textual AST display, one line per node, with nesting.
-     * 
-     * @param p
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     * @param markNode a node to mark with a textual arrow prefix, if present.
-     */
-    void printTree(PrintWriter p, Node node, int maxDepth, Node markNode);
-
-    /**
-     * Creates a textual AST display, one line per node, with nesting.
-     * 
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     * @param markNode a node to mark with a textual arrow prefix, if present.
-     */
-    String printTreeToString(Node node, int maxDepth, Node markNode);
-
-    /**
-     * Creates a textual AST display, one line per node, with nesting.
-     * 
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     */
-    String printTreeToString(Node node, int maxDepth);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugContext.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +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.  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.debug;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.*;
-
-/**
- * Access to the suite of facilities available when debugging is enabled.
- */
-public interface DebugContext {
-
-    /**
-     * Access to the Truffle execution context being debugged.
-     */
-    ExecutionContext getContext();
-
-    /**
-     * Access to the appropriate implementation of AST node instrumentation.
-     */
-    NodeInstrumenter getNodeInstrumenter();
-
-    /**
-     * Access to the management of breakpoints, notifications, etc.
-     */
-    DebugManager getDebugManager();
-
-    /**
-     * Gets a printer for Truffle ASTs helpful for debugging guest language implementations.
-     */
-    ASTPrinter getASTPrinter();
-
-    /**
-     * Converts a value in the guest language to a display string.
-     */
-    String displayValue(Object value);
-
-    /**
-     * Converts a slot identifier in the guest language to a display string.
-     */
-    String displayIdentifier(FrameSlot slot);
-
-    /**
-     * Invokes appropriate debugging action when Truffle execution halts.
-     */
-    void executionHalted(Node node, MaterializedFrame frame);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugManager.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +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.  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.debug;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.*;
-import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
-
-/**
- * Language-agnostic access to AST-based debugging support.
- * <p>
- * <strong>Disclaimer:</strong> this interface is under development and will change.
- */
-public interface DebugManager {
-
-    /**
-     * Informs the {@link DebugManager} that the Guest Language runtime is starting to load a
-     * source. Care should be taken to ensure that under any circumstance there is always a
-     * following call to {@link #notifyFinishedLoading(Source)} with the same argument.
-     */
-    void notifyStartLoading(Source source);
-
-    /**
-     * Informs the {@link DebugManager} that the Guest Language runtime has finished loading a
-     * source. Care should be taken to ensure that under any circumstance there is always a prior
-     * call to {@link #notifyStartLoading(Source)} with the same argument.
-     */
-    void notifyFinishedLoading(Source source);
-
-    /**
-     * Return a reference to the (canonical) instrumentation site associated with a particular
-     * source code location; this site will have effect on any Truffle/AST implementation
-     * corresponding to the source location, even if the AST is copied multiple times.
-     */
-    ProbeChain getProbeChain(SourceSection sourceSection);
-
-    /**
-     * Informs the {@link DebugManager} that Truffle execution has halted; execution will resume
-     * when this method returns.
-     * 
-     * @param astNode a guest language AST node that represents the current execution site, assumed
-     *            not to be any kind of {@link InstrumentationNode},
-     * @param frame execution frame at the site where execution suspended
-     */
-    void haltedAt(Node astNode, MaterializedFrame frame);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DefaultDebugManager.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +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.  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.debug;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
-import com.oracle.truffle.api.source.*;
-
-/**
- * A minimal, language-agnostic implementation that tracks loaded sources, and keeps maps describing
- * what locations in the source have instrumentation available. This implementation will do nothing
- * unless there are calls to it during AST construction, notably {@link #notifyStartLoading(Source)}
- * and {@link #notifyFinishedLoading(Source)} <em>and</em> there are at least some AST nodes being
- * instrumented.
- */
-public class DefaultDebugManager implements DebugManager {
-
-    private final Set<Source> loadedSources = new HashSet<>();
-
-    private Source beingLoaded = null;
-
-    /**
-     * Map: SourceSection ==&gt; probe chain associated with that source section in an AST.
-     */
-    private final Map<SourceSection, ProbeChain> srcToProbeChain = new HashMap<>();
-
-    /**
-     * Map: Source lines ==&gt; probe chains associated with source sections starting on the line.
-     */
-    private final Map<SourceLineLocation, Set<ProbeChain>> lineToProbeChains = new HashMap<>();
-
-    private final ExecutionContext context;
-
-    public DefaultDebugManager(ExecutionContext context) {
-        this.context = context;
-    }
-
-    /**
-     * Gets the {@linkplain ProbeChain probe} associated with a particular {@link SourceSection
-     * source location}, creating a new one if needed. There should only be one probe associated
-     * with each {@linkplain SourceSection source location}.
-     */
-    public ProbeChain getProbeChain(SourceSection sourceSection) {
-        assert sourceSection != null;
-        assert sourceSection.getSource().equals(beingLoaded);
-
-        ProbeChain probeChain = srcToProbeChain.get(sourceSection);
-
-        if (probeChain != null) {
-            return probeChain;
-        }
-        probeChain = new ProbeChain(context, sourceSection, null);
-
-        // Register new ProbeChain by unique SourceSection
-        srcToProbeChain.put(sourceSection, probeChain);
-
-        // Register new ProbeChain by source line, there may be more than one
-        // Create line location for map key
-        final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
-
-        Set<ProbeChain> probeChains = lineToProbeChains.get(lineLocation);
-        if (probeChains == null) {
-            probeChains = new HashSet<>();
-            lineToProbeChains.put(lineLocation, probeChains);
-        }
-        probeChains.add(probeChain);
-
-        return probeChain;
-    }
-
-    public void notifyStartLoading(Source source) {
-        assert beingLoaded == null;
-        beingLoaded = source;
-    }
-
-    public void notifyFinishedLoading(Source source) {
-        assert source == beingLoaded;
-        loadedSources.add(source);
-        beingLoaded = null;
-    }
-
-    public void haltedAt(Node astNode, MaterializedFrame frame) {
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +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.  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.debug;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Controls breaking out of an execution context, such as a shell or eval.
- */
-public final class KillException extends ControlFlowException {
-
-    private static final long serialVersionUID = 3163641880088766957L;
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +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.  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.debug;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Controls breaking out of all executions and ending Truffle execution.
- */
-public final class QuitException extends ControlFlowException {
-
-    private static final long serialVersionUID = -4301115629772778413L;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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.  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.frame;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+
+public interface FrameInstance {
+
+    public static enum FrameAccess {
+        NONE,
+        READ_ONLY,
+        READ_WRITE,
+        MATERIALIZE
+    }
+
+    Frame getFrame(FrameAccess access, boolean slowPath);
+
+    boolean isVirtualFrame();
+
+    DirectCallNode getCallNode();
+
+    CallTarget getCallTarget();
+
+    CallTarget getTargetCallTarget();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractExecutionContext.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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.  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.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.source.*;
+
+public abstract class AbstractExecutionContext implements ExecutionContext {
+
+    private final SourceManager sourceManager = new SourceManager();
+    private final Instrumentation instrumentation;
+    private Visualizer visualizer = new DefaultVisualizer();
+    protected ASTProber astProber = null;
+
+    protected AbstractExecutionContext() {
+        this.instrumentation = InstrumentationFactory.create(this);
+    }
+
+    public final SourceManager getSourceManager() {
+        return sourceManager;
+    }
+
+    public final Instrumentation instrumentation() {
+        return instrumentation;
+    }
+
+    public Visualizer visualizer() {
+        return visualizer;
+    }
+
+    public void addNodeProber(ASTNodeProber nodeProber) {
+        if (astProber == null) {
+            throw new IllegalStateException("No ASTProber installed in context");
+        }
+        astProber.addNodeProber(nodeProber);
+    }
+
+    /**
+     * Assign guest language-specific visualization support for tools. This must be assigned outside
+     * the implementation context to avoid build circularities.
+     */
+    public void setVisualizer(Visualizer visualizer) {
+        this.visualizer = visualizer;
+    }
+
+    /**
+     * Assigns a guest language-specific manager for using {@link ASTNodeProber}s added by tools to
+     * instrument ASTs with {@link Probe}s at specified nodes. This must be assigned outside the
+     * implementation context to avoid build circularities. It must also be set before any
+     * instrumentation probe implementations are assigned.
+     */
+    public void setASTProber(ASTProber astProber) {
+        this.astProber = astProber;
+    }
+
+    /**
+     * Gets a guest language-specific {@link ASTNodeProber} that will apply all that have been
+     * added; {@code null} if no instrumentation in AST.
+     */
+    public ASTNodeProber getCombinedNodeProber() {
+        return astProber == null ? null : astProber.getCombinedNodeProber();
+    }
+
+    public abstract void setInstrumentEventListener(InstrumentEventListener listener);
+
+    public abstract InstrumentEventListener getInstrumentEventListener();
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +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.impl;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class DefaultCallNode extends CallNode {
-
-    public DefaultCallNode(CallTarget target) {
-        super(target);
-    }
-
-    @Override
-    public Object call(Object[] arguments) {
-        return getCurrentCallTarget().call(arguments);
-    }
-
-    @Override
-    public void inline() {
-    }
-
-    @Override
-    public CallTarget getSplitCallTarget() {
-        return null;
-    }
-
-    @Override
-    public boolean split() {
-        return false;
-    }
-
-    @Override
-    public boolean isSplittable() {
-        return false;
-    }
-
-    @Override
-    public boolean isInlined() {
-        return false;
-    }
-
-    @Override
-    public boolean isInlinable() {
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return (getParent() != null ? getParent().toString() : super.toString()) + " call " + getCurrentCallTarget().toString();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Wed Apr 23 15:48:38 2014 +0200
@@ -32,14 +32,27 @@
  * This is an implementation-specific class. Do not use or instantiate it. Instead, use
  * {@link TruffleRuntime#createCallTarget(RootNode)} to create a {@link RootCallTarget}.
  */
-public class DefaultCallTarget extends RootCallTarget {
+public class DefaultCallTarget implements RootCallTarget {
+
+    private final RootNode rootNode;
 
-    protected DefaultCallTarget(RootNode function) {
-        super(function);
+    public DefaultCallTarget(RootNode function) {
+        this.rootNode = function;
+        this.rootNode.adoptChildren();
+        this.rootNode.setCallTarget(this);
     }
 
     @Override
-    public Object call(Object[] args) {
+    public String toString() {
+        return rootNode.toString();
+    }
+
+    public final RootNode getRootNode() {
+        return rootNode;
+    }
+
+    @Override
+    public Object call(Object... args) {
         VirtualFrame frame = new DefaultVirtualFrame(getRootNode().getFrameDescriptor(), args);
         return getRootNode().execute(frame);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is runtime specific API. Do not use in a guest language.
+ */
+public final class DefaultDirectCallNode extends DirectCallNode {
+
+    private boolean inliningForced;
+
+    public DefaultDirectCallNode(CallTarget target) {
+        super(target);
+    }
+
+    @Override
+    public Object call(VirtualFrame frame, Object[] arguments) {
+        return getCurrentCallTarget().call(arguments);
+    }
+
+    @Override
+    public void forceInlining() {
+        inliningForced = true;
+    }
+
+    @Override
+    public boolean isInliningForced() {
+        return inliningForced;
+    }
+
+    @Override
+    public CallTarget getSplitCallTarget() {
+        return null;
+    }
+
+    @Override
+    public boolean split() {
+        return false;
+    }
+
+    @Override
+    public boolean isInlined() {
+        return false;
+    }
+
+    @Override
+    public boolean isSplittable() {
+        return false;
+    }
+
+    @Override
+    public boolean isInlinable() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return (getParent() != null ? getParent().toString() : super.toString()) + " call " + getCurrentCallTarget().toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * 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.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is runtime specific API. Do not use in a guest language.
+ */
+final class DefaultIndirectCallNode extends IndirectCallNode {
+
+    @Override
+    public Object call(VirtualFrame frame, CallTarget target, Object[] arguments) {
+        return target.call(arguments);
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Wed Apr 23 15:48:38 2014 +0200
@@ -53,8 +53,12 @@
         return new DefaultCallTarget(rootNode);
     }
 
-    public CallNode createCallNode(CallTarget target) {
-        return new DefaultCallNode(target);
+    public DirectCallNode createDirectCallNode(CallTarget target) {
+        return new DefaultDirectCallNode(target);
+    }
+
+    public IndirectCallNode createIndirectCallNode() {
+        return new DefaultIndirectCallNode();
     }
 
     @Override
@@ -81,4 +85,14 @@
     public Assumption createAssumption(String name) {
         return new DefaultAssumption(name);
     }
+
+    public Iterable<FrameInstance> getStackTrace() {
+        // TODO(lstadler) implement this using ThreadLocal
+        return null;
+    }
+
+    public FrameInstance getCurrentFrame() {
+        // TODO(lstadler) implement this using ThreadLocal
+        return null;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Implementation of a policy for <em>instrumenting</em> inserting a {@link Probe} at a Truffle AST
+ * node.
+ * <p>
+ * Note that this interface is guest language agnostic, but current extensions are
+ * language-specific. This will be revisited.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development. Really!
+ */
+public interface ASTNodeProber {
+
+    /**
+     * Optionally applies <em>instrumentation</em> at a Truffle AST node, depending on guest
+     * language characteristics and use-case policy.
+     * <ul>
+     * <li>if no instrumentation is to be applied, returns the AST node unmodified;</li>
+     * <li>if an AST node is to be instrumented, then returns a newly created {@link Wrapper} that
+     * <em>decorates</em> the AST node and notifies an associated {@link Probe} of all
+     * {@link ExecutionEvents} at the wrapped AST node.</li>
+     * <li>if the argument is itself a {@link Wrapper}, i.e. if the AST node at this site has
+     * already been wrapped, then the wrapper is returned (with the possible addition of a
+     * {@linkplain PhylumTag tag}).</li>
+     * </ul>
+     *
+     * @param astNode an AST node to which instrumentation might be applied
+     * @param tag an optional category directing how the node, if instrumented, should be perceived
+     *            by tool users
+     * @param args additional arguments for instrumentation specific to a particular guest language
+     * @return if no instrumentation should be applied or if the node is a {@link Wrapper} then the
+     *         unmodified node; otherwise a newly created {@link Wrapper} (whose child
+     *         {@code astNode}) with an associated {@link Probe} .
+     */
+
+    Node probeAs(Node astNode, PhylumTag tag, Object... args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.  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.instrument;
+
+import java.io.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Language-agnostic access to AST-based debugging support.
+ * <p>
+ * <strong>WARNING:</strong> this interface is under development and will change substantially.
+ */
+public interface ASTPrinter {
+
+    /**
+     * Prints a textual AST display, one line per node, with nesting.
+     * 
+     * @param p
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     * @param markNode a node to mark with a textual arrow prefix, if present.
+     */
+    void printTree(PrintWriter p, Node node, int maxDepth, Node markNode);
+
+    /**
+     * Creates a textual AST display, one line per node, with nesting.
+     * 
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     * @param markNode a node to mark with a textual arrow prefix, if present.
+     */
+    String printTreeToString(Node node, int maxDepth, Node markNode);
+
+    /**
+     * Creates a textual AST display, one line per node, with nesting.
+     * 
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     */
+    String printTreeToString(Node node, int maxDepth);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.  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.instrument;
+
+/**
+ * Implementation of a policy for <em>instrumenting</em> Truffle ASTs with {@link Probe}s at
+ * particular nodes by inserting node {@link Wrapper}s.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface ASTProber {
+
+    // TODO (mlvdv) This is a provisional interface, more of a marker really
+    // TODO (mlvdv) AST probing should eventually be done with visitors.
+
+    void addNodeProber(ASTNodeProber nodeProber);
+
+    /**
+     * Gets a prober that applies all added {@link ASTNodeProber}s.
+     */
+    ASTNodeProber getCombinedNodeProber();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,179 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Normal events during program execution at Truffle AST nodes that are reported via a {@link Probe}
+ * associated with the node, and made available to the probe's attached {@link Instrument}s.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface ExecutionEvents {
+
+    /**
+     * Notifies that an AST node's execute method has just been entered. Callers should assure that
+     * a matching call to {@link #leave(Node, VirtualFrame, Object)} always follows.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame being passed to the execute method
+     */
+    void enter(Node astNode, VirtualFrame frame);
+
+    /**
+     * Notifies that an AST Node's void-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     */
+    void leave(Node astNode, VirtualFrame frame);
+
+    /**
+     * Notifies that an AST Node's boolean-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, boolean result);
+
+    /**
+     * Notifies that an AST Node's byte-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, byte result);
+
+    /**
+     * Notifies that an AST Node's short-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, short result);
+
+    /**
+     * Notifies that an AST Node's integer-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, int result);
+
+    /**
+     * Notifies that an AST Node's long-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, long result);
+
+    /**
+     * Notifies that an AST Node's float-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, float result);
+
+    /**
+     * Notifies that an AST Node's double-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, double result);
+
+    /**
+     * Notifies that an AST Node's char-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, char result);
+
+    /**
+     * Notifies that an AST Node's object-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, Object result);
+
+    /**
+     * Notifies that an AST Node's execute method is about to leave under exceptional conditions,
+     * returning no value.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param e the exception associated with the unusual return
+     */
+    void leaveExceptional(Node astNode, VirtualFrame frame, Exception e);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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.  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.instrument;
+
+/**
+ * A receiver of Truffle AST {@link ExecutionEvents}, propagated from a {@link Probe} to which the
+ * instrument is attached.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface Instrument extends ExecutionEvents {
+
+    /**
+     * @return the {@link Probe} to which this instrument is attached.
+     */
+    Probe getProbe();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentEventListener.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A client of the instrumentation framework that requests event notifications from the language
+ * engine.
+ */
+public interface InstrumentEventListener {
+
+    /**
+     * The guest language runtime is starting to load a source. Care should be taken to ensure that
+     * under any circumstance there is always a following call to {@link #loadEnding(Source)} with
+     * the same argument.
+     */
+    void loadStarting(Source source);
+
+    /**
+     * The guest language runtime has finished loading a source. Care should be taken to ensure that
+     * under any circumstance there is always a prior call to {@link #loadStarting(Source)} with the
+     * same argument.
+     */
+    void loadEnding(Source source);
+
+    /**
+     * A guest language call is about to be executed.
+     */
+    void callEntering(Node astNode, String name);
+
+    /**
+     * A guest language call has just completed.
+     */
+    void callReturned(Node astNode, String name);
+
+    /**
+     * An opportunity for instrumentation to interact with Truffle AST execution halted at some
+     * node.
+     */
+    void haltedAt(Node astNode, MaterializedFrame frame);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentation.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.  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.instrument;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.source.*;
+
+public interface Instrumentation {
+
+    /**
+     * Adds a new specification for how to instrument ASTs.
+     */
+    void addNodeProber(ASTNodeProber nodeProber);
+
+    /**
+     * Registers a tool interested in being notified about the insertion of a newly created
+     * {@link Probe} into a Truffle AST.
+     */
+    void addProbeListener(ProbeListener listener);
+
+    /**
+     * Return the (possibly newly created) {@link Probe} uniquely associated with a particular
+     * source code location. A newly created probe carries no tags.
+     *
+     * @param eventListener an optional listener for certain instrumentation-related events
+     * @return a probe uniquely associated with an extent of guest language source code.
+     */
+    Probe getProbe(SourceSection sourceSection, InstrumentEventListener eventListener);
+
+    /**
+     * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty
+     * collection if no probes found.
+     */
+    Collection<Probe> findProbesTaggedAs(PhylumTag tag);
+
+    /**
+     * Returns all existing probes with first character on a specified line; empty collection if no
+     * probes found.
+     */
+    Collection<Probe> findProbesByLine(SourceLineLocation lineLocation);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.impl.*;
+
+public class InstrumentationFactory {
+
+    public static Instrumentation create(ExecutionContext context) {
+        return new InstrumentationImpl(context);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Controls breaking out of an execution context, such as a shell or eval.
+ */
+public final class KillException extends ControlFlowException {
+
+    private static final long serialVersionUID = 3163641880088766957L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTag.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,70 @@
+/*
+ * 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.  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.instrument;
+
+/**
+ * Program element "tags" that define user-visible behavior for debugging and other simple tools.
+ * These categories (<em>phyla</em>) should correspond to program structures that are meaningful to
+ * a guest language programmer.
+ * <p>
+ * An untagged Truffle node should be understood as an artifact of the guest language implementation
+ * and should not be visible to the user of a guest language programming tool. Nodes may also have
+ * more than one tag, for example a variable assignment that is also a statement. Finally, the
+ * assignment of tags to nodes could depending on the use-case of whatever tool is using them.
+ * <p>
+ * This is a somewhat language-agnostic set of phyla, suitable for conventional imperative
+ * languages, and is being developed incrementally.
+ * <p>
+ * The need for alternative sets of tags is likely to arise, perhaps for other families of languages
+ * (for example for mostly expression-oriented languages) or even for specific languages.
+ * <p>
+ * These are listed alphabetically so that listing from some collection classes will come out in
+ * that order.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public enum PhylumTag {
+
+    /**
+     * Marker for a variable assignment.
+     */
+    ASSIGNMENT,
+
+    /**
+     * Marker for a call site.
+     */
+    CALL,
+
+    /**
+     * Marker for a location where a guest language exception is about to be thrown.
+     */
+    THROW,
+
+    /**
+     * Marker for a location where ordinary "stepping" should halt.
+     */
+    STATEMENT;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTagged.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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.  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.instrument;
+
+import java.util.*;
+
+/**
+ * Information about a guest language program element that can be marked as belonging to 0 or more
+ * {@linkplain PhylumTag tags}.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface PhylumTagged {
+
+    /**
+     * Is this node tagged as belonging to a particular category of language constructs?
+     */
+    boolean isTaggedAs(PhylumTag tag);
+
+    /**
+     * In which categories has this node been tagged (<em>empty set</em> if none).
+     */
+    Set<PhylumTag> getPhylumTags();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,148 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A collector of {@link ExecutionEvents} at a specific site (node) in a Truffle AST (generated by a
+ * {@link Wrapper} inserted into the AST) for the purpose of <em>instrumentation</em>. For probes
+ * associated with programmer-facing tools, there should be no more than one probe associated with a
+ * particular piece of source code syntax (i.e. a {@link SourceSection}).
+ * <p>
+ * Any {@linkplain PhylumTag tags} associated with a particular piece of source code syntax are
+ * managed by the probe.
+ * <p>
+ * When ASTs are copied, it is presumed that the probe for a site is shared by all AST nodes
+ * representing that site.
+ * <p>
+ * A probe holds zero or more {@link Instrument}s, which can be added and removed dynamically.
+ * Events reported to a probe are propagated to every attached instrument; the order is undefined.
+ * <p>
+ * Probe methods must be amenable to Truffle/Graal inlining on the assumption that the collection of
+ * attached instruments seldom changes. The assumption is invalidated when instruments are added or
+ * removed, but some instruments may change their internal state in such a way that the assumption
+ * should also be invalidated.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface Probe extends PhylumTagged {
+
+    /**
+     * The source location with which this probe is (presumably uniquely) associated.
+     */
+    SourceSection getSourceLocation();
+
+    /**
+     * Mark this probe as being associated with an AST node in some category useful for debugging
+     * and other tools.
+     */
+    void tagAs(PhylumTag tag);
+
+    /**
+     * Adds an instrument to this probe.
+     */
+    void addInstrument(Instrument newInstrument);
+
+    /**
+     * Removes an instrument from this probe.
+     */
+    void removeInstrument(Instrument oldInstrument);
+
+    /**
+     * Change <em>stepping mode</em>, which is used in association with nodes tagged as
+     * {@linkplain PhylumTag#STATEMENT statements}.
+     */
+    void setStepping(boolean stepping);
+
+    /**
+     * Value of <em>stepping mode</em>, which is used in association with nodes tagged as
+     * {@linkplain PhylumTag#STATEMENT statements}.
+     */
+    boolean isStepping();
+
+    /**
+     * @see ExecutionEvents#enter(Node, VirtualFrame)
+     */
+    void notifyEnter(Node astNode, VirtualFrame frame);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, boolean)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, boolean result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, byte)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, byte result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, short)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, short result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, int)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, int result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, long)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, long result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, char)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, char result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, float)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, float result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, double)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, double result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, Object)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, Object result);
+
+    /**
+     * @see ExecutionEvents#leaveExceptional(Node, VirtualFrame, Exception)
+     */
+    void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Client for receiving events relate to {@link Probe} management. Does not report AST copying.
+ */
+public interface ProbeListener {
+
+    /**
+     * Notifies that a newly created (untagged) {@link Probe} has been inserted into a Truffle AST.
+     * There will be no notification when an existing {@link Probe} is shared by an AST copy.
+     */
+    void newProbeInserted(SourceSection location, Probe probe);
+
+    /**
+     * Notifies that a (fully constructed) {@link Probe} has been tagged. A subsequent marking with
+     * the same tag is idempotent and generates no notification.
+     */
+    void probeTaggedAs(Probe probe, PhylumTag tag);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Controls breaking out of all executions and ending Truffle execution.
+ */
+public final class QuitException extends ControlFlowException {
+
+    private static final long serialVersionUID = -4301115629772778413L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Visualization services for guest language and Truffle information.
+ */
+public interface Visualizer {
+
+    /**
+     * Gets a printer for Truffle ASTs, possibly specialized to be helpful for a specific guest
+     * language implementation.
+     */
+    ASTPrinter getASTPrinter();
+
+    /**
+     * Converts a value in the guest language to a display string.
+     */
+    String displayValue(Object value);
+
+    /**
+     * Converts a slot identifier in the guest language to a display string.
+     */
+    String displayIdentifier(FrameSlot slot);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Wrapper.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,57 @@
+/*
+ * 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.  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.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A node that can be inserted into a Truffle AST in order to attach <em>instrumentation</em> at a
+ * particular node.
+ * <p>
+ * A wrapper <em>decorates</em> an AST node (its <em>child</em>) by acting as a transparent
+ * <em>proxy</em> for the child with respect to Truffle execution semantics.
+ * <p>
+ * A wrapper is also expected to notify its associated {@link Probe} when certain
+ * {@link ExecutionEvents} occur at the wrapper during program execution.
+ * <p>
+ * The wrapper's {@link Probe} is shared by every copy of the wrapper made when the AST is copied.
+ * <p>
+ * Wrappers methods must be amenable to Truffle/Graal inlining.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface Wrapper extends PhylumTagged {
+
+    /**
+     * Gets the AST node being instrumented, which should never be an instance of {@link Wrapper}.
+     */
+    Node getChild();
+
+    /**
+     * Gets the {@link Probe} to which events occurring at this wrapper's child are propagated.
+     */
+    Probe getProbe();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,168 @@
+/*
+ * 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.  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.instrument.impl;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind;
+
+/**
+ * A language-agnostic for printing out various pieces of a Truffle AST.
+ */
+public class DefaultASTPrinter implements ASTPrinter {
+
+    public DefaultASTPrinter() {
+    }
+
+    public void printTree(PrintWriter p, Node node, int maxDepth, Node markNode) {
+        printTree(p, node, maxDepth, markNode, 1);
+        p.println();
+        p.flush();
+    }
+
+    public String printTreeToString(Node node, int maxDepth, Node markNode) {
+        StringWriter out = new StringWriter();
+        printTree(new PrintWriter(out), node, maxDepth, markNode);
+        return out.toString();
+    }
+
+    public String printTreeToString(Node node, int maxDepth) {
+        return printTreeToString(node, maxDepth, null);
+    }
+
+    private static void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) {
+        if (node == null) {
+            p.print("null");
+            return;
+        }
+
+        p.print(nodeName(node));
+
+        String sep = "";
+        p.print("(");
+
+        final SourceSection src = node.getSourceSection();
+        if (src != null) {
+            if (!(src instanceof NullSourceSection)) {
+                p.print(src.getSource().getName() + ":" + src.getStartLine());
+            }
+        }
+        if (node instanceof PhylumTagged) {
+            final PhylumTagged taggedNode = (PhylumTagged) node;
+            String prefix = "";
+            for (PhylumTag tag : taggedNode.getPhylumTags()) {
+                p.print(prefix);
+                prefix = ",";
+                p.print(tag.toString());
+            }
+
+        }
+
+        ArrayList<NodeField> childFields = new ArrayList<>();
+
+        for (NodeField field : NodeClass.get(node.getClass()).getFields()) {
+            if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
+                childFields.add(field);
+            } else if (field.getKind() == NodeFieldKind.DATA) {
+                // p.print(sep);
+                // sep = ", ";
+                //
+                // final String fieldName = field.getName();
+                // switch (fieldName) {
+                //
+                // }
+                // p.print(fieldName);
+                // p.print(" = ");
+                // p.print(field.loadValue(node));
+            }
+        }
+        p.print(")");
+
+        if (level <= maxDepth) {
+
+            if (childFields.size() != 0) {
+                p.print(" {");
+                for (NodeField field : childFields) {
+
+                    Object value = field.loadValue(node);
+                    if (value == null) {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                        p.print(" = null ");
+                    } else if (field.getKind() == NodeFieldKind.CHILD) {
+                        final Node valueNode = (Node) value;
+                        printNewLine(p, level, valueNode == markNode);
+                        p.print(field.getName());
+                        p.print(" = ");
+                        printTree(p, valueNode, maxDepth, markNode, level + 1);
+                    } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                        Node[] children = (Node[]) value;
+                        p.print(" = [");
+                        sep = "";
+                        for (Node child : children) {
+                            p.print(sep);
+                            sep = ", ";
+                            printTree(p, child, maxDepth, markNode, level + 1);
+                        }
+                        p.print("]");
+                    } else {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                    }
+                }
+                printNewLine(p, level - 1);
+                p.print("}");
+            }
+        }
+    }
+
+    private static void printNewLine(PrintWriter p, int level, boolean mark) {
+        p.println();
+        for (int i = 0; i < level; i++) {
+            if (mark && i == 0) {
+                p.print(" -->");
+            } else {
+                p.print("    ");
+            }
+        }
+    }
+
+    private static void printNewLine(PrintWriter p, int level) {
+        printNewLine(p, level, false);
+    }
+
+    private static String nodeName(Node node) {
+        return node.getClass().getSimpleName();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultInstrument.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,84 @@
+/*
+ * 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.  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.instrument.impl;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An {@link Instrument} that implements all {@link ExecutionEvents} notifications with empty
+ * methods.
+ */
+public class DefaultInstrument extends InstrumentationNodeImpl implements Instrument {
+
+    protected DefaultInstrument() {
+    }
+
+    public void enter(Node astNode, VirtualFrame frame) {
+    }
+
+    public void leave(Node astNode, VirtualFrame frame) {
+    }
+
+    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) {
+    }
+
+    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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.  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.instrument.impl;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+
+public class DefaultVisualizer implements Visualizer {
+
+    private final ASTPrinter astPrinter;
+
+    public DefaultVisualizer() {
+        this.astPrinter = new DefaultASTPrinter();
+    }
+
+    public ASTPrinter getASTPrinter() {
+        return astPrinter;
+    }
+
+    public String displayValue(Object value) {
+        return value.toString();
+    }
+
+    public String displayIdentifier(FrameSlot slot) {
+        return slot.getIdentifier().toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,145 @@
+/*
+ * 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.  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.instrument.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * @author mlvdv
+ *
+ */
+public final class InstrumentationImpl implements Instrumentation {
+
+    private final ExecutionContext context;
+
+    // TODO (mlvdv) maps should really use weak references.
+
+    /**
+     * Map: SourceSection ==> probe associated with that source section in an AST.
+     */
+    private final Map<SourceSection, Probe> srcToProbe = new HashMap<>();
+
+    /**
+     * Map: Source line ==> probes associated with source sections starting on the line.
+     */
+    private final Map<SourceLineLocation, Collection<Probe>> lineToProbes = new HashMap<>();
+
+    private final List<ProbeListener> probeListeners = new ArrayList<>();
+
+    public InstrumentationImpl(ExecutionContext context) {
+        this.context = context;
+    }
+
+    public void addNodeProber(ASTNodeProber nodeProber) {
+        context.addNodeProber(nodeProber);
+    }
+
+    public void addProbeListener(ProbeListener listener) {
+        assert listener != null;
+        probeListeners.add(listener);
+    }
+
+    /**
+     * Return the (possibly newly created) {@link Probe} uniquely associated with a particular
+     * source code location. A newly created probe carries no tags.
+     *
+     * @param eventListener an optional listener for certain instrumentation-related events
+     * @return a probe uniquely associated with an extent of guest language source code.
+     */
+    public Probe getProbe(SourceSection sourceSection, InstrumentEventListener eventListener) {
+        assert sourceSection != null;
+
+        Probe probe = srcToProbe.get(sourceSection);
+
+        if (probe != null) {
+            return probe;
+        }
+        probe = InstrumentationNodeImpl.createProbe(this, sourceSection, eventListener);
+
+        // Register new probe by unique SourceSection
+        srcToProbe.put(sourceSection, probe);
+
+        // Register new probe by source line, there may be more than one
+        // Create line location for map key
+        final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
+
+        Collection<Probe> probes = lineToProbes.get(lineLocation);
+        if (probes == null) {
+            probes = new ArrayList<>(2);
+            lineToProbes.put(lineLocation, probes);
+        }
+        probes.add(probe);
+
+        for (ProbeListener listener : probeListeners) {
+            listener.newProbeInserted(sourceSection, probe);
+        }
+
+        return probe;
+    }
+
+    /**
+     * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty
+     * collection if no probes found.
+     */
+    public Collection<Probe> findProbesTaggedAs(PhylumTag tag) {
+        if (tag == null) {
+            return new ArrayList<>(srcToProbe.values());
+        }
+        final List<Probe> probes = new ArrayList<>();
+        for (Probe probe : srcToProbe.values()) {
+            if (probe.isTaggedAs(tag)) {
+                probes.add(probe);
+            }
+        }
+        return probes;
+    }
+
+    /**
+     * Returns all existing probes with first character on a specified line; empty collection if no
+     * probes found.
+     */
+    public Collection<Probe> findProbesByLine(SourceLineLocation lineLocation) {
+        final Collection<Probe> probes = lineToProbes.get(lineLocation);
+        if (probes == null) {
+            return Collections.emptyList();
+        }
+        return new ArrayList<>(probes);
+    }
+
+    /**
+     * Receives (from the {@link Probe} implementation) and distributes notification that a
+     * {@link Probe} has acquired a new {@linkplain PhylumTag tag}.
+     */
+    void newTagAdded(Probe probe, PhylumTag tag) {
+        for (ProbeListener listener : probeListeners) {
+            listener.probeTaggedAs(probe, tag);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNodeImpl.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,448 @@
+/*
+ * 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.  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.instrument.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments.
+ * <p>
+ * Coordinates propagation of Truffle AST {@link ExecutionEvents}.
+ */
+public abstract class InstrumentationNodeImpl extends Node implements ExecutionEvents {
+
+    // TODO (mlvdv) This is a pretty awkward design.
+
+    /**
+     * Creates a new {@link Probe}, presumed to be unique to a particular {@linkplain SourceSection}
+     * extent of guest language source code.
+     *
+     * @param eventListener an optional listener for certain instrumentation-related events.
+     * @return a new probe
+     */
+    static Probe createProbe(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) {
+        return new ProbeImpl(instrumentation, sourceSection, eventListener);
+    }
+
+    /**
+     * Next in chain.
+     */
+    @Child protected InstrumentationNodeImpl next;
+
+    protected InstrumentationNodeImpl() {
+    }
+
+    /**
+     * @return the instance of {@link Probe} to which this instrument is attached.
+     */
+    public Probe getProbe() {
+        final InstrumentationNodeImpl parent = (InstrumentationNodeImpl) getParent();
+        return parent == null ? null : parent.getProbe();
+    }
+
+    /**
+     * Add a probe to the end of this probe chain.
+     */
+    void internalAddInstrument(InstrumentationNodeImpl newInstrument) {
+        if (next == null) {
+            this.next = insert(newInstrument);
+        } else {
+            next.internalAddInstrument(newInstrument);
+        }
+    }
+
+    void internalRemoveInstrument(InstrumentationNodeImpl oldInstrument) {
+        if (next == null) {
+            throw new RuntimeException("Couldn't find probe to remove: " + oldInstrument);
+        } else if (next == oldInstrument) {
+            if (oldInstrument.next == null) {
+                this.next = null;
+            } else {
+                this.next = insert(oldInstrument.next);
+                oldInstrument.next = null;
+            }
+        } else {
+            next.internalRemoveInstrument(oldInstrument);
+        }
+    }
+
+    /**
+     * Reports to the instance of {@link Probe} holding this instrument that some essential state
+     * has changed that requires deoptimization.
+     */
+    @CompilerDirectives.SlowPath
+    protected void notifyProbeChanged(InstrumentationNodeImpl instrument) {
+        final ProbeImpl probe = (ProbeImpl) getProbe();
+        probe.notifyProbeChanged(instrument);
+    }
+
+    private void internalEnter(Node astNode, VirtualFrame frame) {
+        enter(astNode, frame);
+        if (next != null) {
+            next.internalEnter(astNode, frame);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame) {
+        leave(astNode, frame);
+        if (next != null) {
+            next.internalLeave(astNode, frame);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, boolean result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, byte result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, short result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, int result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, long result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, char result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, float result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, double result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, Object result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+        leaveExceptional(astNode, frame, null);
+        if (next != null) {
+            next.internalLeaveExceptional(astNode, frame, e);
+        }
+    }
+
+    /**
+     * Holder of a chain of {@linkplain InstrumentationNodeImpl instruments}: manages the
+     * {@link Assumption} that none of the instruments have changed since last checked.
+     * <p>
+     * An instance is intended to be shared by every clone of the AST node with which it is
+     * originally attached, so it holds no parent pointer.
+     * <p>
+     * May be categorized by one or more {@linkplain PhylumTag tags}, signifying information useful
+     * for instrumentation about its AST location(s).
+     */
+    private static final class ProbeImpl extends InstrumentationNodeImpl implements Probe {
+
+        final InstrumentationImpl instrumentation;
+
+        final InstrumentEventListener eventListener;
+
+        @CompilerDirectives.CompilationFinal private Assumption probeUnchanged;
+
+        /**
+         * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line
+         * will cause a halt.
+         */
+        @CompilerDirectives.CompilationFinal private boolean stepping;
+
+        /**
+         * Source information about the AST node to which this instrumentation is attached.
+         */
+        private final SourceSection probedSourceSection;
+
+        private final Set<PhylumTag> tags = EnumSet.noneOf(PhylumTag.class);
+
+        private ProbeImpl(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) {
+            this.instrumentation = instrumentation;
+            this.probedSourceSection = sourceSection;
+            this.eventListener = eventListener == null ? NullInstrumentEventListener.INSTANCE : eventListener;
+            this.probeUnchanged = Truffle.getRuntime().createAssumption();
+            this.next = null;
+        }
+
+        @Override
+        public Probe getProbe() {
+            return this;
+        }
+
+        @Override
+        protected void notifyProbeChanged(InstrumentationNodeImpl instrument) {
+            probeUnchanged.invalidate();
+            probeUnchanged = Truffle.getRuntime().createAssumption();
+        }
+
+        public SourceSection getSourceLocation() {
+            return probedSourceSection;
+        }
+
+        public void tagAs(PhylumTag tag) {
+            assert tag != null;
+            if (!tags.contains(tag)) {
+                tags.add(tag);
+                instrumentation.newTagAdded(this, tag);
+            }
+        }
+
+        public boolean isTaggedAs(PhylumTag tag) {
+            assert tag != null;
+            return tags.contains(tag);
+        }
+
+        public Set<PhylumTag> getPhylumTags() {
+            return tags;
+        }
+
+        public void setStepping(boolean stepping) {
+            if (this.stepping != stepping) {
+                this.stepping = stepping;
+                probeUnchanged.invalidate();
+                probeUnchanged = Truffle.getRuntime().createAssumption();
+            }
+        }
+
+        public boolean isStepping() {
+            return stepping;
+        }
+
+        @CompilerDirectives.SlowPath
+        public void addInstrument(Instrument instrument) {
+            probeUnchanged.invalidate();
+            final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument;
+            super.internalAddInstrument(instrumentImpl);
+            probeUnchanged = Truffle.getRuntime().createAssumption();
+        }
+
+        @CompilerDirectives.SlowPath
+        public void removeInstrument(Instrument instrument) {
+            probeUnchanged.invalidate();
+            final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument;
+            super.internalRemoveInstrument(instrumentImpl);
+            probeUnchanged = Truffle.getRuntime().createAssumption();
+        }
+
+        public void notifyEnter(Node astNode, VirtualFrame frame) {
+            if (stepping || next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                if (stepping) {
+                    eventListener.haltedAt(astNode, frame.materialize());
+                }
+                if (next != null) {
+                    next.internalEnter(astNode, frame);
+                }
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, byte result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, short result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, int result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, long result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, char result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, float result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, double result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, Object result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeaveExceptional(astNode, frame, e);
+            }
+        }
+
+        public void enter(Node astNode, VirtualFrame frame) {
+        }
+
+        public void leave(Node astNode, VirtualFrame frame) {
+        }
+
+        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) {
+        }
+
+        public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/NullInstrumentEventListener.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,57 @@
+/*
+ * 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.  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.instrument.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Minimal, mostly no-op implementation of instrumentation services.
+ */
+public final class NullInstrumentEventListener implements InstrumentEventListener {
+
+    public static final InstrumentEventListener INSTANCE = new NullInstrumentEventListener();
+
+    private NullInstrumentEventListener() {
+    }
+
+    public void callEntering(Node astNode, String name) {
+    }
+
+    public void callReturned(Node astNode, String name) {
+    }
+
+    public void haltedAt(Node astNode, MaterializedFrame frame) {
+    }
+
+    public void loadStarting(Source source) {
+    }
+
+    public void loadEnding(Source source) {
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2012, 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.  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.*;
-
-/**
- * Represents a call to a {@link CallTarget} in the Truffle AST. Addtionally to calling the
- * {@link CallTarget} this {@link Node} enables the runtime system to implement further
- * optimizations. Optimizations that can possibly applied to a {@link CallNode} are inlining and
- * splitting. Inlining inlines this call site into the call graph of the parent {@link CallTarget}.
- * Splitting duplicates the {@link CallTarget} using {@link RootNode#split()} to collect call site
- * sensitive profiling information.
- *
- * Please note: This class is not intended to be subclassed by guest language implementations.
- *
- * @see TruffleRuntime#createCallNode(CallTarget)
- * @see #inline()
- * @see #split()
- */
-public abstract class CallNode extends Node {
-
-    protected final CallTarget callTarget;
-
-    protected CallNode(CallTarget callTarget) {
-        this.callTarget = callTarget;
-    }
-
-    /**
-     * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}.
-     *
-     * @param arguments the arguments that should be passed to the callee
-     * @return the return result of the call
-     */
-    public abstract Object call(Object[] arguments);
-
-    /**
-     * Returns the originally supplied {@link CallTarget} when this call node was created. Please
-     * note that the returned {@link CallTarget} is not necessarily the {@link CallTarget} that is
-     * called. For that use {@link #getCurrentCallTarget()} instead.
-     *
-     * @return the {@link CallTarget} provided.
-     */
-    public CallTarget getCallTarget() {
-        return callTarget;
-    }
-
-    /**
-     * Returns <code>true</code> if the underlying runtime system supports inlining for the
-     * {@link CallTarget} in this {@link CallNode}.
-     *
-     * @return true if inlining is supported.
-     */
-    public abstract boolean isInlinable();
-
-    /**
-     * Returns <code>true</code> if the {@link CallTarget} in this {@link CallNode} is inlined. A
-     * {@link CallNode} can either be inlined manually by invoking {@link #inline()} or by the
-     * runtime system which may at any point decide to inline.
-     *
-     * @return true if this method was inlined else false.
-     */
-    public abstract boolean isInlined();
-
-    /**
-     * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the
-     * runtime system does not support inlining or it is already inlined this method has no effect.
-     */
-    public abstract void inline();
-
-    /**
-     * Returns <code>true</code> if this {@link CallNode} can be split. A {@link CallNode} can only
-     * be split if the runtime system supports splitting and if the {@link RootNode} contained the
-     * {@link CallTarget} returns <code>true</code> for {@link RootNode#isSplittable()}.
-     *
-     * @return <code>true</code> if the target can be split
-     */
-    public abstract boolean isSplittable();
-
-    /**
-     * Enforces the runtime system to split the {@link CallTarget}. If the {@link CallNode} is not
-     * splittable this methods has no effect.
-     */
-    public abstract boolean split();
-
-    /**
-     * Returns <code>true</code> if the target of the {@link CallNode} was split.
-     *
-     * @return if the target was split
-     */
-    public final boolean isSplit() {
-        return getSplitCallTarget() != null;
-    }
-
-    /**
-     * Returns the splitted {@link CallTarget} if this method is split.
-     *
-     * @return the split {@link CallTarget}
-     */
-    public abstract CallTarget getSplitCallTarget();
-
-    /**
-     * Returns the used call target when {@link #call(Object[])} is invoked. If the
-     * {@link CallTarget} was split this method returns the {@link CallTarget} returned by
-     * {@link #getSplitCallTarget()}.
-     *
-     * @return the used {@link CallTarget} when node is called
-     */
-    public CallTarget getCurrentCallTarget() {
-        CallTarget split = getSplitCallTarget();
-        if (split != null) {
-            return split;
-        } else {
-            return getCallTarget();
-        }
-    }
-
-    /**
-     * Returns the {@link RootNode} associated with {@link CallTarget} returned by
-     * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a
-     * {@link RootNode} this method returns <code>null</code>.
-     *
-     * @see #getCurrentCallTarget()
-     * @return the root node of the used call target
-     */
-    public final RootNode getCurrentRootNode() {
-        CallTarget target = getCurrentCallTarget();
-        if (target instanceof RootCallTarget) {
-            return ((RootCallTarget) target).getRootNode();
-        }
-        return null;
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, 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.  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.*;
+
+/**
+ * Represents a direct call to a {@link CallTarget}. Direct calls are calls for which the
+ * {@link CallTarget} remains the same for each consecutive call. This part of the Truffle API
+ * enables the runtime system to perform additional optimizations on direct calls.
+ *
+ * Optimizations that can be applied to a {@link DirectCallNode} are inlining and splitting.
+ * Inlining inlines this call site into the call graph of the parent {@link CallTarget}. Splitting
+ * duplicates the {@link CallTarget} using {@link RootNode#split()} to collect call site sensitive
+ * profiling information.
+ *
+ * Please note: This class is not intended to be subclassed by guest language implementations.
+ *
+ * @see IndirectCallNode for calls with a non-constant target
+ * @see TruffleRuntime#createDirectCallNode(CallTarget)
+ * @see #forceInlining()
+ * @see #split()
+ */
+public abstract class DirectCallNode extends Node {
+
+    protected final CallTarget callTarget;
+
+    protected DirectCallNode(CallTarget callTarget) {
+        this.callTarget = callTarget;
+    }
+
+    /**
+     * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}.
+     *
+     * @param arguments the arguments that should be passed to the callee
+     * @return the return result of the call
+     */
+    public abstract Object call(VirtualFrame frame, Object[] arguments);
+
+    /**
+     * Returns the originally supplied {@link CallTarget} when this call node was created. Please
+     * note that the returned {@link CallTarget} is not necessarily the {@link CallTarget} that is
+     * called. For that use {@link #getCurrentCallTarget()} instead.
+     *
+     * @return the {@link CallTarget} provided.
+     */
+    public CallTarget getCallTarget() {
+        return callTarget;
+    }
+
+    /**
+     * Returns <code>true</code> if the underlying runtime system supports inlining for the
+     * {@link CallTarget} in this {@link DirectCallNode}.
+     *
+     * @return true if inlining is supported.
+     */
+    public abstract boolean isInlinable();
+
+    /**
+     * Returns <code>true</code> if the {@link CallTarget} is forced to be inlined. A
+     * {@link DirectCallNode} can either be inlined manually by invoking {@link #forceInlining()} or
+     * by the runtime system which may at any point decide to inline.
+     *
+     * @return true if this method was inlined else false.
+     */
+    public abstract boolean isInliningForced();
+
+    /**
+     * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the
+     * runtime system does not support inlining or it is already inlined this method has no effect.
+     * The runtime system may decide to not inline calls which were forced to inline.
+     */
+    public abstract void forceInlining();
+
+    /**
+     * Returns true if the runtime system has decided to inline this call-site. If the
+     * {@link DirectCallNode} was forced to inline then this does not necessarily mean that the
+     * {@link DirectCallNode} is really going to be inlined. This depends on whether or not the
+     * runtime system supports inlining. The runtime system may also decide to not inline calls
+     * which were forced to inline.
+     */
+    public abstract boolean isInlined();
+
+    /**
+     * Returns <code>true</code> if this {@link DirectCallNode} can be split. A
+     * {@link DirectCallNode} can only be split if the runtime system supports splitting and if the
+     * {@link RootNode} contained the {@link CallTarget} returns <code>true</code> for
+     * {@link RootNode#isSplittable()}.
+     *
+     * @return <code>true</code> if the target can be split
+     */
+    public abstract boolean isSplittable();
+
+    /**
+     * Enforces the runtime system to split the {@link CallTarget}. If the {@link DirectCallNode} is
+     * not splittable this methods has no effect.
+     */
+    public abstract boolean split();
+
+    /**
+     * Returns <code>true</code> if the target of the {@link DirectCallNode} was split.
+     *
+     * @return if the target was split
+     */
+    public final boolean isSplit() {
+        return getSplitCallTarget() != null;
+    }
+
+    /**
+     * Returns the split {@link CallTarget} if this method is split.
+     *
+     * @return the split {@link CallTarget}
+     */
+    public abstract CallTarget getSplitCallTarget();
+
+    /**
+     * Returns the used call target when {@link #call(VirtualFrame, Object[])} is invoked. If the
+     * {@link CallTarget} was split this method returns the {@link CallTarget} returned by
+     * {@link #getSplitCallTarget()}.
+     *
+     * @return the used {@link CallTarget} when node is called
+     */
+    public CallTarget getCurrentCallTarget() {
+        CallTarget split = getSplitCallTarget();
+        if (split != null) {
+            return split;
+        } else {
+            return getCallTarget();
+        }
+    }
+
+    /**
+     * Returns the {@link RootNode} associated with {@link CallTarget} returned by
+     * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a
+     * {@link RootNode} this method returns <code>null</code>.
+     *
+     * @see #getCurrentCallTarget()
+     * @return the root node of the used call target
+     */
+    public final RootNode getCurrentRootNode() {
+        CallTarget target = getCurrentCallTarget();
+        if (target instanceof RootCallTarget) {
+            return ((RootCallTarget) target).getRootNode();
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 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.  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.*;
+
+/**
+ * Represents an indirect call to a {@link CallTarget}. Indirect calls are calls for which the
+ * {@link CallTarget} may change dynamically for each consecutive call. This part of the Truffle API
+ * enables the runtime system to perform additional optimizations on indirect calls.
+ *
+ * Please note: This class is not intended to be sub classed by guest language implementations.
+ *
+ * @see DirectCallNode for faster calls with a constantly known {@link CallTarget}.
+ */
+public abstract class IndirectCallNode extends Node {
+
+    /**
+     * Performs an indirect call to the given {@link CallTarget} target with the provided arguments.
+     *
+     * @param frame the caller frame
+     * @param target the {@link CallTarget} to call
+     * @param arguments the arguments to provide
+     * @return the return value of the call
+     */
+    public abstract Object call(VirtualFrame frame, CallTarget target, Object[] arguments);
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Apr 23 15:48:38 2014 +0200
@@ -636,8 +636,8 @@
                 nodeCount++;
             }
 
-            if (visitInlinedCallNodes && node instanceof CallNode) {
-                CallNode call = (CallNode) node;
+            if (visitInlinedCallNodes && node instanceof DirectCallNode) {
+                DirectCallNode call = (DirectCallNode) node;
                 if (call.isInlined()) {
                     Node target = ((RootCallTarget) call.getCurrentCallTarget()).getRootNode();
                     if (target != null) {
@@ -763,7 +763,7 @@
     /**
      * Prints a human readable form of a {@link Node} AST to the given {@link PrintStream}. This
      * print method does not check for cycles in the node structure.
-     * 
+     *
      * @param out the stream to print to.
      * @param node the root node to write
      */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -58,7 +58,7 @@
      * Creates a split {@link RootNode} based on the current {@link RootNode}. This method should
      * return an AST that was never executed and must not be shared with other {@link RootNode} or
      * {@link CallTarget} instances. This method is intended to be overridden by a subclass.
-     * 
+     *
      * @return the split {@link RootNode}
      */
     public RootNode split() {
@@ -67,10 +67,10 @@
 
     /**
      * Returns <code>true</code> if this {@link RootNode} can be split. A {@link RootNode} can be
-     * split inside of a {@link CallTarget} that is invoked using a {@link CallNode}. If this method
-     * returns <code>true</code> a proper implementation of {@link #split()} must also be provided.
-     * This method is intended to be overridden by a subclass.
-     * 
+     * split inside of a {@link CallTarget} that is invoked using a {@link DirectCallNode}. If this
+     * method returns <code>true</code> a proper implementation of {@link #split()} must also be
+     * provided. This method is intended to be overridden by a subclass.
+     *
      * @return <code>true</code> if splittable else <code>false</code>.
      */
     public boolean isSplittable() {
@@ -89,7 +89,7 @@
 
     /**
      * Executes this function using the specified frame and returns the result value.
-     * 
+     *
      * @param frame the frame of the currently executing guest language method
      * @return the value of the execution
      */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/DefaultNodeInstrumenter.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +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.  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.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A no-op node instrumenter; always returns the node unproxied and unmodified.
- */
-public class DefaultNodeInstrumenter implements NodeInstrumenter {
-
-    public Node instrumentAs(Node node, NodePhylum phylum, Object... args) {
-        return node;
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /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.  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.instrument;
-
-/**
- * Marker interface for all Truffle <strong>instrumentation nodes</strong>: nodes that are do not
- * appear in Truffle ASTs as part of a language's execution semantics.
- * <p>
- * In documentation related to instrumentation nodes, these are distinguished by referring to all
- * other nodes (i.e. ones that <em>do</em> implement language semantics) as <em>AST nodes</em>.
- */
-public interface InstrumentationNode {
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeEvents.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +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.  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.instrument;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Marker interface for all Truffle <strong>instrumentation nodes</strong>: nodes that are do not
- * appear in Truffle ASTs as part of a language's execution semantics.
- * <p>
- * In documentation related to instrumentation nodes, these are distinguished by referring to all
- * other nodes (i.e. ones that <em>do</em> implement language semantics) as <em>AST nodes</em>.
- */
-public interface InstrumentationProbeEvents {
-
-    /**
-     * Notifies a probe that receiver that an AST node's execute method has just been entered.
-     * Callers should assure that a matching call to {@link #leave(Node, VirtualFrame, Object)}
-     * always follows.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame being passed to the execute method
-     */
-    void enter(Node astNode, VirtualFrame frame);
-
-    /**
-     * Notifies a probe that an AST Node's void-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     */
-    void leave(Node astNode, VirtualFrame frame);
-
-    /**
-     * Notifies a probe that an AST Node's boolean-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, boolean result);
-
-    /**
-     * Notifies a probe that an AST Node's byte-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, byte result);
-
-    /**
-     * Notifies a probe that an AST Node's short-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, short result);
-
-    /**
-     * Notifies a probe that an AST Node's integer-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, int result);
-
-    /**
-     * Notifies a probe that an AST Node's long-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, long result);
-
-    /**
-     * Notifies a probe that an AST Node's float-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, float result);
-
-    /**
-     * Notifies a probe that an AST Node's double-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, double result);
-
-    /**
-     * Notifies a probe that an AST Node's char-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, char result);
-
-    /**
-     * Notifies a probe that an AST Node's object-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, Object result);
-
-    /**
-     * Notifies a probe that an AST Node's execute method is about to leave under exceptional
-     * conditions, returning no value.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param e the exception associated with the unusual return
-     */
-    void leaveExceptional(Node astNode, VirtualFrame frame, Exception e);
-
-    /**
-     * Notifies a probe that an AST node is about to be replaced with another.
-     * 
-     * @param oldAstNode the AST node currently in the tree
-     * @param newAstNode the AST replacement node
-     * @param reason explanation for the replacement
-     */
-    void replace(Node oldAstNode, Node newAstNode, String reason);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,500 +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.  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.instrument;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A <strong>probe</strong>: a Truffle instrumentation node that holds code to perform some action
- * when notified (via a {@linkplain InstrumentationProxyNode proxy node} in the AST) of a
- * {@linkplain InstrumentationProbeEvents probe event} taking place at the AST node.
- * <p>
- * Probes are only active when attached to a {@linkplain ProbeChain "probe chain"} that is referred
- * to by one or more {@linkplain InstrumentationProxyNode proxy nodes} in an AST.
- */
-public abstract class InstrumentationProbeNode extends Node implements InstrumentationNode, InstrumentationProbeEvents {
-
-    /**
-     * Next in chain.
-     */
-    @Child protected InstrumentationProbeNode next;
-
-    protected InstrumentationProbeNode() {
-    }
-
-    protected int countProbes() {
-        return next == null ? 0 : next.countProbes() + 1;
-    }
-
-    protected boolean isStepping() {
-        final InstrumentationProbeNode parent = (InstrumentationProbeNode) getParent();
-        return parent.isStepping();
-    }
-
-    /**
-     * Add a probe to the end of this probe chain.
-     */
-    protected void internalAppendProbe(InstrumentationProbeNode newProbeNode) {
-        if (next == null) {
-            this.next = insert(newProbeNode);
-        } else {
-            next.internalAppendProbe(newProbeNode);
-        }
-    }
-
-    protected void internalRemoveProbe(InstrumentationProbeNode oldProbeNode) {
-        if (next == null) {
-            throw new RuntimeException("Couldn't find probe to remove: " + oldProbeNode);
-        } else if (next == oldProbeNode) {
-            if (oldProbeNode.next == null) {
-                this.next = null;
-            } else {
-                this.next = insert(oldProbeNode.next);
-                oldProbeNode.next = null;
-            }
-        } else {
-            next.internalRemoveProbe(oldProbeNode);
-        }
-    }
-
-    /**
-     * Passes up the chain notification that a probe has changed its execution state in a way that
-     * invalidates fast path code. Assumes that there is an instance of {@link ProbeChain} at the
-     * head of the chain.
-     */
-    @CompilerDirectives.SlowPath
-    protected void notifyProbeChanged(InstrumentationProbeNode probeNode) {
-        final InstrumentationProbeNode parent = (InstrumentationProbeNode) getParent();
-        parent.notifyProbeChanged(probeNode);
-    }
-
-    // TODO (mlvdv) making the internal*() methods public is a workaround for a bug/limitation in
-    // the Truffle compiler; they are intended to be private.
-
-    public void internalEnter(Node astNode, VirtualFrame frame) {
-        enter(astNode, frame);
-        if (next != null) {
-            next.internalEnter(astNode, frame);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame) {
-        leave(astNode, frame);
-        if (next != null) {
-            next.internalLeave(astNode, frame);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, boolean result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, byte result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, short result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, int result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, long result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, char result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, float result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, double result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, Object result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        leaveExceptional(astNode, frame, null);
-        if (next != null) {
-            next.internalLeaveExceptional(astNode, frame, e);
-        }
-    }
-
-    public void internalReplace(Node oldAstNode, Node newAstNode, String reason) {
-        replace(oldAstNode, newAstNode, reason);
-        if (next != null) {
-            next.internalReplace(oldAstNode, newAstNode, reason);
-        }
-    }
-
-    /**
-     * A probe implementation that implements all of {@link InstrumentationProbeEvents} with empty
-     * methods; concrete subclasses can override only the methods for which something is to be done.
-     */
-    public static class DefaultProbeNode extends InstrumentationProbeNode {
-
-        private final ExecutionContext executionContext;
-
-        protected DefaultProbeNode(ExecutionContext context) {
-            this.executionContext = context;
-        }
-
-        public ExecutionContext getContext() {
-            return executionContext;
-        }
-
-        public void enter(Node astNode, VirtualFrame frame) {
-        }
-
-        public void leave(Node astNode, VirtualFrame frame) {
-        }
-
-        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) {
-        }
-
-        public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        }
-
-        public void replace(Node oldAstNode, Node newAstNode, String reason) {
-        }
-
-    }
-
-    /**
-     * Holder of a chain of {@linkplain InstrumentationProbeNode probes}: manages the
-     * {@link Assumption} that the chain has not changed since checked checked.
-     * <p>
-     * May be categorized by one or more {@linkplain NodePhylum node phyla}, signifying information
-     * useful for instrumentation about its AST location(s).
-     */
-    public static final class ProbeChain extends DefaultProbeNode implements PhylumMarked {
-
-        @CompilerDirectives.CompilationFinal private Assumption probeUnchanged;
-
-        /**
-         * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line
-         * will cause a halt.
-         */
-        @CompilerDirectives.CompilationFinal private boolean stepping;
-
-        /**
-         * Source information about the node to which this probe chain is attached; it isn't
-         * otherwise available. A probe chain is shared by every copy made during runtime, so there
-         * is no parent pointer.
-         */
-        private final SourceSection probedSourceSection;
-
-        private final Set<NodePhylum> phyla = EnumSet.noneOf(NodePhylum.class);
-
-        private final String description; // for debugging
-
-        /**
-         * Creates a new, empty chain of {@linkplain InstrumentationProbeNode probes}, to which
-         * probes can be added/removed, and all of which will be notified of
-         * {@linkplain InstrumentationProbeEvents events} when the chain is notified.
-         */
-        public ProbeChain(ExecutionContext context, SourceSection sourceSection, String description) {
-            super(context);
-            this.probeUnchanged = Truffle.getRuntime().createAssumption();
-            this.probedSourceSection = sourceSection;
-            this.description = description;
-            this.next = null;
-        }
-
-        public int probeCount() {
-            return countProbes();
-        }
-
-        public String getDescription() {
-            return description;
-        }
-
-        public SourceSection getProbedSourceSection() {
-            return probedSourceSection;
-        }
-
-        /**
-         * Mark this probe chain as being associated with an AST node in some category useful for
-         * debugging and other tools.
-         */
-        public void markAs(NodePhylum phylum) {
-            assert phylum != null;
-            phyla.add(phylum);
-        }
-
-        /**
-         * Is this probe chain as being associated with an AST node in some category useful for
-         * debugging and other tools.
-         */
-        public boolean isMarkedAs(NodePhylum phylum) {
-            assert phylum != null;
-            return phyla.contains(phylum);
-        }
-
-        /**
-         * In which categories is the AST (with which this probe is associated) marked?
-         */
-        public Set<NodePhylum> getPhylumMarks() {
-            return phyla;
-        }
-
-        /**
-         * Change <em>stepping mode</em> for statements.
-         */
-        public void setStepping(boolean stepping) {
-            if (this.stepping != stepping) {
-                this.stepping = stepping;
-                probeUnchanged.invalidate();
-                probeUnchanged = Truffle.getRuntime().createAssumption();
-            }
-        }
-
-        @Override
-        protected boolean isStepping() {
-            return stepping;
-        }
-
-        @Override
-        protected int countProbes() {
-            // The head of the chain does not itself hold a probe
-            return next == null ? 0 : next.countProbes();
-        }
-
-        @Override
-        protected void notifyProbeChanged(InstrumentationProbeNode probeNode) {
-            probeUnchanged.invalidate();
-            probeUnchanged = Truffle.getRuntime().createAssumption();
-        }
-
-        @CompilerDirectives.SlowPath
-        public void appendProbe(InstrumentationProbeNode newProbeNode) {
-            probeUnchanged.invalidate();
-            super.internalAppendProbe(newProbeNode);
-            probeUnchanged = Truffle.getRuntime().createAssumption();
-        }
-
-        @CompilerDirectives.SlowPath
-        public void removeProbe(InstrumentationProbeNode oldProbeNode) {
-            probeUnchanged.invalidate();
-            super.internalRemoveProbe(oldProbeNode);
-            probeUnchanged = Truffle.getRuntime().createAssumption();
-        }
-
-        public void notifyEnter(Node astNode, VirtualFrame frame) {
-            if (stepping || next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                if (stepping) {
-                    getContext().getDebugContext().getDebugManager().haltedAt(astNode, frame.materialize());
-                }
-                if (next != null) {
-                    next.internalEnter(astNode, frame);
-                }
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, byte result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, short result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, int result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, long result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, char result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, float result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, double result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, Object result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeaveExceptional(astNode, frame, e);
-            }
-        }
-
-        public void notifyReplace(Node oldAstNode, Node newAstNode, String reason) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalReplace(oldAstNode, newAstNode, reason);
-            }
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProxyNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +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.  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.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
-
-/**
- * Interface implemented by language-specific Truffle <strong>proxy nodes</strong>: nodes that do
- * not participate in the language's execution semantics, but which are inserted into an AST so that
- * tools (e.g. tracers, analyzers, debuggers) can be notified of AST interpretation events and
- * possibly intervene.
- * <p>
- * Language-specific proxy nodes call notification methods on an attached {@linkplain ProbeChain
- * probe chain} which passes along {@linkplain InstrumentationProbeEvents events} to any
- * {@linkplain InstrumentationProbeNode probes} that might have been attached.
- */
-public interface InstrumentationProxyNode extends InstrumentationNode, PhylumMarked {
-
-    /**
-     * Gets the non-instrumentation node being proxied.
-     */
-    Node getChild();
-
-    /**
-     * Gets the chain of probes to which events at this node are delegated. Note that a chain of
-     * probes may be used by more than one proxy.
-     */
-    ProbeChain getProbeChain();
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodeInstrumenter.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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.  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.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Implements the instrumentation of a Truffle AST node and returning either:
- * <ul>
- * <li>the node itself, or</li>
- * <li>a newly created {@linkplain InstrumentationProxyNode proxy node} that holds the instrumented
- * node as its {@linkplain com.oracle.truffle.api.nodes.Node.Child child}.</li>
- * </ul>
- */
-public interface NodeInstrumenter {
-
-    /**
-     * Wraps a {@linkplain InstrumentationProxyNode proxy node} around a node (if not already
-     * wrapped), marks the location with a {@linkplain NodePhylum phylum (category)} for user
-     * interaction, and passes along any characteristics of the particular node that are important
-     * for instrumentation (e.g. the function/method name at a call).
-     */
-    Node instrumentAs(Node node, NodePhylum phylum, Object... args);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodePhylum.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +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.  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.instrument;
-
-/**
- * Categories of {@link InstrumentationProxyNode}s to be used for defining user-visible debugging
- * and other simple tool behavior. These categories (<em>phyla</em>) should correspond to program
- * structures that are meaningful to a programmer using the guest language. A Truffle node without a
- * proxy carrying some phylum should be treated as an artifact of the guest language implementation
- * and should never be visible to the user of a guest language programming tool.
- * <p>
- * Note that phyla are not intended to represent a partition of user-visible node categories, as the
- * relative categorization of nodes can change with the particular programming tasks at hand.
- * <p>
- * This is a somewhat language-agnostic set of phyla, suitable for conventional imperative
- * languages, and is being developed incrementally.
- * <p>
- * The need for alternative sets of phyla is likely to arise, perhaps for other families of
- * languages (for example for mostly expression-oriented languages) or even for specific languages.
- * <p>
- * These are listed alphabetically so that listing from some collection classes will come out in
- * that order.
- * <p>
- * <strong>Disclaimer:</strong> this interface is under development and will change.
- */
-public enum NodePhylum {
-
-    /**
-     * Marker for a proxy at a variable assignment.
-     */
-    ASSIGNMENT,
-
-    /**
-     * Marker for a proxy at a call site.
-     */
-    CALL,
-
-    /**
-     * Marker for a proxy at which ordinary "stepping" should halt.
-     */
-    STATEMENT;
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/PhylumMarked.java	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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.  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.instrument;
-
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A kind of {@link Node} that can be marked as belong to 0 or more {@linkplain NodePhylum phyla}.
- */
-public interface PhylumMarked {
-
-    /**
-     * Is this proxy tagged as belonging to a particular category of language constructs?
-     */
-    boolean isMarkedAs(NodePhylum phylum);
-
-    /**
-     * In which categories is this node tagged (<em>empty set</em> if none).
-     */
-    Set<NodePhylum> getPhylumMarks();
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceLineLocation.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceLineLocation.java	Wed Apr 23 15:48:38 2014 +0200
@@ -31,7 +31,7 @@
  * instance of {@link Source}, suitable for hash table keys with equality defined in terms of
  * content.
  */
-public class SourceLineLocation implements Comparable {
+public class SourceLineLocation implements Comparable<Object> {
 
     private final Source source;
     private final int line;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Wed Apr 23 15:48:38 2014 +0200
@@ -60,7 +60,7 @@
         // TODO run verifications that other annotations are not processed out of scope of the
         // operation or typelattice.
         try {
-            for (AnnotationProcessor generator : getGenerators()) {
+            for (AnnotationProcessor<?> generator : getGenerators()) {
                 AbstractParser<?> parser = generator.getParser();
                 if (parser.getAnnotationType() != null) {
                     for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) {
@@ -86,7 +86,7 @@
         }
     }
 
-    private static void processElement(RoundEnvironment env, AnnotationProcessor generator, Element e, boolean callback) {
+    private static void processElement(RoundEnvironment env, AnnotationProcessor<?> generator, Element e, boolean callback) {
         try {
             generator.process(env, e, callback);
         } catch (Throwable e1) {
@@ -94,16 +94,15 @@
         }
     }
 
-    private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) {
+    private static void handleThrowable(AnnotationProcessor<?> generator, Throwable t, Element e) {
         String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e;
         generator.getContext().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + Utils.printException(t), e);
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public void callback(TypeElement template) {
-        for (AnnotationProcessor generator : generators) {
-            Class annotationType = generator.getParser().getAnnotationType();
+        for (AnnotationProcessor<?> generator : generators) {
+            Class<? extends Annotation> annotationType = generator.getParser().getAnnotationType();
             if (annotationType != null) {
                 Annotation annotation = template.getAnnotation(annotationType);
                 if (annotation != null) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Wed Apr 23 15:48:38 2014 +0200
@@ -112,7 +112,7 @@
         return nodeCost;
     }
 
-    private DeclaredType getRequired(ProcessorContext context, Class clazz) {
+    private DeclaredType getRequired(ProcessorContext context, Class<?> clazz) {
         TypeMirror type = context.getType(clazz);
         if (type == null) {
             errors.add(String.format("Could not find required type: %s", clazz.getSimpleName()));
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -32,7 +32,7 @@
         return method.invoke(o);
     }
 
-    protected static Object method(Object o, String methodName, Class[] paramTypes, Object... values) throws Exception {
+    protected static Object method(Object o, String methodName, Class<?>[] paramTypes, Object... values) throws Exception {
         Method method = o.getClass().getMethod(methodName, paramTypes);
         method.setAccessible(true);
         return method.invoke(o, values);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java	Wed Apr 23 15:48:38 2014 +0200
@@ -44,8 +44,8 @@
         return type.getEnclosedElements();
     }
 
-    private static final Class[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
-    private static final Class[] getCharContentSignature = new Class[]{boolean.class};
+    private static final Class<?>[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
+    private static final Class<?>[] getCharContentSignature = new Class[]{boolean.class};
 
     @Override
     public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -44,7 +44,7 @@
     protected void createChildren(M m) {
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public CodeElement<?> process(CodeElement parent, M m) {
         model = m;
         element = (CodeElement<? super Element>) create(model);
@@ -57,6 +57,7 @@
         return element;
     }
 
+    @SuppressWarnings("rawtypes")
     public CodeElement getElement() {
         return element;
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java	Wed Apr 23 15:48:38 2014 +0200
@@ -36,6 +36,7 @@
         return new CodeCompilationUnit();
     }
 
+    @SuppressWarnings("rawtypes")
     @Override
     public CodeCompilationUnit process(CodeElement parent, M m) {
         return (CodeCompilationUnit) super.process(parent, m);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.output	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,90 @@
+Initial stack trace:
+Frame: root doIt, a=0, hello=null
+Frame: root main, i=0
+After 123 assignment:
+Frame: root doIt, a=0, hello=123
+Frame: root main, i=0
+After hello assignment:
+Frame: root doIt, a=0, hello=world
+Frame: root main, i=0
+Initial stack trace:
+Frame: root doIt, a=1, hello=null
+Frame: root main, i=1
+After 123 assignment:
+Frame: root doIt, a=1, hello=123
+Frame: root main, i=1
+After hello assignment:
+Frame: root doIt, a=1, hello=world
+Frame: root main, i=1
+Initial stack trace:
+Frame: root doIt, a=2, hello=null
+Frame: root main, i=2
+After 123 assignment:
+Frame: root doIt, a=2, hello=123
+Frame: root main, i=2
+After hello assignment:
+Frame: root doIt, a=2, hello=world
+Frame: root main, i=2
+Initial stack trace:
+Frame: root doIt, a=3, hello=null
+Frame: root main, i=3
+After 123 assignment:
+Frame: root doIt, a=3, hello=123
+Frame: root main, i=3
+After hello assignment:
+Frame: root doIt, a=3, hello=world
+Frame: root main, i=3
+Initial stack trace:
+Frame: root doIt, a=4, hello=null
+Frame: root main, i=4
+After 123 assignment:
+Frame: root doIt, a=4, hello=123
+Frame: root main, i=4
+After hello assignment:
+Frame: root doIt, a=4, hello=world
+Frame: root main, i=4
+Initial stack trace:
+Frame: root doIt, a=5, hello=null
+Frame: root main, i=5
+After 123 assignment:
+Frame: root doIt, a=5, hello=123
+Frame: root main, i=5
+After hello assignment:
+Frame: root doIt, a=5, hello=world
+Frame: root main, i=5
+Initial stack trace:
+Frame: root doIt, a=6, hello=null
+Frame: root main, i=6
+After 123 assignment:
+Frame: root doIt, a=6, hello=123
+Frame: root main, i=6
+After hello assignment:
+Frame: root doIt, a=6, hello=world
+Frame: root main, i=6
+Initial stack trace:
+Frame: root doIt, a=7, hello=null
+Frame: root main, i=7
+After 123 assignment:
+Frame: root doIt, a=7, hello=123
+Frame: root main, i=7
+After hello assignment:
+Frame: root doIt, a=7, hello=world
+Frame: root main, i=7
+Initial stack trace:
+Frame: root doIt, a=8, hello=null
+Frame: root main, i=8
+After 123 assignment:
+Frame: root doIt, a=8, hello=123
+Frame: root main, i=8
+After hello assignment:
+Frame: root doIt, a=8, hello=world
+Frame: root main, i=8
+Initial stack trace:
+Frame: root doIt, a=9, hello=null
+Frame: root main, i=9
+After 123 assignment:
+Frame: root doIt, a=9, hello=123
+Frame: root main, i=9
+After hello assignment:
+Frame: root doIt, a=9, hello=world
+Frame: root main, i=9
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,22 @@
+function doIt(a) {
+  println("Initial stack trace:");
+  println(stacktrace());
+  
+  hello = 123;
+  println("After 123 assignment:");
+  println(stacktrace());
+  
+  helloEqualsWorld();
+  println("After hello assignment:");
+  println(stacktrace());
+  
+//  readln();
+}
+
+function main() {
+  i = 0;
+  while (i < 10) {
+    doIt(i);
+    i = i + 1;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 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.builtins;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This builtin sets the variable named "hello" in the caller frame to the string "world".
+ */
+@NodeInfo(shortName = "helloEqualsWorld")
+public abstract class SLHelloEqualsWorldBuiltin extends SLBuiltinNode {
+
+    @Specialization
+    public String change() {
+        FrameInstance frameInstance = Truffle.getRuntime().getStackTrace().iterator().next();
+        Frame frame = frameInstance.getFrame(FrameAccess.READ_WRITE, false);
+        FrameSlot slot = frame.getFrameDescriptor().findOrAddFrameSlot("hello");
+        frame.setObject(slot, "world");
+        return "world";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, 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.builtins;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.SlowPath;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Returns a string representation of the current stack. This includes the {@link CallTarget}s and
+ * the contents of the {@link Frame}. Note that this is implemented as a slow path by passing
+ * {@code true} to {@link FrameInstance#getFrame(FrameAccess, boolean)}.
+ */
+@NodeInfo(shortName = "stacktrace")
+public abstract class SLStackTraceBuiltin extends SLBuiltinNode {
+
+    @Specialization
+    public String trace() {
+        return createStackTrace();
+    }
+
+    @SlowPath
+    private static String createStackTrace() {
+        StringBuilder str = new StringBuilder();
+        Iterable<FrameInstance> frames = Truffle.getRuntime().getStackTrace();
+
+        if (frames != null) {
+            for (FrameInstance frame : frames) {
+                dumpFrame(str, frame.getCallTarget(), frame.getFrame(FrameAccess.READ_ONLY, true), frame.isVirtualFrame());
+            }
+        }
+        return str.toString();
+    }
+
+    private static void dumpFrame(StringBuilder str, CallTarget rootNode, Frame frame, boolean isVirtual) {
+        if (str.length() > 0) {
+            str.append("\n");
+        }
+        str.append("Frame: ").append(rootNode).append(isVirtual ? " (virtual)" : "");
+        FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
+        for (FrameSlot s : frameDescriptor.getSlots()) {
+            str.append(", ").append(s.getIdentifier()).append("=").append(frame.getValue(s));
+        }
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -36,11 +36,11 @@
     private final SLFunction cachedFunction;
 
     /**
-     * {@link CallNode} is part of the Truffle API and handles all the steps necessary for method
-     * inlining: if the call is executed frequently and the callee is small, then the call is
+     * {@link DirectCallNode} is part of the Truffle API and handles all the steps necessary for
+     * method inlining: if the call is executed frequently and the callee is small, then the call is
      * inlined, i.e., the call node is replaced with a copy of the callee's AST.
      */
-    @Child private CallNode callCachedTargetNode;
+    @Child private DirectCallNode callCachedTargetNode;
 
     /** Assumption that the {@link #callCachedTargetNode} is still valid. */
     private final Assumption cachedTargetStable;
@@ -53,7 +53,7 @@
 
     protected SLDirectDispatchNode(SLAbstractDispatchNode next, SLFunction cachedFunction) {
         this.cachedFunction = cachedFunction;
-        this.callCachedTargetNode = Truffle.getRuntime().createCallNode(cachedFunction.getCallTarget());
+        this.callCachedTargetNode = Truffle.getRuntime().createDirectCallNode(cachedFunction.getCallTarget());
         this.cachedTargetStable = cachedFunction.getCallTargetStable();
         this.nextNode = next;
     }
@@ -92,7 +92,7 @@
                  * Now we are really ready to perform the call. We use a Truffle CallNode for that,
                  * because it does all the work for method inlining.
                  */
-                return callCachedTargetNode.call(arguments);
+                return callCachedTargetNode.call(frame, arguments);
 
             } catch (InvalidAssumptionException ex) {
                 /*
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java	Wed Apr 23 15:48:38 2014 +0200
@@ -22,7 +22,9 @@
  */
 package com.oracle.truffle.sl.nodes.call;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
 /**
@@ -31,12 +33,20 @@
  */
 final class SLGenericDispatchNode extends SLAbstractDispatchNode {
 
+    /**
+     * {@link IndirectCallNode} is part of the Truffle API and handles all the steps necessary for
+     * calling a megamorphic call-site. The Graal specific version of this node performs additional
+     * optimizations for the fast access of the SimpleLanguage stack trace.
+     */
+    @Child private IndirectCallNode callNode = Truffle.getRuntime().createIndirectCallNode();
+
     @Override
     protected Object executeDispatch(VirtualFrame frame, SLFunction function, Object[] arguments) {
         /*
          * SL has a quite simple call lookup: just ask the function for the current call target, and
          * call it.
          */
-        return function.getCallTarget().call(arguments);
+        return callNode.call(frame, function.getCallTarget(), arguments);
     }
+
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Wed Apr 23 15:22:20 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Wed Apr 23 15:48:38 2014 +0200
@@ -97,6 +97,8 @@
         installBuiltin(SLPrintlnBuiltinFactory.getInstance());
         installBuiltin(SLNanoTimeBuiltinFactory.getInstance());
         installBuiltin(SLDefineFunctionBuiltinFactory.getInstance());
+        installBuiltin(SLStackTraceBuiltinFactory.getInstance());
+        installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance());
     }
 
     private void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory) {
--- a/make/linux/makefiles/buildtree.make	Wed Apr 23 15:22:20 2014 +0200
+++ b/make/linux/makefiles/buildtree.make	Wed Apr 23 15:48:38 2014 +0200
@@ -258,6 +258,10 @@
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
+	echo "$(call gamma-path,altsrc,gpu/ptx/vm) \\"; \
+	echo "$(call gamma-path,commonsrc,gpu/ptx/vm)" \\; \
+	echo "$(call gamma-path,altsrc,gpu/hsail/vm) \\"; \
+	echo "$(call gamma-path,commonsrc,gpu/hsail/vm) \\"; \
 	echo "$(call gamma-path,altsrc,gpu) \\"; \
 	echo "$(call gamma-path,commonsrc,gpu)"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
--- a/make/linux/makefiles/vm.make	Wed Apr 23 15:22:20 2014 +0200
+++ b/make/linux/makefiles/vm.make	Wed Apr 23 15:48:38 2014 +0200
@@ -185,8 +185,10 @@
 
 GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/graal)
 GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/ptx/vm)
+GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/hsail/vm)
 GRAAL_PATHS += $(HS_COMMON_SRC)/share/vm/graal
 GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/ptx/vm
+GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/hsail/vm
 
 # Include dirs per type.
 Src_Dirs/CORE      := $(CORE_PATHS)
--- a/make/solaris/makefiles/mapfile-vers	Wed Apr 23 15:22:20 2014 +0200
+++ b/make/solaris/makefiles/mapfile-vers	Wed Apr 23 15:48:38 2014 +0200
@@ -223,8 +223,6 @@
                 JVM_SetLength;
                 JVM_SetNativeThreadName;
                 JVM_SetPrimitiveArrayElement;
-                # Preserved so that Graal repo can link against a JDK7 libjava.so works
-                JVM_SetProtectionDomain;
                 JVM_SetSockOpt;
                 JVM_SetThreadPriority;
                 JVM_Sleep;
--- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Wed Apr 23 15:22:20 2014 +0200
+++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Wed Apr 23 15:48:38 2014 +0200
@@ -87,7 +87,7 @@
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
 org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
@@ -100,7 +100,6 @@
 org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
 org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
 org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.tasks=ignore
 org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
 org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
 org.eclipse.jdt.core.compiler.problem.unclosedCloseable=ignore
--- a/mx/mx_graal.py	Wed Apr 23 15:22:20 2014 +0200
+++ b/mx/mx_graal.py	Wed Apr 23 15:48:38 2014 +0200
@@ -28,7 +28,7 @@
 
 import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing, StringIO
 from os.path import join, exists, dirname, basename, getmtime
-from argparse import ArgumentParser, REMAINDER
+from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER
 from outputparser import OutputParser, ValuesMatcher
 import mx
 import xml.dom.minidom
@@ -828,7 +828,7 @@
     else:
         return [], args
 
-def _run_tests(args, harness, annotations, testfile):
+def _run_tests(args, harness, annotations, testfile, whitelist):
 
 
     vmArgs, tests = _extract_VM_args(args)
@@ -860,6 +860,9 @@
                 mx.log('warning: no tests matched by substring "' + t)
         projectscp = mx.classpath(projs)
 
+    if whitelist:
+        classes = list(set(classes) & set(whitelist))
+
     if len(classes) != 0:
         f_testfile = open(testfile, 'w')
         for c in classes:
@@ -867,7 +870,7 @@
         f_testfile.close()
         harness(projectscp, vmArgs)
 
-def _unittest(args, annotations, prefixcp=""):
+def _unittest(args, annotations, prefixcp="", whitelist=None):
     mxdir = dirname(__file__)
     name = 'JUnitWrapper'
     javaSource = join(mxdir, name + '.java')
@@ -894,12 +897,20 @@
             vm(prefixArgs + vmArgs + ['-cp', prefixcp + projectscp + os.pathsep + mxdir, name] + [testfile])
 
     try:
-        _run_tests(args, harness, annotations, testfile)
+        _run_tests(args, harness, annotations, testfile, whitelist)
     finally:
         if os.environ.get('MX_TESTFILE') is None:
             os.remove(testfile)
 
 _unittestHelpSuffix = """
+    Unittest options:
+
+      --short-only           run short testcases only
+      --long-only            run long testcases only
+      --baseline-whitelist   run only testcases which are known to
+                             work with the baseline compiler
+
+    To avoid conflicts with VM options '--' can be used as delimiter.
 
     If filters are supplied, only tests whose fully qualified name
     includes a filter as a substring are run.
@@ -928,17 +939,63 @@
 def unittest(args):
     """run the JUnit tests (all testcases){0}"""
 
-    _unittest(args, ['@Test', '@LongTest', '@Parameters'])
+    parser = ArgumentParser(prog='mx unittest',
+          description='run the JUnit tests',
+          add_help=False,
+          formatter_class=RawDescriptionHelpFormatter,
+          epilog=_unittestHelpSuffix,
+        )
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument('--short-only', action='store_true', help='run short testcases only')
+    group.add_argument('--long-only', action='store_true', help='run long testcases only')
+    parser.add_argument('--baseline-whitelist', action='store_true', help='run baseline testcases only')
+
+    ut_args = []
+    delimiter = False
+    # check for delimiter
+    while len(args) > 0:
+        arg = args.pop(0)
+        if arg == '--':
+            delimiter = True
+            break
+        ut_args.append(arg)
+
+    if delimiter:
+        # all arguments before '--' must be recognized
+        parsed_args = parser.parse_args(ut_args)
+    else:
+        # parse all know arguments
+        parsed_args, args = parser.parse_known_args(ut_args)
+
+    whitelist = None
+    if parsed_args.baseline_whitelist:
+        baseline_whitelist_file = 'test/baseline_whitelist.txt'
+        try:
+            with open(join(_graal_home, baseline_whitelist_file)) as fp:
+                whitelist = [l.rstrip() for l in fp.readlines()]
+        except IOError:
+            mx.log('warning: could not read baseline whitelist: ' + baseline_whitelist_file)
+
+    if parsed_args.long_only:
+        annotations = ['@LongTest', '@Parameters']
+    elif parsed_args.short_only:
+        annotations = ['@Test']
+    else:
+        annotations = ['@Test', '@LongTest', '@Parameters']
+
+    _unittest(args, annotations, whitelist=whitelist)
 
 def shortunittest(args):
-    """run the JUnit tests (short testcases only){0}"""
+    """alias for 'unittest --short-only'{0}"""
 
-    _unittest(args, ['@Test'])
+    args.insert(0, '--short-only')
+    unittest(args)
 
 def longunittest(args):
-    """run the JUnit tests (long testcases only){0}"""
+    """alias for 'unittest --long-only'{0}"""
 
-    _unittest(args, ['@LongTest', '@Parameters'])
+    args.insert(0, '--long-only')
+    unittest(args)
 
 def buildvms(args):
     """build one or more VMs in various configurations"""
@@ -1248,10 +1305,10 @@
     else:
         executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer')
 
-    archive = join(libpath, 'c1visualizer.zip')
-    if not exists(executable):
+    archive = join(libpath, 'c1visualizer_2014-04-22.zip')
+    if not exists(executable) or not exists(archive):
         if not exists(archive):
-            mx.download(archive, ['https://java.net/downloads/c1visualizer/c1visualizer.zip'])
+            mx.download(archive, ['https://java.net/downloads/c1visualizer/c1visualizer_2014-04-22.zip'])
         zf = zipfile.ZipFile(archive, 'r')
         zf.extractall(libpath)
 
@@ -1345,33 +1402,154 @@
         with open(resultFile, 'w') as f:
             f.write(json.dumps(results))
 
-def jmh(args):
-    """run the JMH_BENCHMARKS"""
+def _get_jmh_path():
+    path = mx.get_env('JMH_BENCHMARKS', None)
+    if not path:
+        probe = join(dirname(_graal_home), 'java-benchmarks')
+        if exists(probe):
+            path = probe
+
+    if not path:
+        mx.abort("Please set the JMH_BENCHMARKS environment variable to point to the java-benchmarks workspace")
+    if not exists(path):
+        mx.abort("The directory denoted by the JMH_BENCHMARKS environment variable does not exist: " + path)
+    return path
+
+def makejmhdeps(args):
+    """creates and installs Maven dependencies required by the JMH benchmarks
 
-    # TODO: add option for `mvn clean package'
-    # TODO: add options to pass through arguments directly to JMH
+    The dependencies are specified by files named pom.mxdeps in the
+    JMH directory tree. Each such file contains a list of dependencies
+    defined in JSON format. For example:
+
+    '[{"artifactId" : "compiler.test", "groupId" : "com.oracle.graal", "deps" : ["com.oracle.graal.compiler.test"]}]'
+
+    will result in a dependency being installed in the local Maven repository
+    that can be referenced in a pom.xml file as follows:
+
+          <dependency>
+            <groupId>com.oracle.graal</groupId>
+            <artifactId>compiler.test</artifactId>
+            <version>1.0-SNAPSHOT</version>
+          </dependency>"""
+
+    parser = ArgumentParser(prog='mx makejmhdeps')
+    parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='<path>')
+    parser.add_argument('-p', '--permissive', action='store_true', help='issue note instead of error if a Maven dependency cannot be built due to missing projects/libraries')
+    args = parser.parse_args(args)
 
-    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 defined: " + str(jmhPath))
+    def makejmhdep(artifactId, groupId, deps):
+        graalSuite = mx.suite("graal")
+        path = artifactId + '.jar'
+        if args.permissive:
+            for name in deps:
+                if not mx.project(name, fatalIfMissing=False):
+                    if not mx.library(name, fatalIfMissing=False):
+                        mx.log('Skipping ' + groupId + '.' + artifactId + '.jar as ' + name + ' cannot be resolved')
+                        return
+        d = mx.Distribution(graalSuite, name=artifactId, path=path, sourcesPath=path, deps=deps, excludedLibs=[])
+        d.make_archive()
+        cmd = ['mvn', 'install:install-file', '-DgroupId=' + groupId, '-DartifactId=' + artifactId,
+               '-Dversion=1.0-SNAPSHOT', '-Dpackaging=jar', '-Dfile=' + d.path]
+        if not mx._opts.verbose:
+            cmd.append('-q')
+        if args.settings:
+            cmd = cmd + ['-s', args.settings]
+        mx.run(cmd)
+        os.unlink(d.path)
 
-    def _blackhole(x):
-        mx.logv(x[:-1])
+    jmhPath = _get_jmh_path()
+    for root, _, filenames in os.walk(jmhPath):
+        for f in [join(root, n) for n in filenames if n == 'pom.mxdeps']:
+            mx.logv('[processing ' + f + ']')
+            try:
+                with open(f) as fp:
+                    for d in json.load(fp):
+                        artifactId = d['artifactId']
+                        groupId = d['groupId']
+                        deps = d['deps']
+                        makejmhdep(artifactId, groupId, deps)
+            except ValueError as e:
+                mx.abort('Error parsing {}:\n{}'.format(f, e))
+
+def buildjmh(args):
+    """build the JMH benchmarks"""
 
+    parser = ArgumentParser(prog='mx buildjmh')
+    parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='<path>')
+    parser.add_argument('-c', action='store_true', dest='clean', help='clean before building')
+    args = parser.parse_args(args)
 
-    # (Re)install graal.jar into the local m2 repository since the micros-graal
-    # benchmarks have it as a dependency
-    graalDist = mx.distribution('GRAAL')
-    cmd = ['mvn', 'install:install-file', '-q',
-           '-Dfile=' + graalDist.path, '-DgroupId=com.oracle.graal', '-DartifactId=graal',
-           '-Dversion=1.0-SNAPSHOT', '-Dpackaging=jar']
-    if graalDist.sourcesPath:
-        cmd = cmd + ['-Dsources=' + graalDist.sourcesPath]
-    mx.run(cmd)
+    jmhPath = _get_jmh_path()
+    mx.log('JMH benchmarks: ' + jmhPath)
+
+    # Ensure the mx injected dependencies are up to date
+    makejmhdeps(['-p'] + (['-s', args.settings] if args.settings else []))
+
+    timestamp = mx.TimeStampFile(join(_graal_home, 'mx', 'jmh', jmhPath.replace(os.sep, '_') + '.timestamp'))
+    mustBuild = args.clean
+    if not mustBuild:
+        try:
+            hgfiles = [join(jmhPath, f) for f in subprocess.check_output(['hg', '-R', jmhPath, 'locate']).split('\n')]
+            mustBuild = timestamp.isOlderThan(hgfiles)
+        except:
+            # not a Mercurial repository or hg commands are not available.
+            mustBuild = True
 
-    mx.log("Building benchmarks...")
-    mx.run(['mvn', 'package'], cwd=jmhPath, out=_blackhole)
+    if mustBuild:
+        buildOutput = []
+        def _redirect(x):
+            if mx._opts.verbose:
+                mx.log(x[:-1])
+            else:
+                buildOutput.append(x)
+        env = os.environ.copy()
+        env['JAVA_HOME'] = _jdk(vmToCheck='server')
+        env['MAVEN_OPTS'] = '-server'
+        mx.log("Building benchmarks...")
+        cmd = ['mvn']
+        if args.settings:
+            cmd = cmd + ['-s', args.settings]
+        if args.clean:
+            cmd.append('clean')
+        cmd.append('package')
+        retcode = mx.run(cmd, cwd=jmhPath, out=_redirect, env=env, nonZeroIsFatal=False)
+        if retcode != 0:
+            mx.log(''.join(buildOutput))
+            mx.abort(retcode)
+        timestamp.touch()
+    else:
+        mx.logv('[all Mercurial controlled files in ' + jmhPath + ' are older than ' + timestamp.path + ' - skipping build]')
+
+def jmh(args):
+    """run the JMH benchmarks
+
+    This command respects the standard --vm and --vmbuild options
+    for choosing which VM to run the benchmarks with."""
+    if '-h' in args:
+        mx.help_(['jmh'])
+        mx.abort(1)
+
+    vmArgs, benchmarksAndJsons = _extract_VM_args(args)
+
+    benchmarks = [b for b in benchmarksAndJsons if not b.startswith('{')]
+    jmhArgJsons = [b for b in benchmarksAndJsons if b.startswith('{')]
+
+    jmhArgs = {'-rff' : join(_graal_home, 'mx', 'jmh', 'jmh.out'), '-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'}
+
+    # e.g. '{"-wi" : 20}'
+    for j in jmhArgJsons:
+        try:
+            for n, v in json.loads(j).iteritems():
+                if v is None:
+                    del jmhArgs[n]
+                else:
+                    jmhArgs[n] = v
+        except ValueError as e:
+            mx.abort('error parsing JSON input: {}\n{}'.format(j, e))
+
+    jmhPath = _get_jmh_path()
+    mx.log('Using benchmarks in ' + jmhPath)
 
     matchedSuites = set()
     numBench = [0]
@@ -1385,8 +1563,7 @@
 
         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
+            mx.abort('Missing ' + microJar + ' - please run "mx buildjmh"')
         if benchmarks:
             def _addBenchmark(x):
                 if x.startswith("Benchmark:"):
@@ -1417,16 +1594,14 @@
         (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",
-            "-v", "EXTRA" if mx._opts.verbose else "NORMAL",
-            "-i", "10", "-wi", "10",
-            "--jvm", exe,
-            "--jvmArgs", " ".join(["-" + vm] + forkedVmArgs)] + regex,
-            addDefaultArgs=False,
-            cwd=jmhPath)
-
+        javaArgs = ['-jar', os.path.join(absoluteMicro, "target", "microbenchmarks.jar"),
+                    '--jvm', exe,
+                    '--jvmArgs', ' '.join(["-" + vm] + forkedVmArgs)]
+        for k, v in jmhArgs.iteritems():
+            javaArgs.append(k)
+            if len(str(v)):
+                javaArgs.append(str(v))
+        mx.run_java(javaArgs + regex, addDefaultArgs=False, cwd=jmhPath)
 
 def specjvm2008(args):
     """run one or more SPECjvm2008 benchmarks"""
@@ -1757,6 +1932,7 @@
 def mx_init(suite):
     commands = {
         'build': [build, ''],
+        'buildjmh': [buildjmh, '[-options]'],
         'buildvars': [buildvars, ''],
         'buildvms': [buildvms, '[-options]'],
         'c1visualizer' : [c1visualizer, ''],
@@ -1768,7 +1944,7 @@
         'hcfdis': [hcfdis, ''],
         'igv' : [igv, ''],
         'jdkhome': [print_jdkhome, ''],
-        'jmh': [jmh, '[VM options] [filters...]'],
+        'jmh': [jmh, '[VM options] [filters|JMH-args-as-json...]'],
         '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]'],
@@ -1776,9 +1952,10 @@
         'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'],
         'gate' : [gate, '[-options]'],
         'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
-        'unittest' : [unittest, '[VM options] [filters...]', _unittestHelpSuffix],
-        'longunittest' : [longunittest, '[VM options] [filters...]', _unittestHelpSuffix],
-        'shortunittest' : [shortunittest, '[VM options] [filters...]', _unittestHelpSuffix],
+        'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix],
+        'longunittest' : [longunittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix],
+        'makejmhdeps' : [makejmhdeps, ''],
+        'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix],
         'jacocoreport' : [jacocoreport, '[output directory]'],
         'site' : [site, '[-options]'],
         'vm': [vm, '[-options] class [args...]'],
--- a/mx/projects	Wed Apr 23 15:22:20 2014 +0200
+++ b/mx/projects	Wed Apr 23 15:48:38 2014 +0200
@@ -5,10 +5,21 @@
 library@JDK_TOOLS@path=${JAVA_HOME}/lib/tools.jar
 library@JDK_TOOLS@optional=true
 
-library@JUNIT@path=lib/junit-4.8.jar
-library@JUNIT@urls=http://repo1.maven.org/maven2/junit/junit/4.8/junit-4.8.jar
-library@JUNIT@sha1=4150c00c5706306ef0f8f1410e70c8ff12757922
+library@JUNIT@path=lib/junit-4.11.jar
+library@JUNIT@urls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar
+library@JUNIT@sha1=4e031bb61df09069aeb2bffb4019e7a5034a4ee0
 library@JUNIT@eclipse.container=org.eclipse.jdt.junit.JUNIT_CONTAINER/4
+library@JUNIT@sourcePath=lib/junit-4.11-sources.jar
+library@JUNIT@sourceUrls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11-sources.jar
+library@JUNIT@sourceSha1=28e0ad201304e4a4abf999ca0570b7cffc352c3c
+library@JUNIT@dependencies=HAMCREST
+
+library@HAMCREST@path=lib/hamcrest-core-1.3.jar
+library@HAMCREST@urls=http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
+library@HAMCREST@sha1=42a25dc3219429f0e5d060061f71acb49bf010a0
+library@HAMCREST@sourcePath=lib/hamcrest-core-1.3-sources.jar
+library@HAMCREST@sourceUrls=http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar
+library@HAMCREST@sourceSha1=1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b
 
 library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar
 library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar
@@ -45,6 +56,9 @@
 library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-8f0db117e64e.jar
 library@JAVA_ALLOCATION_INSTRUMENTER@sha1=64c0a5329fbcb8284640e58d83252e0a3b08c23e
 
+library@VECMATH@path=lib/vecmath-1.3.1.jar
+library@VECMATH@urls=http://mirrors.ibiblio.org/pub/mirrors/maven/java3d/jars/vecmath-1.3.1.jar
+
 distribution@GRAAL@path=graal.jar
 distribution@GRAAL@sourcesPath=graal.src.zip
 distribution@GRAAL@dependencies=\
@@ -239,7 +253,7 @@
 # graal.graph
 project@com.oracle.graal.graph@subDir=graal
 project@com.oracle.graal.graph@sourceDirs=src
-project@com.oracle.graal.graph@dependencies=com.oracle.graal.debug,com.oracle.graal.api.code,FINDBUGS
+project@com.oracle.graal.graph@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,FINDBUGS
 project@com.oracle.graal.graph@javaCompliance=1.8
 project@com.oracle.graal.graph@workingSets=Graal,Graph
 
@@ -269,7 +283,7 @@
 # graal.lir
 project@com.oracle.graal.lir@subDir=graal
 project@com.oracle.graal.lir@sourceDirs=src
-project@com.oracle.graal.lir@dependencies=com.oracle.graal.asm,com.oracle.graal.nodes
+project@com.oracle.graal.lir@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.asm
 project@com.oracle.graal.lir@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir@javaCompliance=1.8
 project@com.oracle.graal.lir@workingSets=Graal,LIR
@@ -359,7 +373,7 @@
 # graal.nodes
 project@com.oracle.graal.nodes@subDir=graal
 project@com.oracle.graal.nodes@sourceDirs=src
-project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements
+project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements,com.oracle.graal.lir
 project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.nodes@javaCompliance=1.8
 project@com.oracle.graal.nodes@annotationProcessors=com.oracle.graal.replacements.verifier
@@ -376,7 +390,7 @@
 # graal.phases
 project@com.oracle.graal.phases@subDir=graal
 project@com.oracle.graal.phases@sourceDirs=src
-project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes,com.oracle.graal.options
+project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes
 project@com.oracle.graal.phases@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.phases@javaCompliance=1.8
 project@com.oracle.graal.phases@workingSets=Graal,Phases
@@ -408,7 +422,7 @@
 # graal.compiler
 project@com.oracle.graal.compiler@subDir=graal
 project@com.oracle.graal.compiler@sourceDirs=src
-project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir
+project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc
 project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler@javaCompliance=1.8
 project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor
@@ -485,6 +499,14 @@
 project@com.oracle.graal.java@javaCompliance=1.8
 project@com.oracle.graal.java@workingSets=Graal,Java
 
+# graal.compiler.common
+project@com.oracle.graal.compiler.common@subDir=graal
+project@com.oracle.graal.compiler.common@sourceDirs=src
+project@com.oracle.graal.compiler.common@dependencies=com.oracle.graal.api.code,com.oracle.graal.options
+project@com.oracle.graal.compiler.common@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.compiler.common@javaCompliance=1.8
+project@com.oracle.graal.compiler.common@workingSets=Graal,Java
+
 # graal.baseline
 project@com.oracle.graal.baseline@subDir=graal
 project@com.oracle.graal.baseline@sourceDirs=src
@@ -611,14 +633,14 @@
 # graal.compiler.hsail.test
 project@com.oracle.graal.compiler.hsail.test@subDir=graal
 project@com.oracle.graal.compiler.hsail.test@sourceDirs=src
-project@com.oracle.graal.compiler.hsail.test@dependencies=com.oracle.graal.compiler.hsail.test.infra,com.oracle.graal.compiler.test
+project@com.oracle.graal.compiler.hsail.test@dependencies=com.oracle.graal.compiler.hsail.test.infra,com.oracle.graal.compiler.test,VECMATH
 project@com.oracle.graal.compiler.hsail.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.hsail.test@javaCompliance=1.8
 
 # graal.asm.hsail
 project@com.oracle.graal.asm.hsail@subDir=graal
 project@com.oracle.graal.asm.hsail@sourceDirs=src
-project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm,com.oracle.graal.graph
+project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm,com.oracle.graal.compiler.common
 project@com.oracle.graal.asm.hsail@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.hsail@javaCompliance=1.8
 
@@ -723,7 +745,7 @@
 # graal.truffle.hotspot.amd64
 project@com.oracle.graal.truffle.hotspot.amd64@subDir=graal
 project@com.oracle.graal.truffle.hotspot.amd64@sourceDirs=src
-project@com.oracle.graal.truffle.hotspot.amd64@dependencies=com.oracle.graal.truffle.hotspot,com.oracle.graal.hotspot.amd64
+project@com.oracle.graal.truffle.hotspot.amd64@dependencies=com.oracle.graal.truffle.hotspot,com.oracle.graal.asm.amd64
 project@com.oracle.graal.truffle.hotspot.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.truffle.hotspot.amd64@javaCompliance=1.8
 project@com.oracle.graal.truffle.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor
--- a/mxtool/mx.py	Wed Apr 23 15:22:20 2014 +0200
+++ b/mxtool/mx.py	Wed Apr 23 15:48:38 2014 +0200
@@ -36,6 +36,7 @@
 import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch
 import textwrap
 import socket
+import tarfile
 import hashlib
 import xml.parsers.expat
 import shutil, re, xml.dom.minidom
@@ -84,6 +85,89 @@
     def add_update_listener(self, listener):
         self.update_listeners.add(listener)
 
+    def make_archive(self):
+        # are sources combined into main archive?
+        unified = self.path == self.sourcesPath
+
+        with Archiver(self.path) as arc, Archiver(None if unified else self.sourcesPath) as srcArcRaw:
+            srcArc = arc if unified else srcArcRaw
+            services = {}
+            def overwriteCheck(zf, arcname, source):
+                if not hasattr(zf, '_provenance'):
+                    zf._provenance = {}
+                existingSource = zf._provenance.get(arcname, None)
+                if existingSource and existingSource != source and not arcname.endswith('/'):
+                    log('warning: ' + self.path + ': overwriting ' + arcname + '\n  new: ' + source + '\n  old: ' + existingSource)
+                zf._provenance[arcname] = source
+
+            for dep in self.sorted_deps(includeLibs=True):
+                if dep.isLibrary():
+                    l = dep
+                    # merge library jar into distribution jar
+                    logv('[' + self.path + ': adding library ' + l.name + ']')
+                    lpath = l.get_path(resolve=True)
+                    libSourcePath = l.get_source_path(resolve=True)
+                    if lpath:
+                        with zipfile.ZipFile(lpath, 'r') as lp:
+                            for arcname in lp.namelist():
+                                if arcname.startswith('META-INF/services/') and not arcname == 'META-INF/services/':
+                                    service = arcname[len('META-INF/services/'):]
+                                    assert '/' not in service
+                                    services.setdefault(service, []).extend(lp.read(arcname).splitlines())
+                                else:
+                                    overwriteCheck(arc.zf, arcname, lpath + '!' + arcname)
+                                    arc.zf.writestr(arcname, lp.read(arcname))
+                    if srcArc.zf and libSourcePath:
+                        with zipfile.ZipFile(libSourcePath, 'r') as lp:
+                            for arcname in lp.namelist():
+                                overwriteCheck(srcArc.zf, arcname, lpath + '!' + arcname)
+                                srcArc.zf.writestr(arcname, lp.read(arcname))
+                else:
+                    p = dep
+                    # skip a  Java project if its Java compliance level is "higher" than the configured JDK
+                    jdk = java(p.javaCompliance)
+                    if not jdk:
+                        log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, self.path))
+                        continue
+
+                    logv('[' + self.path + ': adding project ' + p.name + ']')
+                    outputDir = p.output_dir()
+                    for root, _, files in os.walk(outputDir):
+                        relpath = root[len(outputDir) + 1:]
+                        if relpath == join('META-INF', 'services'):
+                            for service in files:
+                                with open(join(root, service), 'r') as fp:
+                                    services.setdefault(service, []).extend([provider.strip() for provider in fp.readlines()])
+                        elif relpath == join('META-INF', 'providers'):
+                            for provider in files:
+                                with open(join(root, provider), 'r') as fp:
+                                    for service in fp:
+                                        services.setdefault(service.strip(), []).append(provider)
+                        else:
+                            for f in files:
+                                arcname = join(relpath, f).replace(os.sep, '/')
+                                overwriteCheck(arc.zf, arcname, join(root, f))
+                                arc.zf.write(join(root, f), arcname)
+                    if srcArc.zf:
+                        sourceDirs = p.source_dirs()
+                        if p.source_gen_dir():
+                            sourceDirs.append(p.source_gen_dir())
+                        for srcDir in sourceDirs:
+                            for root, _, files in os.walk(srcDir):
+                                relpath = root[len(srcDir) + 1:]
+                                for f in files:
+                                    if f.endswith('.java'):
+                                        arcname = join(relpath, f).replace(os.sep, '/')
+                                        overwriteCheck(srcArc.zf, arcname, join(root, f))
+                                        srcArc.zf.write(join(root, f), arcname)
+
+            for service, providers in services.iteritems():
+                arcname = 'META-INF/services/' + service
+                arc.zf.writestr(arcname, '\n'.join(providers))
+
+        self.notify_updated()
+
+
     def notify_updated(self):
         for l in self.update_listeners:
             l(self)
@@ -358,6 +442,18 @@
                     print >> fp, ap
         return outOfDate
 
+    def make_archive(self, path=None):
+        outputDir = self.output_dir()
+        if not path:
+            path = join(self.dir, self.name + '.jar')
+        with Archiver(path) as arc:
+            for root, _, files in os.walk(outputDir):
+                for f in files:
+                    relpath = root[len(outputDir) + 1:]
+                    arcname = join(relpath, f).replace(os.sep, '/')
+                    arc.zf.write(join(root, f), arcname)
+        return path
+
 def _make_absolute(path, prefix):
     """
     Makes 'path' absolute if it isn't already by prefixing 'prefix'
@@ -405,7 +501,7 @@
     return path
 
 class Library(Dependency):
-    def __init__(self, suite, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1):
+    def __init__(self, suite, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps):
         Dependency.__init__(self, suite, name)
         self.path = path.replace('/', os.sep)
         self.urls = urls
@@ -414,6 +510,7 @@
         self.sourcePath = sourcePath
         self.sourceUrls = sourceUrls
         self.sourceSha1 = sourceSha1
+        self.deps = deps
         for url in urls:
             if url.endswith('/') != self.path.endswith(os.sep):
                 abort('Path for dependency directory must have a URL ending with "/": path=' + self.path + ' url=' + url)
@@ -447,9 +544,9 @@
 
 
     def get_source_path(self, resolve):
-        if self.path is None:
+        if self.sourcePath is None:
             return None
-        path = _make_absolute(self.path, self.suite.dir)
+        path = _make_absolute(self.sourcePath, self.suite.dir)
         sha1path = path + '.sha1'
 
         return _download_file_with_sha1(self.name, path, self.sourceUrls, self.sourceSha1, sha1path, resolve, len(self.sourceUrls) != 0, sources=True)
@@ -460,9 +557,21 @@
             cp.append(path)
 
     def all_deps(self, deps, includeLibs, includeSelf=True, includeAnnotationProcessors=False):
-        if not includeLibs or not includeSelf:
+        """
+        Add the transitive set of dependencies for this library to the 'deps' list.
+        """
+        if not includeLibs:
+            return deps
+        childDeps = list(self.deps)
+        if self in deps:
             return deps
-        deps.append(self)
+        for name in childDeps:
+            assert name != self.name
+            dep = library(name)
+            if not dep in deps:
+                dep.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
+        if not self in deps and includeSelf:
+            deps.append(self)
         return deps
 
 class HgConfig:
@@ -619,7 +728,8 @@
             sourcePath = attrs.pop('sourcePath', None)
             sourceUrls = pop_list(attrs, 'sourceUrls')
             sourceSha1 = attrs.pop('sourceSha1', None)
-            l = Library(self, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1)
+            deps = pop_list(attrs, 'dependencies')
+            l = Library(self, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps)
             l.__dict__.update(attrs)
             self.libs.append(l)
 
@@ -1693,6 +1803,7 @@
     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')
+    parser.add_argument('--jdt-show-task-tags', action='store_true', help='show task tags as Eclipse batch compiler warnings')
     parser.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>')
 
     if suppliedParser:
@@ -1918,11 +2029,15 @@
                 if not exists(jdtProperties):
                     log('JDT properties file {0} not found'.format(jdtProperties))
                 else:
-                    # convert all warnings to errors
-                    if args.jdt_warning_as_error:
+                    with open(jdtProperties) as fp:
+                        origContent = fp.read()
+                        content = origContent
+                        if args.jdt_warning_as_error:
+                            content = content.replace('=warning', '=error')
+                        if not args.jdt_show_task_tags:
+                            content = content + '\norg.eclipse.jdt.core.compiler.problem.tasks=ignore'
+                    if origContent != content:
                         jdtPropertiesTmp = jdtProperties + '.tmp'
-                        with open(jdtProperties) as fp:
-                            content = fp.read().replace('=warning', '=error')
                         with open(jdtPropertiesTmp, 'w') as fp:
                             fp.write(content)
                         toBeDeleted.append(jdtPropertiesTmp)
@@ -1943,6 +2058,39 @@
         return args
     return None
 
+def _chunk_files_for_command_line(files, limit=None, pathFunction=None):
+    """
+    Returns a generator for splitting up a list of files into chunks such that the
+    size of the space separated file paths in a chunk is less than a given limit.
+    This is used to work around system command line length limits.
+    """
+    chunkSize = 0
+    chunkStart = 0
+    if limit is None:
+        commandLinePrefixAllowance = 3000
+        if get_os() == 'windows':
+            # The CreateProcess function on Windows limits the length of a command line to
+            # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx)
+            limit = 32768 - commandLinePrefixAllowance
+        else:
+            # Using just SC_ARG_MAX without extra downwards adjustment
+            # results in "[Errno 7] Argument list too long" on MacOS.
+            syslimit = os.sysconf('SC_ARG_MAX') - 20000
+            limit = syslimit - commandLinePrefixAllowance
+    for i in range(len(files)):
+        path = files[i] if pathFunction is None else pathFunction(files[i])
+        size = len(path) + 1
+        if chunkSize + size < limit:
+            chunkSize += size
+        else:
+            assert i > chunkStart
+            yield files[chunkStart:i]
+            chunkStart = i
+            chunkSize = 0
+    if chunkStart == 0:
+        assert chunkSize < limit
+        yield files
+
 def eclipseformat(args):
     """run the Eclipse Code Formatter on the Java sources
 
@@ -2045,18 +2193,19 @@
         if res is not batch:
             res.javafiles = res.javafiles + batch.javafiles
 
-    print "we have: " + str(len(batches)) + " batches"
+    log("we have: " + str(len(batches)) + " batches")
     for batch in batches.itervalues():
-        run([args.eclipse_exe,
-            '-nosplash',
-            '-application',
-            'org.eclipse.jdt.core.JavaCodeFormatter',
-            '-vm', java(batch.javaCompliance).java,
-            '-config', batch.path]
-            + [f.path for f in batch.javafiles])
-        for fi in batch.javafiles:
-            if fi.update(batch.removeTrailingWhitespace):
-                modified.append(fi)
+        for chunk in _chunk_files_for_command_line(batch.javafiles, pathFunction=lambda f: f.path):
+            run([args.eclipse_exe,
+                '-nosplash',
+                '-application',
+                'org.eclipse.jdt.core.JavaCodeFormatter',
+                '-vm', java(batch.javaCompliance).java,
+                '-config', batch.path]
+                + [f.path for f in chunk])
+            for fi in chunk:
+                if fi.update(batch.removeTrailingWhitespace):
+                    modified.append(fi)
 
     log('{0} files were modified'.format(len(modified)))
 
@@ -2165,124 +2314,50 @@
         log('Running pylint on ' + pyfile + '...')
         run(['pylint', '--reports=n', '--rcfile=' + rcfile, pyfile], env=env)
 
+"""
+Utility for creating and updating a zip file atomically.
+"""
+class Archiver:
+    def __init__(self, path):
+        self.path = path
+
+    def __enter__(self):
+        if self.path:
+            fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path))
+            self.tmpFd = fd
+            self.tmpPath = tmp
+            self.zf = zipfile.ZipFile(tmp, 'w')
+        else:
+            self.tmpFd = None
+            self.tmpPath = None
+            self.zf = None
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        if self.zf:
+            self.zf.close()
+            os.close(self.tmpFd)
+            # Correct the permissions on the temporary file which is created with restrictive permissions
+            os.chmod(self.tmpPath, 0o666 & ~currentUmask)
+            # Atomic on Unix
+            shutil.move(self.tmpPath, self.path)
+
 def archive(args):
     """create jar files for projects and distributions"""
     parser = ArgumentParser(prog='mx archive')
     parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...')
     args = parser.parse_args(args)
 
-
-    class Archive:
-        def __init__(self, path):
-            self.path = path
-
-        def __enter__(self):
-            if self.path:
-                fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path))
-                self.tmpFd = fd
-                self.tmpPath = tmp
-                self.zf = zipfile.ZipFile(tmp, 'w')
-            else:
-                self.tmpFd = None
-                self.tmpPath = None
-                self.zf = None
-            return self
-
-        def __exit__(self, exc_type, exc_value, traceback):
-            if self.zf:
-                self.zf.close()
-                os.close(self.tmpFd)
-                # Correct the permissions on the temporary file which is created with restrictive permissions
-                os.chmod(self.tmpPath, 0o666 & ~currentUmask)
-                # Atomic on Unix
-                shutil.move(self.tmpPath, self.path)
-
     archives = []
     for name in args.names:
         if name.startswith('@'):
             dname = name[1:]
             d = distribution(dname)
-            with Archive(d.path) as arc, Archive(d.sourcesPath) as srcArc:
-                services = {}
-                def overwriteCheck(zf, arcname, source):
-                    if arcname in zf.namelist():
-                        log('warning: ' + d.path + ': overwriting ' + arcname + ' [source: ' + source + ']')
-
-                for dep in d.sorted_deps(includeLibs=True):
-                    if dep.isLibrary():
-                        l = dep
-                        # merge library jar into distribution jar
-                        logv('[' + d.path + ': adding library ' + l.name + ']')
-                        lpath = l.get_path(resolve=True)
-                        libSourcePath = l.get_source_path(resolve=True)
-                        if lpath:
-                            with zipfile.ZipFile(lpath, 'r') as lp:
-                                for arcname in lp.namelist():
-                                    if arcname.startswith('META-INF/services/') and not arcname == 'META-INF/services/':
-                                        service = arcname[len('META-INF/services/'):]
-                                        assert '/' not in service
-                                        services.setdefault(service, []).extend(lp.read(arcname).splitlines())
-                                    else:
-                                        overwriteCheck(arc.zf, arcname, lpath + '!' + arcname)
-                                        arc.zf.writestr(arcname, lp.read(arcname))
-                        if srcArc.zf and libSourcePath:
-                            with zipfile.ZipFile(libSourcePath, 'r') as lp:
-                                for arcname in lp.namelist():
-                                    overwriteCheck(srcArc.zf, arcname, lpath + '!' + arcname)
-                                    srcArc.zf.writestr(arcname, lp.read(arcname))
-                    else:
-                        p = dep
-                        # skip a  Java project if its Java compliance level is "higher" than the configured JDK
-                        jdk = java(p.javaCompliance)
-                        if not jdk:
-                            log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, d.path))
-                            continue
-
-                        logv('[' + d.path + ': adding project ' + p.name + ']')
-                        outputDir = p.output_dir()
-                        for root, _, files in os.walk(outputDir):
-                            relpath = root[len(outputDir) + 1:]
-                            if relpath == join('META-INF', 'services'):
-                                for service in files:
-                                    with open(join(root, service), 'r') as fp:
-                                        services.setdefault(service, []).extend([provider.strip() for provider in fp.readlines()])
-                            elif relpath == join('META-INF', 'providers'):
-                                for provider in files:
-                                    with open(join(root, provider), 'r') as fp:
-                                        for service in fp:
-                                            services.setdefault(service.strip(), []).append(provider)
-                            else:
-                                for f in files:
-                                    arcname = join(relpath, f).replace(os.sep, '/')
-                                    overwriteCheck(arc.zf, arcname, join(root, f))
-                                    arc.zf.write(join(root, f), arcname)
-                        if srcArc.zf:
-                            for srcDir in p.source_dirs():
-                                for root, _, files in os.walk(srcDir):
-                                    relpath = root[len(srcDir) + 1:]
-                                    for f in files:
-                                        if f.endswith('.java'):
-                                            arcname = join(relpath, f).replace(os.sep, '/')
-                                            overwriteCheck(srcArc.zf, arcname, join(root, f))
-                                            srcArc.zf.write(join(root, f), arcname)
-
-                for service, providers in services.iteritems():
-                    arcname = 'META-INF/services/' + service
-                    arc.zf.writestr(arcname, '\n'.join(providers))
-
-            d.notify_updated()
+            d.make_archive()
             archives.append(d.path)
-
         else:
             p = project(name)
-            outputDir = p.output_dir()
-            with Archive(join(p.dir, p.name + '.jar')) as arc:
-                for root, _, files in os.walk(outputDir):
-                    for f in files:
-                        relpath = root[len(outputDir) + 1:]
-                        arcname = join(relpath, f).replace(os.sep, '/')
-                        arc.zf.write(join(root, f), arcname)
-                archives.append(arc.path)
+            archives.append(p.make_archive())
 
     return archives
 
@@ -2462,26 +2537,9 @@
             log('Running Checkstyle on {0} using {1}...'.format(sourceDir, config))
 
             try:
-
-                # Checkstyle is unable to read the filenames to process from a file, and the
-                # CreateProcess function on Windows limits the length of a command line to
-                # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx)
-                # so calling Checkstyle must be done in batches.
-                while len(javafilelist) != 0:
-                    i = 0
-                    size = 0
-                    while i < len(javafilelist):
-                        s = len(javafilelist[i]) + 1
-                        if size + s < 30000:
-                            size += s
-                            i += 1
-                        else:
-                            break
-
-                    batch = javafilelist[:i]
-                    javafilelist = javafilelist[i:]
+                for chunk in _chunk_files_for_command_line(javafilelist):
                     try:
-                        run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + batch, nonZeroIsFatal=False)
+                        run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + chunk, nonZeroIsFatal=False)
                     finally:
                         if exists(auditfileName):
                             errors = []
@@ -2853,35 +2911,47 @@
         if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'})
 
+        containerDeps = set()
+        libraryDeps = set()
+        projectDeps = set()
+
         for dep in p.all_deps([], True):
             if dep == p:
                 continue
-
             if dep.isLibrary():
                 if hasattr(dep, 'eclipse.container'):
-                    out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : getattr(dep, 'eclipse.container')})
-                elif hasattr(dep, 'eclipse.project'):
-                    out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + getattr(dep, 'eclipse.project')})
+                    container = getattr(dep, 'eclipse.container')
+                    containerDeps.add(container)
+                    libraryDeps -= set(dep.all_deps([], True))
                 else:
-                    path = dep.path
-                    dep.get_path(resolve=True)
-                    if not path or (not exists(path) and not dep.mustExist):
-                        continue
-
-                    # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
-                    # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
-                    # safest to simply use absolute paths.
-                    path = _make_absolute(path, p.suite.dir)
-
-                    attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
-
-                    sourcePath = dep.get_source_path(resolve=True)
-                    if sourcePath is not None:
-                        attributes['sourcepath'] = sourcePath
-                    out.element('classpathentry', attributes)
-                    libFiles.append(path)
+                    libraryDeps.add(dep)
             else:
-                out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
+                projectDeps.add(dep)
+
+        for dep in containerDeps:
+            out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : dep})
+
+        for dep in libraryDeps:
+            path = dep.path
+            dep.get_path(resolve=True)
+            if not path or (not exists(path) and not dep.mustExist):
+                continue
+
+            # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
+            # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
+            # safest to simply use absolute paths.
+            path = _make_absolute(path, p.suite.dir)
+
+            attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
+
+            sourcePath = dep.get_source_path(resolve=True)
+            if sourcePath is not None:
+                attributes['sourcepath'] = sourcePath
+            out.element('classpathentry', attributes)
+            libFiles.append(path)
+
+        for dep in projectDeps:
+            out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
 
         out.element('classpathentry', {'kind' : 'output', 'path' : getattr(p, 'eclipse.output', 'bin')})
         out.close('classpath')
@@ -3554,6 +3624,193 @@
     _zip_files(files, suite.dir, configZip.path)
     _zip_files(libFiles, suite.dir, configLibsZip)
 
+def intellijinit(args, refreshOnly=False):
+    """(re)generate Intellij project configurations"""
+
+    for suite in suites(True):
+        _intellij_suite(args, suite, refreshOnly)
+
+def _intellij_suite(args, suite, refreshOnly=False):
+
+    libraries = set()
+
+    ideaProjectDirectory = join(suite.dir, '.idea')
+
+    if not exists(ideaProjectDirectory):
+        os.mkdir(ideaProjectDirectory)
+    nameFile = join(ideaProjectDirectory, '.name')
+    update_file(nameFile, "Graal")
+    modulesXml = XMLDoc()
+    modulesXml.open('project', attributes={'version': '4'})
+    modulesXml.open('component', attributes={'name': 'ProjectModuleManager'})
+    modulesXml.open('modules')
+
+
+    def _intellij_exclude_if_exists(xml, p, name):
+        path = join(p.dir, name)
+        if exists(path):
+            xml.element('excludeFolder', attributes={'url':'file://$MODULE_DIR$/' + name})
+
+    annotationProcessorProfiles = {}
+
+    def _complianceToIntellijLanguageLevel(compliance):
+        return 'JDK_1_' + str(compliance.value)
+
+    # create the modules (1 module  = 1 Intellij project)
+    for p in suite.projects:
+        if p.native:
+            continue
+
+        if not java(p.javaCompliance):
+            log('Excluding {0} (JDK with compliance level {1} not available)'.format(p.name, p.javaCompliance))
+            continue
+
+        if not exists(p.dir):
+            os.makedirs(p.dir)
+
+        annotationProcessorProfileKey = tuple(p.annotation_processors())
+
+        if not annotationProcessorProfileKey in annotationProcessorProfiles:
+            annotationProcessorProfiles[annotationProcessorProfileKey] = [p]
+        else:
+            annotationProcessorProfiles[annotationProcessorProfileKey].append(p)
+
+        intellijLanguageLevel = _complianceToIntellijLanguageLevel(p.javaCompliance)
+
+        moduleXml = XMLDoc()
+        moduleXml.open('module', attributes={'type': 'JAVA_MODULE', 'version': '4'})
+
+        moduleXml.open('component', attributes={'name': 'NewModuleRootManager', 'LANGUAGE_LEVEL': intellijLanguageLevel, 'inherit-compiler-output': 'false'})
+        moduleXml.element('output', attributes={'url': 'file://$MODULE_DIR$/bin'})
+        moduleXml.element('exclude-output')
+
+        moduleXml.open('content', attributes={'url': 'file://$MODULE_DIR$'})
+        for src in p.srcDirs:
+            srcDir = join(p.dir, src)
+            if not exists(srcDir):
+                os.mkdir(srcDir)
+            moduleXml.element('sourceFolder', attributes={'url':'file://$MODULE_DIR$/' + src, 'isTestSource': 'false'})
+
+        if len(p.annotation_processors()) > 0:
+            genDir = p.source_gen_dir()
+            if not exists(genDir):
+                os.mkdir(genDir)
+            moduleXml.element('sourceFolder', attributes={'url':'file://$MODULE_DIR$/' + os.path.relpath(genDir, p.dir), 'isTestSource': 'false'})
+
+        for name in ['.externalToolBuilders', '.settings', 'nbproject']:
+            _intellij_exclude_if_exists(moduleXml, p, name)
+        moduleXml.close('content')
+
+        moduleXml.element('orderEntry', attributes={'type': 'jdk', 'jdkType': 'JavaSDK', 'jdkName': str(p.javaCompliance)})
+        moduleXml.element('orderEntry', attributes={'type': 'sourceFolder', 'forTests': 'false'})
+
+        deps = p.all_deps([], True, includeAnnotationProcessors=True)
+        for dep in deps:
+            if dep == p:
+                continue
+
+            if dep.isLibrary():
+                if dep.mustExist:
+                    libraries.add(dep)
+                    moduleXml.element('orderEntry', attributes={'type': 'library', 'name': dep.name, 'level': 'project'})
+            else:
+                moduleXml.element('orderEntry', attributes={'type': 'module', 'module-name': dep.name})
+
+        moduleXml.close('component')
+        moduleXml.close('module')
+        moduleFile = join(p.dir, p.name + '.iml')
+        update_file(moduleFile, moduleXml.xml(indent='  ', newl='\n'))
+
+        moduleFilePath = "$PROJECT_DIR$/" + os.path.relpath(moduleFile, suite.dir)
+        modulesXml.element('module', attributes={'fileurl': 'file://' + moduleFilePath, 'filepath': moduleFilePath})
+
+    modulesXml.close('modules')
+    modulesXml.close('component')
+    modulesXml.close('project')
+    moduleXmlFile = join(ideaProjectDirectory, 'modules.xml')
+    update_file(moduleXmlFile, modulesXml.xml(indent='  ', newl='\n'))
+
+    # TODO What about cross-suite dependencies?
+
+    librariesDirectory = join(ideaProjectDirectory, 'libraries')
+
+    if not exists(librariesDirectory):
+        os.mkdir(librariesDirectory)
+
+    # Setup the libraries that were used above
+    # TODO: setup all the libraries from the suite regardless of usage?
+    for library in libraries:
+        libraryXml = XMLDoc()
+
+        libraryXml.open('component', attributes={'name': 'libraryTable'})
+        libraryXml.open('library', attributes={'name': library.name})
+        libraryXml.open('CLASSES')
+        libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.get_path(True), suite.dir) + '!/'})
+        libraryXml.close('CLASSES')
+        libraryXml.element('JAVADOC')
+        if library.sourcePath:
+            libraryXml.open('SOURCES')
+            libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.get_source_path(True), suite.dir) + '!/'})
+            libraryXml.close('SOURCES')
+        else:
+            libraryXml.element('SOURCES')
+        libraryXml.close('library')
+        libraryXml.close('component')
+
+        libraryFile = join(librariesDirectory, library.name + '.xml')
+        update_file(libraryFile, libraryXml.xml(indent='  ', newl='\n'))
+
+
+
+    # Set annotation processor profiles up, and link them to modules in compiler.xml
+    compilerXml = XMLDoc()
+    compilerXml.open('project', attributes={'version': '4'})
+    compilerXml.open('component', attributes={'name': 'CompilerConfiguration'})
+
+    compilerXml.element('option', attributes={'name': "DEFAULT_COMPILER", 'value': 'Javac'})
+    compilerXml.element('resourceExtensions')
+    compilerXml.open('wildcardResourcePatterns')
+    compilerXml.element('entry', attributes={'name': '!?*.java'})
+    compilerXml.close('wildcardResourcePatterns')
+
+    if annotationProcessorProfiles:
+        compilerXml.open('annotationProcessing')
+        for processors, modules in annotationProcessorProfiles.items():
+            compilerXml.open('profile', attributes={'default': 'false', 'name': '-'.join(processors), 'enabled': 'true'})
+            compilerXml.element('sourceOutputDir', attributes={'name': 'src_gen'})  # TODO use p.source_gen_dir() ?
+            compilerXml.element('outputRelativeToContentRoot', attributes={'value': 'true'})
+            compilerXml.open('processorPath', attributes={'useClasspath': 'false'})
+            for apName in processors:
+                pDep = dependency(apName)
+                for entry in pDep.all_deps([], True):
+                    if entry.isLibrary():
+                        compilerXml.element('entry', attributes={'name': '$PROJECT_DIR$/' + os.path.relpath(entry.path, suite.dir)})
+                    else:
+                        assert entry.isProject()
+                        compilerXml.element('entry', attributes={'name': '$PROJECT_DIR$/' + os.path.relpath(entry.output_dir(), suite.dir)})
+            compilerXml.close('processorPath')
+            for module in modules:
+                compilerXml.element('module', attributes={'name': module.name})
+            compilerXml.close('profile')
+        compilerXml.close('annotationProcessing')
+
+    compilerXml.close('component')
+    compilerXml.close('project')
+    compilerFile = join(ideaProjectDirectory, 'compiler.xml')
+    update_file(compilerFile, compilerXml.xml(indent='  ', newl='\n'))
+
+    # Wite misc.xml for global JDK config
+    miscXml = XMLDoc()
+    miscXml.open('project', attributes={'version': '4'})
+    miscXml.element('component', attributes={'name': 'ProjectRootManager', 'version': '2', 'languageLevel': _complianceToIntellijLanguageLevel(java().javaCompliance), 'project-jdk-name': str(java().javaCompliance), 'project-jdk-type': 'JavaSDK'})
+    miscXml.close('project')
+    miscFile = join(ideaProjectDirectory, 'misc.xml')
+    update_file(miscFile, miscXml.xml(indent='  ', newl='\n'))
+
+
+    # TODO look into copyright settings
+    # TODO should add vcs.xml support
+
 def ideclean(args):
     """remove all Eclipse and NetBeans project configurations"""
     def rm(path):
@@ -3563,6 +3820,7 @@
     for s in suites():
         rm(join(s.mxDir, 'eclipse-config.zip'))
         rm(join(s.mxDir, 'netbeans-config.zip'))
+        shutil.rmtree(join(s.dir, '.idea'), ignore_errors=True)
 
     for p in projects():
         if p.native:
@@ -3575,6 +3833,7 @@
         rm(join(p.dir, '.checkstyle'))
         rm(join(p.dir, '.project'))
         rm(join(p.dir, '.factorypath'))
+        rm(join(p.dir, p.name + '.iml'))
         rm(join(p.dir, 'build.xml'))
         rm(join(p.dir, 'eclipse-build.xml'))
         try:
@@ -3587,6 +3846,7 @@
     """(re)generate Eclipse and NetBeans project configurations"""
     eclipseinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
     netbeansinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
+    intellijinit(args, refreshOnly=refreshOnly)
     if not refreshOnly:
         fsckprojects([])
 
@@ -4080,6 +4340,75 @@
                 return items[indexes[0]]
             return None
 
+def exportlibs(args):
+    """export libraries to an archive file"""
+
+    parser = ArgumentParser(prog='exportlibs')
+    parser.add_argument('-b', '--base', action='store', help='base name of archive (default: libs)', default='libs', metavar='<path>')
+    parser.add_argument('--arc', action='store', choices=['tgz', 'tbz2', 'tar', 'zip'], default='tgz', help='the type of the archive to create')
+    parser.add_argument('--no-sha1', action='store_false', dest='sha1', help='do not create SHA1 signature of archive')
+    parser.add_argument('--no-md5', action='store_false', dest='md5', help='do not create MD5 signature of archive')
+    parser.add_argument('--include-system-libs', action='store_true', help='include system libraries (i.e., those not downloaded from URLs)')
+    parser.add_argument('extras', nargs=REMAINDER, help='extra files and directories to add to archive', metavar='files...')
+    args = parser.parse_args(args)
+
+    def createArchive(addMethod):
+        entries = {}
+        def add(path, arcname):
+            apath = os.path.abspath(path)
+            if not entries.has_key(arcname):
+                entries[arcname] = apath
+                logv('[adding ' + path + ']')
+                addMethod(path, arcname=arcname)
+            elif entries[arcname] != apath:
+                logv('[warning: ' + apath + ' collides with ' + entries[arcname] + ' as ' + arcname + ']')
+            else:
+                logv('[already added ' + path + ']')
+
+        for lib in _libs.itervalues():
+            if len(lib.urls) != 0 or args.include_system_libs:
+                add(lib.get_path(resolve=True), lib.path)
+        if args.extras:
+            for e in args.extras:
+                if os.path.isdir(e):
+                    for root, _, filenames in os.walk(e):
+                        for name in filenames:
+                            f = join(root, name)
+                            add(f, f)
+                else:
+                    add(e, e)
+
+    if args.arc == 'zip':
+        path = args.base + '.zip'
+        with zipfile.ZipFile(path, 'w') as zf:
+            createArchive(zf.write)
+    else:
+        path = args.base + '.tar'
+        mode = 'w'
+        if args.arc != 'tar':
+            sfx = args.arc[1:]
+            mode = mode + ':' + sfx
+            path = path + '.' + sfx
+        with tarfile.open(path, mode) as tar:
+            createArchive(tar.add)
+    log('created ' + path)
+
+    def digest(enabled, path, factory, suffix):
+        if enabled:
+            d = factory()
+            with open(path, 'rb') as f:
+                while True:
+                    buf = f.read(4096)
+                    if not buf:
+                        break
+                    d.update(buf)
+            with open(path + '.' + suffix, 'w') as fp:
+                print >> fp, d.hexdigest()
+            log('created ' + path + '.' + suffix)
+
+    digest(args.sha1, path, hashlib.sha1, 'sha1')
+    digest(args.md5, path, hashlib.md5, 'md5')
+
 def javap(args):
     """disassemble classes matching given pattern with javap"""
 
@@ -4148,11 +4477,13 @@
     'clean': [clean, ''],
     'eclipseinit': [eclipseinit, ''],
     'eclipseformat': [eclipseformat, ''],
+    'exportlibs': [exportlibs, ''],
     'findclass': [findclass, ''],
     'fsckprojects': [fsckprojects, ''],
     'help': [help_, '[command]'],
     'ideclean': [ideclean, ''],
     'ideinit': [ideinit, ''],
+    'intellijinit': [intellijinit, ''],
     'archive': [archive, '[options]'],
     'projectgraph': [projectgraph, ''],
     'pylint': [pylint, ''],
--- a/src/cpu/sparc/vm/compiledIC_sparc.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/cpu/sparc/vm/compiledIC_sparc.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -81,25 +81,26 @@
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
-void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
-#ifdef COMPILER2
+void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
   // Stub is fixed up when the corresponding call is converted from calling
   // compiled code to calling interpreted code.
   // set (empty), G5
   // jmp -1
 
-  address mark = cbuf.insts_mark();  // Get mark within main instrs section.
+  if (mark == NULL) {
+    mark = cbuf.insts_mark();  // Get mark within main instrs section.
+  }
 
   MacroAssembler _masm(&cbuf);
 
   address base =
-  __ start_a_stub(to_interp_stub_size()*2);
-  if (base == NULL) return;  // CodeBuffer::expand failed.
+  __ start_a_stub(to_interp_stub_size());
+  guarantee(base != NULL, "out of space");
 
   // Static stub relocation stores the instruction address of the call.
   __ relocate(static_stub_Relocation::spec(mark));
 
-  __ set_metadata(NULL, as_Register(Matcher::inline_cache_reg_encode()));
+  __ set_metadata(NULL, G5);
 
   __ set_inst_mark();
   AddressLiteral addrlit(-1);
@@ -107,11 +108,10 @@
 
   __ delayed()->nop();
 
+  assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size"); 
+
   // Update current stubs pointer and restore code_end.
   __ end_a_stub();
-#else
-  ShouldNotReachHere();
-#endif
 }
 #undef __
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include "graal/graalCodeInstaller.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCompilerToVM.hpp"
+#include "graal/graalJavaAccess.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+  if (inst->is_call() || inst->is_jump()) {
+    return pc_offset + NativeCall::instruction_size;
+  } else if (inst->is_call_reg()) {
+    return pc_offset + NativeCallReg::instruction_size;
+  } else if (inst->is_sethi()) {
+    return pc_offset + NativeFarCall::instruction_size;
+  } else {
+    fatal("unsupported type of instruction for call site");
+    return 0;
+  }
+}
+
+void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  Handle obj = OopData::object(data);
+  jobject value = JNIHandles::make_local(obj());
+  if (OopData::compressed(data)) {
+    fatal("unimplemented: narrow oop relocation");
+  } else {
+    NativeMovConstReg* move = nativeMovConstReg_at(pc);
+    move->set_data((intptr_t) value);
+
+    // We need two relocations:  one on the sethi and one on the add.
+    int oop_index = _oop_recorder->find_index(value);
+    RelocationHolder rspec = oop_Relocation::spec(oop_index);
+    _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
+    _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
+  }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  jint offset = DataSectionReference::offset(data);
+
+  NativeMovRegMem* load = nativeMovRegMem_at(pc);
+  int disp = _constants_size + pc_offset - offset - BytesPerInstWord;
+  load->set_offset(-disp);
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+  fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+  address pc = (address) inst;
+  if (inst->is_call()) {
+    NativeCall* call = nativeCall_at(pc);
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
+  } else if (inst->is_sethi()) {
+    NativeJump* jump = nativeJump_at(pc);
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
+  } else {
+    fatal(err_msg("unknown call or jump instruction at %p", pc));
+  }
+  TRACE_graal_3("relocating (foreign call) at %p", inst);
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method);
+  }
+#endif
+  switch (_next_call_type) {
+    case INLINE_INVOKE:
+      break;
+    case INVOKEVIRTUAL:
+    case INVOKEINTERFACE: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
+      break;
+    }
+    case INVOKESTATIC: {
+      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+      _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
+      break;
+    }
+    case INVOKESPECIAL: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
+      break;
+    }
+    default:
+      fatal("invalid _next_call_type value");
+      break;
+  }
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+  switch (mark) {
+    case POLL_NEAR:
+      fatal("unimplemented");
+      break;
+    case POLL_FAR:
+      _instructions->relocate(pc, relocInfo::poll_type);
+      break;
+    case POLL_RETURN_NEAR:
+      fatal("unimplemented");
+      break;
+    case POLL_RETURN_FAR:
+      _instructions->relocate(pc, relocInfo::poll_return_type);
+      break;
+    default:
+      fatal("invalid mark value");
+      break;
+  }
+}
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +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.
- */
-
-#ifndef CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
-#define CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
-
-#include "graal/graalCompiler.hpp"
-#include "graal/graalCompilerToVM.hpp"
-#include "graal/graalJavaAccess.hpp"
-
-inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
-  if (inst->is_call() || inst->is_jump()) {
-    return pc_offset + NativeCall::instruction_size;
-  } else if (inst->is_call_reg()) {
-    return pc_offset + NativeCallReg::instruction_size;
-  } else if (inst->is_sethi()) {
-    return pc_offset + NativeFarCall::instruction_size;
-  } else {
-    fatal("unsupported type of instruction for call site");
-    return 0;
-  }
-}
-
-inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
-  if (OopData::compressed(obj)) {
-    fatal("unimplemented: narrow oop relocation");
-  } else {
-    address pc = _instructions->start() + pc_offset;
-    Handle obj = OopData::object(data);
-    jobject value = JNIHandles::make_local(obj());
-
-    NativeMovConstReg* move = nativeMovConstReg_at(pc);
-    move->set_data((intptr_t) value);
-
-    // We need two relocations:  one on the sethi and one on the add.
-    int oop_index = _oop_recorder->find_index(value);
-    RelocationHolder rspec = oop_Relocation::spec(oop_index);
-    _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
-    _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
-  }
-}
-
-inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
-  address pc = _instructions->start() + pc_offset;
-  jint offset = DataSectionReference::offset(data);
-
-  NativeMovRegMem* load = nativeMovRegMem_at(pc);
-  int disp = _constants_size + pc_offset - offset - BytesPerInstWord;
-  load->set_offset(-disp);
-}
-
-inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
-  fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
-}
-
-inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
-  address pc = (address) inst;
-  if (inst->is_call()) {
-    NativeCall* call = nativeCall_at(pc);
-    call->set_destination((address) foreign_call_destination);
-    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
-  } else if (inst->is_sethi()) {
-    NativeJump* jump = nativeJump_at(pc);
-    jump->set_jump_destination((address) foreign_call_destination);
-    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
-  } else {
-    fatal(err_msg("unknown call or jump instruction at %p", pc));
-  }
-  TRACE_graal_3("relocating (foreign call) at %p", inst);
-}
-
-inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
-#ifdef ASSERT
-  Method* method = NULL;
-  // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method);
-  }
-#endif
-  switch (_next_call_type) {
-    case INLINE_INVOKE:
-      break;
-    case INVOKEVIRTUAL:
-    case INVOKEINTERFACE: {
-      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
-      _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
-      break;
-    }
-    case INVOKESTATIC: {
-      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
-      _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
-      break;
-    }
-    case INVOKESPECIAL: {
-      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
-      _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
-      break;
-    }
-    default:
-      fatal("invalid _next_call_type value");
-      break;
-  }
-}
-
-inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
-  switch (mark) {
-    case POLL_NEAR: {
-      fatal("unimplemented");
-    }
-    case POLL_FAR:
-      _instructions->relocate(pc, relocInfo::poll_type);
-      break;
-    case POLL_RETURN_NEAR: {
-      fatal("unimplemented");
-    }
-    case POLL_RETURN_FAR:
-      _instructions->relocate(pc, relocInfo::poll_return_type);
-      break;
-    default:
-      fatal("invalid mark value");
-      break;
-  }
-}
-
-#endif // CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
--- a/src/cpu/x86/vm/compiledIC_x86.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/cpu/x86/vm/compiledIC_x86.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -78,21 +78,24 @@
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
-void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
   // Stub is fixed up when the corresponding call is converted from
   // calling compiled code to calling interpreted code.
   // movq rbx, 0
   // jmp -5 # to self
 
-  address mark = cbuf.insts_mark();  // Get mark within main instrs section.
+  if (mark == NULL) {
+    mark = cbuf.insts_mark();  // Get mark within main instrs section.
+  }
 
   // Note that the code buffer's insts_mark is always relative to insts.
   // That's why we must use the macroassembler to generate a stub.
   MacroAssembler _masm(&cbuf);
 
   address base =
-  __ start_a_stub(to_interp_stub_size()*2);
-  if (base == NULL) return;  // CodeBuffer::expand failed.
+  __ start_a_stub(to_interp_stub_size());
+  guarantee(base != NULL, "out of space");
+
   // Static stub relocation stores the instruction address of the call.
   __ relocate(static_stub_Relocation::spec(mark), Assembler::imm_operand);
   // Static stub relocation also tags the Method* in the code-stream.
@@ -100,6 +103,8 @@
   // This is recognized as unresolved by relocs/nativeinst/ic code.
   __ jump(RuntimeAddress(__ pc()));
 
+  assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size"); 
+
   // Update current stubs pointer and restore insts_end.
   __ end_a_stub();
 }
@@ -117,12 +122,6 @@
 
 void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
   address stub = find_stub();
-#ifdef GRAAL
-  if (stub == NULL) {
-    set_destination_mt_safe(entry);
-    return;
-  }
-#endif
   guarantee(stub != NULL, "stub not found");
 
   if (TraceICs) {
@@ -172,14 +171,12 @@
     verify_alignment();
   }
 
-#ifndef GRAAL
   // Verify stub.
   address stub = find_stub();
   assert(stub != NULL, "no stub found for static call");
   // Creation also verifies the object.
   NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
   NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
-#endif
 
   // Verify state.
   assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/graalCodeInstaller_x86.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "compiler/disassembler.hpp"
+#include "runtime/javaCalls.hpp"
+#include "graal/graalEnv.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCodeInstaller.hpp"
+#include "graal/graalJavaAccess.hpp"
+#include "graal/graalCompilerToVM.hpp"
+#include "graal/graalRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+  if (inst->is_call() || inst->is_jump()) {
+    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
+    return (pc_offset + NativeCall::instruction_size);
+  } else if (inst->is_mov_literal64()) {
+    // mov+call instruction pair
+    jint offset = pc_offset + NativeMovConstReg::instruction_size;
+    u_char* call = (u_char*) (_instructions->start() + offset);
+    assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
+    offset += 3; /* prefix byte + opcode byte + modrm byte */
+    return (offset);
+  } else if (inst->is_call_reg()) {
+    // the inlined vtable stub contains a "call register" instruction
+    assert(method != NULL, "only valid for virtual calls");
+    return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
+  } else if (inst->is_cond_jump()) {
+    address pc = (address) (inst);
+    return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc);
+  } else {
+    fatal("unsupported type of instruction for call site");
+    return 0;
+  }
+}
+
+void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  Handle obj = OopData::object(data);
+  jobject value = JNIHandles::make_local(obj());
+  if (OopData::compressed(data)) {
+    address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
+    int oop_index = _oop_recorder->find_index(value);
+    _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
+    TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand);
+  } else {
+    address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+    *((jobject*) operand) = value;
+    _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+    TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand);
+  }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  jint offset = DataSectionReference::offset(data);
+
+  address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
+  address next_instruction = Assembler::locate_next_instruction(pc);
+  address dest = _constants->start() + offset;
+
+  long disp = dest - next_instruction;
+  assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+  *((jint*) operand) = (jint) disp;
+
+  _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+  TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset);
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+  if (cb->is_nmethod()) {
+    nmethod* nm = (nmethod*) cb;
+    nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
+  } else {
+    nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
+  }
+  _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+  address pc = (address) inst;
+  if (inst->is_call()) {
+    // NOTE: for call without a mov, the offset must fit a 32-bit immediate
+    //       see also CompilerToVM.getMaxCallTargetOffset()
+    NativeCall* call = nativeCall_at(pc);
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else if (inst->is_mov_literal64()) {
+    NativeMovConstReg* mov = nativeMovConstReg_at(pc);
+    mov->set_data((intptr_t) foreign_call_destination);
+    _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
+  } else if (inst->is_jump()) {
+    NativeJump* jump = nativeJump_at(pc);
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else if (inst->is_cond_jump()) {
+    address old_dest = nativeGeneralJump_at(pc)->jump_destination();
+    address disp = Assembler::locate_operand(pc, Assembler::call32_operand);
+    *(jint*) disp += ((address) foreign_call_destination) - old_dest;
+    _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else {
+    fatal("unsupported relocation for foreign call");
+  }
+
+  TRACE_graal_3("relocating (foreign call)  at %p", inst);
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method);
+  }
+#endif
+  switch (_next_call_type) {
+    case INLINE_INVOKE:
+      break;
+    case INVOKEVIRTUAL:
+    case INVOKEINTERFACE: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             virtual_call_Relocation::spec(_invoke_mark_pc),
+                                             Assembler::call32_operand);
+      break;
+    }
+    case INVOKESTATIC: {
+      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             relocInfo::static_call_type, Assembler::call32_operand);
+      break;
+    }
+    case INVOKESPECIAL: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                              relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+static void relocate_poll_near(address pc) {
+  NativeInstruction* ni = nativeInstruction_at(pc);
+  int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
+  int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
+  intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
+  *disp = (int32_t)new_disp;
+}
+
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+  switch (mark) {
+    case POLL_NEAR: {
+      relocate_poll_near(pc);
+      _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
+      break;
+    }
+    case POLL_FAR:
+      // This is a load from a register so there is no relocatable operand.
+      // We just have to ensure that the format is not disp32_operand
+      // so that poll_Relocation::fix_relocation_after_move does the right
+      // thing (i.e. ignores this relocation record)
+      _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand);
+      break;
+    case POLL_RETURN_NEAR: {
+      relocate_poll_near(pc);
+      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand);
+      break;
+    }
+    case POLL_RETURN_FAR:
+      // see comment above for POLL_FAR
+      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
+      break;
+    default:
+      fatal("invalid mark value");
+      break;
+  }
+}
--- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +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.
- */
-#ifndef CPU_X86_VM_CODEINSTALLER_X86_HPP
-#define CPU_X86_VM_CODEINSTALLER_X86_HPP
-
-#include "compiler/disassembler.hpp"
-#include "runtime/javaCalls.hpp"
-#include "graal/graalEnv.hpp"
-#include "graal/graalCompiler.hpp"
-#include "graal/graalCodeInstaller.hpp"
-#include "graal/graalJavaAccess.hpp"
-#include "graal/graalCompilerToVM.hpp"
-#include "graal/graalRuntime.hpp"
-#include "asm/register.hpp"
-#include "classfile/vmSymbols.hpp"
-#include "code/vmreg.hpp"
-
-inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
-  if (inst->is_call() || inst->is_jump()) {
-    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
-    return (pc_offset + NativeCall::instruction_size);
-  } else if (inst->is_mov_literal64()) {
-    // mov+call instruction pair
-    jint offset = pc_offset + NativeMovConstReg::instruction_size;
-    u_char* call = (u_char*) (_instructions->start() + offset);
-    assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
-    offset += 3; /* prefix byte + opcode byte + modrm byte */
-    return (offset);
-  } else if (inst->is_call_reg()) {
-    // the inlined vtable stub contains a "call register" instruction
-    assert(method != NULL, "only valid for virtual calls");
-    return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
-  } else if (inst->is_cond_jump()) {
-    address pc = (address) (inst);
-    return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc);
-  } else {
-    fatal("unsupported type of instruction for call site");
-    return 0;
-  }
-}
-
-inline bool check_metaspace_data(address pc, oop data) {
-  jlong value = MetaspaceData::value(data);
-  address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
-  if (MetaspaceData::compressed(data)) {
-    assert(*((jint*) operand) == value, err_msg("wrong compressed metaspace pointer: %p != %p", *((jint*) operand), value));
-  } else {
-    assert(*((jlong*) operand) == value, err_msg("wrong metaspace pointer: %p != %p", *((jlong*) operand), value));
-  }
-  return true;
-}
-
-inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
-  address pc = _instructions->start() + pc_offset;
-
-  Handle obj = OopData::object(data);
-  jobject value = JNIHandles::make_local(obj());
-  if (OopData::compressed(data)) {
-    address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
-    int oop_index = _oop_recorder->find_index(value);
-    _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
-    TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand);
-  } else {
-    address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
-    *((jobject*) operand) = value;
-    _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
-    TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand);
-  }
-}
-
-inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
-  address pc = _instructions->start() + pc_offset;
-  jint offset = DataSectionReference::offset(data);
-
-  address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
-  address next_instruction = Assembler::locate_next_instruction(pc);
-  address dest = _constants->start() + offset;
-
-  long disp = dest - next_instruction;
-  assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
-  *((jint*) operand) = (jint) disp;
-
-  _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
-  TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset);
-}
-
-inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
-  if (cb->is_nmethod()) {
-    nmethod* nm = (nmethod*) cb;
-    nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
-  } else {
-    nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
-  }
-  _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
-}
-
-inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
-  address pc = (address) inst;
-  if (inst->is_call()) {
-    // NOTE: for call without a mov, the offset must fit a 32-bit immediate
-    //       see also CompilerToVM.getMaxCallTargetOffset()
-    NativeCall* call = nativeCall_at(pc);
-    call->set_destination((address) foreign_call_destination);
-    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
-  } else if (inst->is_mov_literal64()) {
-    NativeMovConstReg* mov = nativeMovConstReg_at(pc);
-    mov->set_data((intptr_t) foreign_call_destination);
-    _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
-  } else if (inst->is_jump()) {
-    NativeJump* jump = nativeJump_at(pc);
-    jump->set_jump_destination((address) foreign_call_destination);
-    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
-  } else if (inst->is_cond_jump()) {
-    address old_dest = nativeGeneralJump_at(pc)->jump_destination();
-    address disp = Assembler::locate_operand(pc, Assembler::call32_operand);
-    *(jint*) disp += ((address) foreign_call_destination) - old_dest;
-    _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand);
-  } else {
-    fatal("unsupported relocation for foreign call");
-  }
-
-  TRACE_graal_3("relocating (foreign call)  at %p", inst);
-}
-
-inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
-#ifdef ASSERT
-  Method* method = NULL;
-  // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method);
-  }
-#endif
-  switch (_next_call_type) {
-    case INLINE_INVOKE:
-      break;
-    case INVOKEVIRTUAL:
-    case INVOKEINTERFACE: {
-      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
-
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
-      _instructions->relocate(call->instruction_address(),
-                                             virtual_call_Relocation::spec(_invoke_mark_pc),
-                                             Assembler::call32_operand);
-      break;
-    }
-    case INVOKESTATIC: {
-      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
-
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
-      _instructions->relocate(call->instruction_address(),
-                                             relocInfo::static_call_type, Assembler::call32_operand);
-      break;
-    }
-    case INVOKESPECIAL: {
-      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
-      _instructions->relocate(call->instruction_address(),
-                              relocInfo::opt_virtual_call_type, Assembler::call32_operand);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-static void relocate_poll_near(address pc) {
-  NativeInstruction* ni = nativeInstruction_at(pc);
-  int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
-  int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
-  intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
-  *disp = (int32_t)new_disp;
-}
-
-
-inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
-  switch (mark) {
-    case POLL_NEAR: {
-      relocate_poll_near(pc);
-      _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
-      break;
-    }
-    case POLL_FAR:
-      // This is a load from a register so there is no relocatable operand.
-      // We just have to ensure that the format is not disp32_operand
-      // so that poll_Relocation::fix_relocation_after_move does the right
-      // thing (i.e. ignores this relocation record)
-      _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand);
-      break;
-    case POLL_RETURN_NEAR: {
-      relocate_poll_near(pc);
-      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand);
-      break;
-    }
-    case POLL_RETURN_FAR:
-      // see comment above for MARK_POLL_FAR
-      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
-      break;
-    default:
-      fatal("invalid mark value");
-      break;
-  }
-}
-
-#endif // CPU_X86_VM_CODEINSTALLER_X86_HPP
-
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -3360,10 +3360,9 @@
 
 #ifdef GRAAL
   int implicit_exception_uncommon_trap_offset = __ pc() - start;
+
   __ pushptr(Address(r15_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset())));
 
-  int uncommon_trap_offset = __ pc() - start;
-
   // Save everything in sight.
   RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
   // fetch_unroll_info needs to call last_java_frame()
@@ -3643,7 +3642,6 @@
   _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
   _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
 #ifdef GRAAL
-  _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
   _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
 #endif
 }
--- a/src/cpu/x86/vm/vmStructs_x86.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/cpu/x86/vm/vmStructs_x86.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -47,6 +47,8 @@
 
 #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
   declare_constant(frame::arg_reg_save_area_bytes)                  \
+  declare_constant(frame::interpreter_frame_sender_sp_offset)       \
+  declare_constant(frame::interpreter_frame_last_sp_offset)         \
   declare_constant(VM_Version::CPU_CX8)                             \
   declare_constant(VM_Version::CPU_CMOV)                            \
   declare_constant(VM_Version::CPU_FXSR)                            \
--- a/src/gpu/hsail/vm/gpu_hsail.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/gpu/hsail/vm/gpu_hsail.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -59,19 +59,19 @@
 
 #define OBJECT                "Ljava/lang/Object;"
 #define STRING                "Ljava/lang/String;"
+#define JLTHREAD              "Ljava/lang/Thread;"
 #define HS_INSTALLED_CODE     "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;"
 #define HS_COMPILED_NMETHOD   "Lcom/oracle/graal/hotspot/HotSpotCompiledNmethod;"
 #define HS_NMETHOD            "Lcom/oracle/graal/hotspot/meta/HotSpotNmethod;"
 
-//  public native void executeKernel(HotSpotNmethod kernel, int jobSize, int i, int j, Object[] args) throws InvalidInstalledCodeException;
-
 JNINativeMethod Hsail::HSAIL_methods[] = {
   {CC"initialize",       CC"()Z",                               FN_PTR(Hsail::initialize)},
   {CC"generateKernel",   CC"([B" STRING ")J",                   FN_PTR(Hsail::generate_kernel)},
-  {CC"executeKernel0",   CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT")Z",  FN_PTR(Hsail::execute_kernel_void_1d)},
+  {CC"executeKernel0",   CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT"["JLTHREAD"I)Z",  FN_PTR(Hsail::execute_kernel_void_1d)},
 };
 
 void * Hsail::_device_context = NULL;
+jint   Hsail::_notice_safepoints = false;
 
 Hsail::okra_create_context_func_t  Hsail::_okra_create_context;
 Hsail::okra_create_kernel_func_t   Hsail::_okra_create_kernel;
@@ -86,6 +86,55 @@
 Hsail::okra_clearargs_func_t       Hsail::_okra_clearargs;
 Hsail::okra_register_heap_func_t   Hsail::_okra_register_heap;
 
+struct Stats {
+  int _dispatches;
+  int _deopts;
+  int _overflows;
+  bool _changeSeen;
+
+public:
+  Stats() {
+    _dispatches = _deopts = _overflows = 0;
+    _changeSeen = false;
+  }
+
+  void incDeopts() {
+    _deopts++;
+    _changeSeen = true;
+  }
+  void incOverflows() {
+    _overflows++;
+    _changeSeen = true;
+  }
+
+  void finishDispatch() {
+    _dispatches++;
+    if (_changeSeen) {
+      // print();
+      _changeSeen = false;
+    }
+  }
+
+  void print() {
+    tty->print_cr("Disp=%d, Deopts=%d, Ovflows=%d", _dispatches, _deopts, _overflows);
+  }
+
+};
+
+static Stats kernelStats;
+
+//static jint in_kernel = 0;
+
+void Hsail::notice_safepoints() {
+  _notice_safepoints = true;
+//  if (TraceGPUInteraction) {
+//    tty->print_cr("[HSAIL] Notice safepoint in_kernel=%d", in_kernel);
+//  }
+}
+
+void Hsail::ignore_safepoints() {
+  _notice_safepoints = false;
+}
 
 void Hsail::register_heap() {
   // After the okra functions are set up and the heap is initialized, register the java heap with HSA
@@ -97,10 +146,11 @@
   _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity());
 }
 
-GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args_handle, jobject oops_save_handle))
+GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args, jobject oops_save,
+                                                      jobject donor_threads, jint allocBytesPerWorkitem))
 
   ResourceMark rm;
-  jlong nmethodValue = HotSpotInstalledCode::codeBlob(kernel_handle);
+  jlong nmethodValue = InstalledCode::address(kernel_handle);
   if (nmethodValue == 0) {
     SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
   }
@@ -113,7 +163,7 @@
     SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
   }
 
-  return execute_kernel_void_1d_internal((address) kernel, dimX, args_handle, mh, nm, oops_save_handle, CHECK_0);
+  return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, oops_save, donor_threads, allocBytesPerWorkitem, CHECK_0);
 GPU_END
 
 static void showRanges(jboolean *a, int len) {
@@ -133,10 +183,79 @@
   }
 }
 
-jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args_handle, methodHandle& mh, nmethod *nm, jobject oops_save_handle, TRAPS) {
+// fill and retire old tlab and get a new one
+// if we can't get one, no problem someone will eventually do a gc
+void Hsail::getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, size_t tlabMinHsail) {
+  tlab->clear_before_allocation();    // fill and retire old tlab (will also check for null)
+
+  // get a size for a new tlab that is at least tlabMinHsail.
+  size_t new_tlab_size = tlab->compute_size(tlabMinHsail);
+  if (new_tlab_size == 0) return;
+
+  HeapWord* tlab_start = Universe::heap()->allocate_new_tlab(new_tlab_size);
+  if (tlab_start == NULL) return;
+
+  // ..and clear it if required
+  if (ZeroTLAB) {
+    Copy::zero_to_words(tlab_start, new_tlab_size);
+  }
+  // and init the tlab pointers
+  tlab->fill(tlab_start, tlab_start, new_tlab_size);
+}
+
+static void printTlabInfo (ThreadLocalAllocBuffer* tlab) {
+  HeapWord *start = tlab->start();
+  HeapWord *top = tlab->top();
+  HeapWord *end = tlab->end();
+  // sizes are in bytes
+  size_t tlabFree = tlab->free() * HeapWordSize;
+  size_t tlabUsed = tlab->used() * HeapWordSize;
+  size_t tlabSize = tlabFree + tlabUsed;
+  double freePct = 100.0 * (double) tlabFree/(double) tlabSize;
+  tty->print_cr("(%p, %p, %p), siz=%ld, free=%ld (%f%%)", start, top, end, tlabSize, tlabFree, freePct);
+}
+
 
+jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oops_save, 
+                                                jobject donor_threads, int allocBytesPerWorkitem, TRAPS) {
   ResourceMark rm(THREAD);
-  objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args_handle);
+  objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args);
+
+  // TODO: avoid donor thread logic if kernel does not allocate
+  objArrayOop donorThreadObjects = (objArrayOop) JNIHandles::resolve(donor_threads);
+  int numDonorThreads = donorThreadObjects->length();
+  guarantee(numDonorThreads > 0, "need at least one donor thread");
+  JavaThread** donorThreads = NEW_RESOURCE_ARRAY(JavaThread*, numDonorThreads);
+  for (int i = 0; i < numDonorThreads; i++) {
+    donorThreads[i] = java_lang_Thread::thread(donorThreadObjects->obj_at(i));
+  }
+
+
+  // compute tlabMinHsail based on number of workitems, number of donor
+  // threads, allocBytesPerWorkitem rounded up
+  size_t tlabMinHsail = (allocBytesPerWorkitem * dimX + (numDonorThreads - 1)) / numDonorThreads;
+  if (TraceGPUInteraction) {
+    tty->print_cr("computed tlabMinHsail = %d", tlabMinHsail);
+  }
+
+  for (int i = 0; i < numDonorThreads; i++) {
+    JavaThread* donorThread = donorThreads[i];
+    ThreadLocalAllocBuffer* tlab = &donorThread->tlab();
+    if (TraceGPUInteraction) {
+      tty->print("donorThread %d, is %p, tlab at %p -> ", i, donorThread, tlab);
+      printTlabInfo(tlab);
+    }
+
+    // note: this used vs. free limit checking should be based on some
+    // heuristic where we see how much this kernel tends to allocate
+    if ((tlab->end() == NULL) || (tlab->free() * HeapWordSize < tlabMinHsail)) {
+      getNewTlabForDonorThread(tlab, tlabMinHsail);
+      if (TraceGPUInteraction) {
+        tty->print("donorThread %d, refilled tlab, -> ", i);
+        printTlabInfo(tlab);
+      }
+    }
+  }
 
   // Reset the kernel arguments
   _okra_clearargs(kernel);
@@ -146,10 +265,14 @@
     e = new (ResourceObj::C_HEAP, mtInternal) HSAILDeoptimizationInfo();
     e->set_never_ran_array(NEW_C_HEAP_ARRAY(jboolean, dimX, mtInternal));
     memset(e->never_ran_array(), 0, dimX * sizeof(jboolean));
+    e->set_donor_threads(donorThreads);
   }
 
   // This object sets up the kernel arguments
   HSAILKernelArguments hka((address) kernel, mh->signature(), argsArray, mh->is_static(), e);
+  if (TraceGPUInteraction) {
+    tty->print_cr("[HSAIL] range=%d", dimX);
+  }
 
   // if any object passed was null, throw an exception here
   // doing this means the kernel code can avoid null checks on the object parameters.
@@ -165,25 +288,53 @@
   // Run the kernel
   bool success = false;
   {
-    TraceTime t1("execute kernel", TraceGPUInteraction);
+    TraceTime t("execute kernel", TraceGPUInteraction);
+
+    //in_kernel = 1;
+    // Run the kernel
     success = _okra_execute_with_range(kernel, dimX);
+    //in_kernel = 0;
+  }
+
+  // fix up any tlab tops that overflowed
+  bool anyOverflows = false;
+  for (int i = 0; i < numDonorThreads; i++) {
+    JavaThread * donorThread = donorThreads[i];
+    ThreadLocalAllocBuffer* tlab = &donorThread->tlab();
+    if (tlab->top() > tlab->end()) {
+      anyOverflows = true;
+      long overflowAmount = (long) tlab->top() - (long) tlab->pf_top(); 
+      // tlab->set_top is private this ugly hack gets around that
+      *(long *)((char *)tlab + in_bytes(tlab->top_offset())) = (long) tlab->pf_top();
+      if (TraceGPUInteraction) {
+        tty->print_cr("donorThread %d at %p overflowed by %ld bytes, setting last good top to %p", i, donorThread, overflowAmount, tlab->top());
+      }
+    }
+  }
+  if (anyOverflows) {
+    kernelStats.incOverflows();
   }
 
   if (UseHSAILDeoptimization) {
+    kernelStats.incDeopts();
     // check if any workitem requested a deopt
     // currently we only support at most one such workitem
     int deoptcode = e->deopt_occurred();
-    if (deoptcode != 0) {
-      if (deoptcode != 1) {
+    if (deoptcode != 1) {
+      if (deoptcode == 0) {
+        if (TraceGPUInteraction && _notice_safepoints != 0) {
+          tty->print_cr("[HSAIL] observed safepoint during kernel");
+        }
+      } else {
         // error condition detected in deopt code
         char msg[200];
         sprintf(msg, "deopt error detected, slot for workitem %d was not empty", -1 * (deoptcode + 1));
         guarantee(deoptcode == 1, msg);
       }
+    } else {
 
       {
         TraceTime t3("handle deoptimizing workitems", TraceGPUInteraction);
-
         if (TraceGPUInteraction) {
           tty->print_cr("deopt happened.");
           HSAILKernelDeoptimization * pdeopt = &e->_deopt_save_states[0];
@@ -194,7 +345,7 @@
         // the hsail frames in oops_save so they get adjusted by any
         // GC. Need to do this before leaving thread_in_vm mode.
         // resolve handle only needed once here (not exiting vm mode)
-        objArrayOop oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save_handle);
+        objArrayOop oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save);
 
         // since slots are allocated from the beginning, we know how far to look
         assert(e->num_deopts() < MAX_DEOPT_SAVE_STATES_SIZE, "deopt save state overflow");
@@ -228,7 +379,7 @@
 
             // update the hsailFrame from the oopsSaveArray
             // re-resolve the handle
-            oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save_handle);
+            oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save);
 
             int dregOopMap = hsailFrame->dreg_oops_map();
             for (int bit = 0; bit < 16; bit++) {
@@ -276,51 +427,51 @@
           tty->print_cr("[HSAIL] Deoptimizing to host completed for %d workitems", count_deoptimized);
         }
       }
-
-      {
-        TraceTime t3("handle never-rans", TraceGPUInteraction);
+    }
 
-        // Handle any never_ran workitems if there were any
-        int count_never_ran = 0;
-        bool handleNeverRansHere = true;
-        // turn off verbose trace stuff for javacall arg setup
-        bool savedTraceGPUInteraction = TraceGPUInteraction;
-        TraceGPUInteraction = false;
-        jboolean *never_ran_array = e->never_ran_array();
-        if (handleNeverRansHere) {
-          for (int k = 0; k < dimX; k++) {
-            if (never_ran_array[k]) {
-              // run it as a javaCall
-              KlassHandle methKlass = mh->method_holder();
-              Thread* THREAD = Thread::current();
-              JavaValue result(T_VOID);
-              JavaCallArguments javaArgs;
-              // re-resolve the args_handle here
-              objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args_handle);
-              // This object sets up the javaCall arguments
-              // the way argsArray is set up, this should work for instance methods as well
-              // (the receiver will be the first oop pushed)
-              HSAILJavaCallArguments hjca(&javaArgs, k, mh->signature(), resolvedArgsArray, mh->is_static());
-              if (mh->is_static()) {
-                JavaCalls::call_static(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD);
-              } else {
-                JavaCalls::call_virtual(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD);
-              }
-              count_never_ran++;
+    // Handle any never_ran workitems if there were any
+    {
+      TraceTime t("handle never-rans ", TraceGPUInteraction);
+      int count_never_ran = 0;
+      bool handleNeverRansHere = true;
+      // turn off verbose trace stuff for javacall arg setup
+      bool savedTraceGPUInteraction = TraceGPUInteraction;
+      TraceGPUInteraction = false;
+      jboolean *never_ran_array = e->never_ran_array();
+      if (handleNeverRansHere) {
+        for (int k = 0; k < dimX; k++) {
+          if (never_ran_array[k]) {
+            // run it as a javaCall
+            KlassHandle methKlass = mh->method_holder();
+            Thread* THREAD = Thread::current();
+            JavaValue result(T_VOID);
+            JavaCallArguments javaArgs;
+            // re-resolve the args_handle here
+            objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args);
+            // This object sets up the javaCall arguments
+            // the way argsArray is set up, this should work for instance methods as well
+            // (the receiver will be the first oop pushed)
+            HSAILJavaCallArguments hjca(&javaArgs, k, mh->signature(), resolvedArgsArray, mh->is_static());
+            if (mh->is_static()) {
+              JavaCalls::call_static(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD);
+            } else {
+              JavaCalls::call_virtual(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD);
             }
+            count_never_ran++;
           }
-          TraceGPUInteraction = savedTraceGPUInteraction;
-          if (TraceGPUInteraction) {
-            tty->print_cr("%d workitems never ran, have been run via JavaCall", count_never_ran);
-            showRanges(never_ran_array, dimX);
-          }
-        } // end of never-ran handling
-      }
+        }
+        TraceGPUInteraction = savedTraceGPUInteraction;
+        if (TraceGPUInteraction) {
+          tty->print_cr("%d workitems never ran, have been run via JavaCall", count_never_ran);
+          showRanges(never_ran_array, dimX);
+        }
+      } // end of never-ran handling
     }
 
     FREE_C_HEAP_ARRAY(jboolean, e->never_ran_array(), mtInternal);
     delete e;
   }
+  kernelStats.finishDispatch();
   return success;
 }
 
@@ -361,7 +512,7 @@
 
 #define LOOKUP_OKRA_FUNCTION(name, alias)  \
   _##alias =                               \
-    CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(handle, STRINGIFY(name))); \
+    CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(okra_lib_handle, STRINGIFY(name))); \
   if (_##alias == NULL) {      \
   tty->print_cr("[HSAIL] ***** Error: Failed to lookup %s in %s, wrong version of OKRA?", STRINGIFY(name), okra_library_name); \
         return false; \
@@ -377,22 +528,25 @@
 
   // here we know we have a valid okra_library_name to try to load
   char ebuf[O_BUFLEN];
+  char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_");
+  if (okra_lib_name_from_env_var != NULL) {
+    okra_library_name = okra_lib_name_from_env_var;
+  }
   if (TraceGPUInteraction) {
-      tty->print_cr("[HSAIL] library is %s", okra_library_name);
+    tty->print_cr("[HSAIL] library is %s", okra_library_name);
   }
-
-  void *handle = os::dll_load(okra_library_name, ebuf, O_BUFLEN);
-  // try alternate location if env variable set
-  char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_");
-  if ((handle == NULL) && (okra_lib_name_from_env_var != NULL)) {
-    handle = os::dll_load(okra_lib_name_from_env_var, ebuf, O_BUFLEN);
-    if ((handle != NULL) && TraceGPUInteraction) {
-      tty->print_cr("[HSAIL] using _OKRA_SIM_LIB_PATH_=%s", getenv("_OKRA_SIM_LIB_PATH_"));
-    }
-  }
-
-  if (handle == NULL) {
-    // Unable to dlopen okra
+  void *okra_lib_handle = NULL;
+#if defined(LINUX)
+  // Check first if the Okra library is already loaded.
+  // TODO: Figure out how to do this on other OSes.
+  okra_lib_handle = ::dlopen(okra_library_name, RTLD_LAZY | RTLD_NOLOAD);
+#endif
+  // If Okra library is not already loaded, load it here
+  if (okra_lib_handle == NULL) {
+    okra_lib_handle = os::dll_load(okra_library_name, ebuf, O_BUFLEN);
+  }  
+  if (okra_lib_handle == NULL) {
+    // Unable to open Okra library
     if (TraceGPUInteraction) {
       tty->print_cr("[HSAIL] library load failed.");
     }
@@ -401,7 +555,8 @@
   
   guarantee(_okra_create_context == NULL, "cannot repeat GPU initialization");
 
-  // at this point we know handle is valid and we can lookup the functions
+  // at this point we know  okra_lib_handle is valid whether we loaded
+  // here or earlier.  In either case, we can lookup the functions
   LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context);
   LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel);
   LOOKUP_OKRA_FUNCTION(okra_push_object, okra_push_object);
@@ -416,7 +571,7 @@
   LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap);
   // if we made it this far, real success
 
-  gpu::initialized_gpu("Okra");
+  Gpu::initialized_gpu(new Hsail());
 
   return true;
 GPU_END
--- a/src/gpu/hsail/vm/gpu_hsail.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/gpu/hsail/vm/gpu_hsail.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -27,11 +27,9 @@
 
 #include "utilities/exceptions.hpp"
 #include "graal/graalEnv.hpp"
-// #include "graal/graalCodeInstaller.hpp"
 #include "gpu_hsail_Frame.hpp"
 
-class Hsail {
-  friend class gpu;
+class Hsail : public Gpu {
 
   public:
   class HSAILKernelDeoptimization {
@@ -58,25 +56,28 @@
   class HSAILDeoptimizationInfo : public ResourceObj {
     friend class VMStructs;
    private:
+    jint* _notice_safepoints;
     jint _deopt_occurred;
     jint _deopt_next_index;
+    JavaThread** _donor_threads;
     jboolean * _never_ran_array;
 
    public:
     HSAILKernelDeoptimization _deopt_save_states[MAX_DEOPT_SAVE_STATES_SIZE];
 
     inline HSAILDeoptimizationInfo() {
+      _notice_safepoints = &Hsail::_notice_safepoints;
       _deopt_occurred = 0;
       _deopt_next_index = 0;
     }
 
     inline jint deopt_occurred() {
-      // Check that hsail did not write in the wrong place
       return _deopt_occurred;
     }
     inline jint num_deopts() { return _deopt_next_index; }
     inline jboolean *never_ran_array() { return _never_ran_array; }
     inline void  set_never_ran_array(jboolean *p) { _never_ran_array = p; }
+    inline void  set_donor_threads(JavaThread **threads) { _donor_threads = threads; }
   };
 
 
@@ -91,14 +92,17 @@
   JNIEXPORT static jlong generate_kernel(JNIEnv *env, jclass, jbyteArray code_handle, jstring name_handle);
 
   // static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args);
-  JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv *env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, jobject oopsSave);
+  JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv *env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, jobject oopsSave,
+                                                   jobject donorThreads, int allocBytesPerWorkitem);
+
+  // static native void getThreadPointers(Object[] donorThreads, long[] threadPointersOut);
+  JNIEXPORT static void get_thread_pointers(JNIEnv *env, jclass, jobject donor_threads_handle, jobject thread_ptrs_handle);
 
-  // static native void setSimulatorSingleThreaded0();
-  JNIEXPORT static void setSimulatorSingleThreaded0(JNIEnv *env, jclass);
+  static void getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, size_t tlabMinHsail);
 
-
-  static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oopsSave, TRAPS);
-
+  static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oopsSave,
+                                                  jobject donor_threads, int allocBytesPerWorkitem, TRAPS);
+  
   static void register_heap();
 
   static GraalEnv::CodeInstallResult install_code(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations);
@@ -108,6 +112,11 @@
   // Registers the implementations for the native methods in HSAILHotSpotBackend
   static bool register_natives(JNIEnv* env);
 
+  virtual const char* name() { return "HSAIL"; }
+
+  virtual void notice_safepoints();
+  virtual void ignore_safepoints();
+
 #if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
   typedef unsigned long long CUdeviceptr;
 #else
@@ -144,5 +153,8 @@
   
 protected:
   static void* _device_context;
+
+  // true if safepoints are activated
+  static jint _notice_safepoints;
 };
 #endif // GPU_HSAIL_HPP
--- a/src/gpu/hsail/vm/vmStructs_hsail.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -32,17 +32,19 @@
 // constants required by the Serviceability Agent. This file is
 // referenced by vmStructs.cpp.
 
-#define VM_STRUCTS_GPU_HSAIL(nonstatic_field)                                                                                                    \
+#define VM_STRUCTS_GPU_HSAIL(nonstatic_field)                                                                                         \
   nonstatic_field(HSAILFrame, _pc_offset,                                                  jint)                                      \
   nonstatic_field(HSAILFrame, _num_s_regs,                                                 jbyte)                                     \
   nonstatic_field(HSAILFrame, _save_area[0],                                               jlong)                                     \
-                                                                                                                                                                                                                                                                                      \
+                                                                                                                                      \
   nonstatic_field(Hsail::HSAILKernelDeoptimization, _workitemid,                                jint)                                 \
   nonstatic_field(Hsail::HSAILKernelDeoptimization, _actionAndReason,                           jint)                                 \
-  nonstatic_field(Hsail::HSAILKernelDeoptimization, _first_frame,                               HSAILFrame)                      \
-                                                                                                                                           \
+  nonstatic_field(Hsail::HSAILKernelDeoptimization, _first_frame,                               HSAILFrame)                           \
+                                                                                                                                      \
+  nonstatic_field(Hsail::HSAILDeoptimizationInfo, _notice_safepoints,                      jint*)                                     \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_occurred,                         jint)                                      \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_next_index,                       jint)                                      \
+  nonstatic_field(Hsail::HSAILDeoptimizationInfo, _donor_threads,                          JavaThread**)                              \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _never_ran_array,                        jboolean *)                                \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_save_states[0],                   Hsail::HSAILKernelDeoptimization)          \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_save_states[1],                   Hsail::HSAILKernelDeoptimization)
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -271,7 +271,7 @@
     tty->print_cr("[CUDA] Success: Created context for device: %d", _cu_device);
   }
 
-  gpu::initialized_gpu(device_name);
+  Gpu::initialized_gpu(new Ptx());
 
   return true;
 GPU_END
--- a/src/gpu/ptx/vm/gpu_ptx.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -93,7 +93,7 @@
 
 #define GRAAL_SUPPORTED_COMPUTE_CAPABILITY_VERSION 3.0
 
-class Ptx {
+class Ptx : public Gpu {
   friend class PtxCall;
 
 private:
@@ -120,6 +120,9 @@
   static int ncores(int major, int minor);
 
 public:
+
+  virtual const char* name() { return "PTX"; }
+
   // Registers the implementations for the native methods in PTXHotSpotBackend
   static bool register_natives(JNIEnv* env);
 
--- a/src/os/bsd/vm/gpu_bsd.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/os/bsd/vm/gpu_bsd.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 #include "hsail/vm/gpu_hsail.hpp"
 #include "utilities/ostream.hpp"
 
-jobject gpu::probe_gpus(JNIEnv* env) {
+jobject Gpu::probe_gpus(JNIEnv* env) {
 #ifdef __APPLE__
   /*
    * Let the CUDA driver initialization be the gate to GPU for now, pending
--- a/src/os/linux/vm/gpu_linux.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/os/linux/vm/gpu_linux.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -38,7 +38,7 @@
 
 #define PCI_DRIVER_NAME_START_POS 255
 
-jobject gpu::probe_gpus(JNIEnv* env) {
+jobject Gpu::probe_gpus(JNIEnv* env) {
   bool hsail = false;
   bool ptx = false;
 
--- a/src/os/windows/vm/gpu_windows.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/os/windows/vm/gpu_windows.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -27,7 +27,7 @@
 #include "hsail/vm/gpu_hsail.hpp"
 #include "utilities/ostream.hpp"
 
-jobject gpu::probe_gpus(JNIEnv* env) {
+jobject Gpu::probe_gpus(JNIEnv* env) {
   // TODO: add detection of PTX/NVidia
   if (Hsail::register_natives(env)) {
     return env->NewStringUTF("HSAIL");
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -186,6 +186,9 @@
   /* Support for Graal */                                                                                                \
   do_klass(CompilerThread_klass,                  com_oracle_graal_compiler_CompilerThread,                     Opt) \
   do_klass(BitSet_klass,                          java_util_BitSet,                                             Opt) \
+  /* graal.graph */                                                                                                  \
+  do_klass(Node_klass,                            com_oracle_graal_graph_Node,                                  Opt) \
+  do_klass(NodeClass_klass,                       com_oracle_graal_graph_NodeClass,                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompiledCode_klass,             com_oracle_graal_hotspot_HotSpotCompiledCode,                 Opt) \
   do_klass(HotSpotCompiledCode_Comment_klass,     com_oracle_graal_hotspot_HotSpotCompiledCode_Comment,         Opt) \
@@ -204,6 +207,9 @@
   do_klass(HotSpotResolvedJavaMethod_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,      Opt) \
   do_klass(HotSpotResolvedObjectType_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,      Opt) \
   do_klass(HotSpotMonitorValue_klass,             com_oracle_graal_hotspot_meta_HotSpotMonitorValue,            Opt) \
+  do_klass(HotSpotObjectConstant_klass,           com_oracle_graal_hotspot_meta_HotSpotObjectConstant,          Opt) \
+  do_klass(HotSpotMetaspaceConstant_klass,        com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstant,       Opt) \
+  do_klass(HotSpotStackFrameReference_klass,      com_oracle_graal_hotspot_HotSpotStackFrameReference,          Opt) \
   /* graal.api.code */                                                                                               \
   do_klass(Assumptions_klass,                     com_oracle_graal_api_code_Assumptions,                        Opt) \
   do_klass(Assumptions_ConcreteMethod_klass,      com_oracle_graal_api_code_Assumptions_ConcreteMethod,         Opt) \
@@ -224,6 +230,7 @@
   do_klass(CompilationResult_Site_klass,          com_oracle_graal_api_code_CompilationResult_Site,             Opt) \
   do_klass(ExternalCompilationResult_klass,       com_oracle_graal_gpu_ExternalCompilationResult,               Opt) \
   do_klass(InfopointReason_klass,                 com_oracle_graal_api_code_InfopointReason,                    Opt) \
+  do_klass(InstalledCode_klass,                   com_oracle_graal_api_code_InstalledCode,                      Opt) \
   do_klass(code_Register_klass,                   com_oracle_graal_api_code_Register,                           Opt) \
   do_klass(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Opt) \
   do_klass(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
@@ -231,6 +238,8 @@
   do_klass(SpeculationLog_klass,                  com_oracle_graal_api_code_SpeculationLog,                     Opt) \
   /* graal.api.meta */                                                                                               \
   do_klass(Constant_klass,                        com_oracle_graal_api_meta_Constant,                           Opt) \
+  do_klass(PrimitiveConstant_klass,               com_oracle_graal_api_meta_PrimitiveConstant,                  Opt) \
+  do_klass(NullConstant_klass,                    com_oracle_graal_api_meta_NullConstant,                       Opt) \
   do_klass(ExceptionHandler_klass,                com_oracle_graal_api_meta_ExceptionHandler,                   Opt) \
   do_klass(Kind_klass,                            com_oracle_graal_api_meta_Kind,                               Opt) \
   do_klass(JavaMethod_klass,                      com_oracle_graal_api_meta_JavaMethod,                         Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -292,6 +292,9 @@
   /* Support for Graal */                                                                                                             \
   template(com_oracle_graal_compiler_CompilerThread,                 "com/oracle/graal/compiler/CompilerThread")                      \
   template(java_util_BitSet,	                                       "java/util/BitSet")                                              \
+  /* graal.graph */                                                                                                                   \
+  template(com_oracle_graal_graph_Node,                              "com/oracle/graal/graph/Node")                                   \
+  template(com_oracle_graal_graph_NodeClass,                         "com/oracle/graal/graph/NodeClass")                              \
   /* graal.hotspot */                                                                                                                 \
   template(com_oracle_graal_hotspot_HotSpotGraalRuntime,             "com/oracle/graal/hotspot/HotSpotGraalRuntime")                  \
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
@@ -315,8 +318,13 @@
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,  "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod")       \
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,  "com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType")       \
   template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")             \
+  template(com_oracle_graal_hotspot_meta_HotSpotObjectConstant,      "com/oracle/graal/hotspot/meta/HotSpotObjectConstant")           \
+  template(com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstant,   "com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstant")        \
+  template(com_oracle_graal_hotspot_HotSpotStackFrameReference,      "com/oracle/graal/hotspot/HotSpotStackFrameReference")           \
   /* graal.api.meta */                                                                                                                \
   template(com_oracle_graal_api_meta_Constant,                       "com/oracle/graal/api/meta/Constant")                            \
+  template(com_oracle_graal_api_meta_PrimitiveConstant,              "com/oracle/graal/api/meta/PrimitiveConstant")                   \
+  template(com_oracle_graal_api_meta_NullConstant,                   "com/oracle/graal/api/meta/NullConstant")                        \
   template(com_oracle_graal_api_meta_ConstantPool,                   "com/oracle/graal/api/meta/ConstantPool")                        \
   template(com_oracle_graal_api_meta_ExceptionHandler,               "com/oracle/graal/api/meta/ExceptionHandler")                    \
   template(com_oracle_graal_api_meta_JavaMethod,                     "com/oracle/graal/api/meta/JavaMethod")                          \
@@ -339,6 +347,7 @@
   template(com_oracle_graal_api_code_CompilationResult_Infopoint,    "com/oracle/graal/api/code/CompilationResult$Infopoint")         \
   template(com_oracle_graal_api_code_CompilationResult_Site,         "com/oracle/graal/api/code/CompilationResult$Site")              \
   template(com_oracle_graal_api_code_InfopointReason,                "com/oracle/graal/api/code/InfopointReason")                     \
+  template(com_oracle_graal_api_code_InstalledCode,                  "com/oracle/graal/api/code/InstalledCode")                       \
   template(com_oracle_graal_api_code_BytecodeFrame,                  "com/oracle/graal/api/code/BytecodeFrame")                       \
   template(com_oracle_graal_api_code_BytecodePosition,               "com/oracle/graal/api/code/BytecodePosition")                    \
   template(com_oracle_graal_api_code_DebugInfo,                      "com/oracle/graal/api/code/DebugInfo")                           \
@@ -352,7 +361,7 @@
   /* graal.gpu */                                                                                                                     \
   template(com_oracle_graal_gpu_ExternalCompilationResult,           "com/oracle/graal/gpu/ExternalCompilationResult")                \
   /* graal.truffle */                                                                                                                 \
-  template(com_oracle_graal_truffle_GraalTruffleRuntime,             "com/oracle/graal/truffle/GraalTruffleRuntime")                  \
+  template(com_oracle_graal_truffle_hotspot_HotSpotTruffleRuntime,   "com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime")        \
   template(startCompiler_name,                    "startCompiler")                                                                    \
   template(bootstrap_name,                        "bootstrap")                                                                        \
   template(compileTheWorld_name,                  "compileTheWorld")                                                                  \
@@ -367,7 +376,7 @@
   template(runtime_name,                          "runtime")                                                                          \
   template(runtime_signature,                     "()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;")                                 \
   template(makeInstance_name,                     "makeInstance")                                                                     \
-  template(makeInstance_signature,                "()Lcom/oracle/graal/truffle/GraalTruffleRuntime;")                                 \
+  template(makeInstance_signature,                "()Lcom/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime;")                       \
   template(initialize_name,                       "initialize")                                                                       \
   template(forObject_name,                        "forObject")                                                                        \
   template(callbackInternal_name,                 "callbackInternal")                                                                 \
--- a/src/share/vm/code/codeBlob.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/code/codeBlob.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -358,8 +358,6 @@
   int _unpack_with_exception_in_tls;
 
 #ifdef GRAAL
-  // (thomaswue) Offset when Graal calls uncommon_trap.
-  int _uncommon_trap_offset;
   int _implicit_exception_uncommon_trap_offset;
 #endif
 
@@ -417,12 +415,6 @@
   address unpack_with_exception_in_tls() const   { return code_begin() + _unpack_with_exception_in_tls; }
 
 #ifdef GRAAL
-  // (thomaswue) Offset when Graal calls uncommon_trap.
-  void set_uncommon_trap_offset(int offset) {
-    _uncommon_trap_offset = offset;
-    assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob");
-  }
-  address uncommon_trap() const                  { return code_begin() + _uncommon_trap_offset;     }
   void set_implicit_exception_uncommon_trap_offset(int offset) {
     _implicit_exception_uncommon_trap_offset = offset;
     assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob");
--- a/src/share/vm/code/compiledIC.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/code/compiledIC.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -76,7 +76,7 @@
   // Don't use ic_destination for this test since that forwards
   // through ICBuffer instead of returning the actual current state of
   // the CompiledIC.
-  if (is_icholder_entry(_ic_call->destination()) GRAAL_ONLY(&& _value != NULL)) {
+  if (is_icholder_entry(_ic_call->destination())) {
     // When patching for the ICStub case the cached value isn't
     // overwritten until the ICStub copied into the CompiledIC during
     // the next safepoint.  Make sure that the CompiledICHolder* is
@@ -107,13 +107,6 @@
   _ic_call->set_destination_mt_safe(entry_point);
 }
 
-#ifdef GRAAL
-  if (_value == NULL) {
-    // Can happen when Graal converted a virtual call into an invoke special based on static analysis.
-    return;
-  }
-#endif
-
   if (is_optimized() || is_icstub) {
     // Optimized call sites don't have a cache value and ICStub call
     // sites only change the entry point.  Changing the value in that
@@ -235,7 +228,9 @@
   bool is_monomorphic = (cb != NULL && cb->is_nmethod());
   // Check that the cached_value is a klass for non-optimized monomorphic calls
   // This assertion is invalid for compiler1: a call that does not look optimized (no static stub) can be used
-  // for calling directly to vep without using the inline cache (i.e., cached_value == NULL)
+  // for calling directly to vep without using the inline cache (i.e., cached_value == NULL).
+  // For Graal this occurs because CHA is only used to improve inlining so call sites which could be optimized
+  // virtuals because there are no currently loaded subclasses of a type are left as virtual call sites.
 #ifdef ASSERT
   CodeBlob* caller = CodeCache::find_blob_unsafe(instruction_address());
   bool is_c1_or_graal_method = caller->is_compiled_by_c1() || caller->is_compiled_by_graal();
@@ -264,14 +259,12 @@
     // Check if we are calling into our own codeblob (i.e., to a stub)
     CodeBlob* cb = CodeCache::find_blob(_ic_call->instruction_address());
     address dest = ic_destination();
-#ifndef GRAAL
 #ifdef ASSERT
     {
       CodeBlob* db = CodeCache::find_blob_unsafe(dest);
       assert(!db->is_adapter_blob(), "must use stub!");
     }
 #endif /* ASSERT */
-#endif
     is_call_to_interpreted = cb->contains(dest);
   }
   return is_call_to_interpreted;
--- a/src/share/vm/code/compiledIC.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/code/compiledIC.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -308,7 +308,7 @@
   friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site);
 
   // Code
-  static void emit_to_interp_stub(CodeBuffer &cbuf);
+  static void emit_to_interp_stub(CodeBuffer &cbuf, address mark = NULL);
   static int to_interp_stub_size();
   static int reloc_to_interp_stub();
 
--- a/src/share/vm/code/debugInfoRec.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/code/debugInfoRec.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -235,10 +235,16 @@
 
 
 int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) {
+  // It's always a space win to share and Graal generates quite a bit
+  // of scopes data so always enable the sharing logic with Graal.
+  // Presumably this is disabled in regular HotSpot because it makes
+  // recording more expensive?
+#ifndef GRAAL
   // Only pull this trick if non-safepoint recording
   // is enabled, for now.
   if (!recording_non_safepoints())
     return serialized_null;
+#endif
 
   NOT_PRODUCT(++dir_stats.chunks_queried);
   int stream_length = stream()->position() - stream_offset;
--- a/src/share/vm/code/nmethod.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/code/nmethod.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -1330,7 +1330,7 @@
   // Java wrapper is no longer alive. Here we need to clear out this weak
   // reference to the dead object.
   if (_graal_installed_code != NULL) {
-    HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0);
+    InstalledCode::set_address(_graal_installed_code, 0);
     _graal_installed_code = NULL;
   }
 #endif
@@ -1510,8 +1510,8 @@
   }
 #ifdef GRAAL
   if (_graal_installed_code != NULL) {
-    // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely.
-    HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0);
+    // Break the link between nmethod and InstalledCode such that the nmethod can subsequently be flushed safely.
+    InstalledCode::set_address(_graal_installed_code, 0);
   }
 #endif
 
@@ -1738,7 +1738,7 @@
 #ifdef GRAAL
   // Follow Graal method
   if (_graal_installed_code != NULL) {
-    if (HotSpotNmethod::isDefault(_graal_installed_code)) {
+    if (_graal_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_graal_installed_code)) {
       if (!is_alive->do_object_b(_graal_installed_code)) {
         _graal_installed_code = NULL;
       }
--- a/src/share/vm/compiler/disassembler.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/compiler/disassembler.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -522,7 +522,7 @@
   nm->method()->method_holder()->name()->print_symbol_on(env.output());
   env.output()->print(".");
   nm->method()->name()->print_symbol_on(env.output());
-  env.output()->print_cr("  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", p, end, ((jlong)(end - p)) * sizeof(unsigned char*));
+  env.output()->print_cr("  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", p, end, ((jlong)(end - p)));
 
   // If there has been profiling, print the buckets.
   if (FlatProfiler::bucket_start_for(p) != NULL) {
--- a/src/share/vm/gc_interface/collectedHeap.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/gc_interface/collectedHeap.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -84,6 +84,7 @@
 class CollectedHeap : public CHeapObj<mtInternal> {
   friend class VMStructs;
   friend class IsGCActiveMark; // Block structured external access to _is_gc_active
+  friend class Hsail;  // access to allocate_new_tlab
 
 #ifdef ASSERT
   static int       _fire_out_of_memory_count;
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 
 #include "precompiled.hpp"
+#include "code/compiledIC.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/disassembler.hpp"
 #include "runtime/javaCalls.hpp"
@@ -180,14 +181,14 @@
 
 // Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedObjectType.klass()).
 static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) {
-  char kind = Kind::typeChar(Constant::kind(constant));
-  char wordKind = 'j';
-  if (kind == wordKind) {
-    oop obj = Constant::object(constant);
-    jlong prim = Constant::primitive(constant);
-    if (obj != NULL) {
-      record_metadata_reference(obj, prim, false, oop_recorder);
-    }
+  if (constant->is_a(HotSpotMetaspaceConstant::klass())) {
+    oop obj = HotSpotMetaspaceConstant::metaspaceObject(constant);
+    jlong prim = HotSpotMetaspaceConstant::primitive(constant);
+    assert(Kind::typeChar(Constant::kind(constant)) == 'j', "must have word kind");
+    assert(obj != NULL, "must have an object");
+    assert(prim != 0, "must have a primitive value");
+
+    record_metadata_reference(obj, prim, false, oop_recorder);
   }
 }
 
@@ -263,17 +264,19 @@
     return value;
   } else if (value->is_a(Constant::klass())){
     record_metadata_in_constant(value, oop_recorder);
-    jlong prim = Constant::primitive(value);
     if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) {
+      jlong prim = PrimitiveConstant::primitive(value);
       return new ConstantIntValue(*(jint*)&prim);
     } else if (type == T_LONG || type == T_DOUBLE) {
+      jlong prim = PrimitiveConstant::primitive(value);
       second = new ConstantIntValue(0);
       return new ConstantLongValue(prim);
     } else if (type == T_OBJECT) {
-      oop obj = Constant::object(value);
-      if (obj == NULL) {
+      if (value->is_a(NullConstant::klass())) {
         return new ConstantOopWriteValue(NULL);
       } else {
+        oop obj = HotSpotObjectConstant::object(value);
+        assert(obj != NULL, "null value must be in NullConstant");
         return new ConstantOopWriteValue(JNIHandles::make_local(obj));
       }
     } else if (type == T_ADDRESS) {
@@ -452,8 +455,7 @@
 
   _code = (arrayOop) CompilationResult::targetCode(comp_result);
   _code_size = CompilationResult::targetCodeSize(comp_result);
-  // The frame size we get from the target method does not include the return address, so add one word for it here.
-  _total_frame_size = CompilationResult::frameSize(comp_result) + HeapWordSize;  // FIXME this is an x86-ism
+  _total_frame_size = CompilationResult::totalFrameSize(comp_result);
   _custom_stack_area_offset = CompilationResult::customStackAreaOffset(comp_result);
 
   // Pre-calculate the constants section size.  This is required for PC-relative addressing.
@@ -472,12 +474,35 @@
   _next_call_type = INVOKE_INVALID;
 }
 
+int CodeInstaller::estimate_stub_entries() {
+  // Estimate the number of static call stubs that might be emitted.
+  int static_call_stubs = 0;
+  for (int i = 0; i < _sites->length(); i++) {
+    oop site = ((objArrayOop) (_sites))->obj_at(i);
+    if (site->is_a(CompilationResult_Mark::klass())) {
+      oop id_obj = CompilationResult_Mark::id(site);
+      if (id_obj != NULL) {
+        assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected");
+        jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+        if (id == INVOKESTATIC || id == INVOKESPECIAL) {
+          static_call_stubs++;
+        }
+      }
+    }
+  }
+  return static_call_stubs;
+}
+
 // perform data and call relocation on the CodeBuffer
 bool CodeInstaller::initialize_buffer(CodeBuffer& buffer) {
   int locs_buffer_size = _sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
   char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size);
   buffer.insts()->initialize_shared_locs((relocInfo*)locs_buffer, locs_buffer_size / sizeof(relocInfo));
-  buffer.initialize_stubs_size(256);
+  // Allocate enough space in the stub section for the static call
+  // stubs.  Stubs have extra relocs but they are managed by the stub
+  // section itself so they don't need to be accounted for in the
+  // locs_buffer above.
+  buffer.initialize_stubs_size(estimate_stub_entries() * CompiledStaticCall::to_interp_stub_size());
   buffer.initialize_consts_size(_constants_size);
 
   _debug_recorder = new DebugInformationRecorder(_oop_recorder);
@@ -651,8 +676,11 @@
   oop hotspot_method = BytecodePosition::method(frame);
   Method* method = getMethodFromHotSpotMethod(hotspot_method);
   jint bci = BytecodePosition::bci(frame);
+  if (bci == BytecodeFrame::BEFORE_BCI()) {
+    bci = SynchronizationEntryBCI;
+  }
   bool reexecute;
-  if (bci == -1 || bci == -2){
+  if (bci == SynchronizationEntryBCI){
      reexecute = false;
   } else {
     Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci));
@@ -776,6 +804,10 @@
 
     TRACE_graal_3("method call");
     CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset);
+    if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) {
+      // Need a static call stub for transitions from compiled to interpreted.
+      CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset);
+    }
   }
 
   _next_call_type = INVOKE_INVALID;
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -102,7 +102,9 @@
   // extract the fields of the CompilationResult
   void initialize_fields(oop target_method);
   void initialize_assumptions(oop target_method);
-
+  
+  int estimate_stub_entries();
+  
   // perform data and call relocation on the CodeBuffer
   bool initialize_buffer(CodeBuffer& buffer);
 
@@ -120,7 +122,7 @@
   void record_scope(jint pc_offset, oop code_pos, GrowableArray<ScopeValue*>* objects);
 
   void process_exception_handlers();
-
+  int estimateStubSpace(int static_call_stubs);
 };
 
 /**
@@ -128,20 +130,4 @@
  */
 Method* getMethodFromHotSpotMethod(oop hotspot_method);
 
-#ifdef TARGET_ARCH_x86
-# include "graalCodeInstaller_x86.hpp"
-#endif
-#ifdef TARGET_ARCH_sparc
-# include "graalCodeInstaller_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_zero
-# error
-#endif
-#ifdef TARGET_ARCH_arm
-# error
-#endif
-#ifdef TARGET_ARCH_ppc
-# error
-#endif
-
 #endif // SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -22,6 +22,7 @@
  */
 
 #include "precompiled.hpp"
+#include "code/scopeDesc.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/generateOopMap.hpp"
 #include "oops/fieldStreams.hpp"
@@ -39,6 +40,9 @@
 #include "graal/graalVMToCompiler.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "runtime/javaCalls.hpp"
+#include "runtime/deoptimization.hpp"
+#include "runtime/vframe.hpp"
+#include "runtime/vframe_hp.hpp"
 #include "runtime/vmStructs.hpp"
 #include "runtime/gpu.hpp"
 
@@ -153,7 +157,6 @@
   //------------------------------------------------------------------------------------------------
 
   set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
-  set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap());
 
   set_address("registerFinalizerAddress", SharedRuntime::register_finalizer);
   set_address("exceptionHandlerForReturnAddressAddress", SharedRuntime::exception_handler_for_return_address);
@@ -187,6 +190,10 @@
   set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post);
   set_address("validateObject", GraalRuntime::validate_object);
 
+  set_address("deoptimizationFetchUnrollInfo", Deoptimization::fetch_unroll_info);
+  set_address("deoptimizationUncommonTrap", Deoptimization::uncommon_trap);
+  set_address("deoptimizationUnpackFrames", Deoptimization::unpack_frames);
+
   //------------------------------------------------------------------------------------------------
 
   set_int("graalCountersThreadOffset", in_bytes(JavaThread::graal_counters_offset()));
@@ -203,6 +210,7 @@
 #undef set_boolean
 #undef set_int
 #undef set_long
+#undef set_address
 
 C2V_END
 
@@ -523,15 +531,16 @@
     assert(cb == NULL, "should be");
   } else {
     if (!installed_code_handle.is_null()) {
-      assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type");
-      HotSpotInstalledCode::set_codeBlob(installed_code_handle, (jlong) cb);
+      assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
+      InstalledCode::set_address(installed_code_handle, (jlong) cb);
+      InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
       oop comp_result = HotSpotCompiledCode::comp(compiled_code_handle);
       if (comp_result->is_a(ExternalCompilationResult::klass())) {
         if (TraceGPUInteraction) {
           tty->print_cr("installCode0: ExternalCompilationResult");
         }
         HotSpotInstalledCode::set_codeStart(installed_code_handle, ExternalCompilationResult::entryPoint(comp_result));
-      } else {
+      } else if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
         HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
         HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
         HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
@@ -553,8 +562,10 @@
     stats->_standard.update(timer, processedBytecodes);
   }
   Handle installed_code_handle = JNIHandles::resolve(installed_code);
-  stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle);
-  stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle);
+  if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
+    stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle);
+    stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle);
+  }
 
   if (CITimeEach) {
     methodHandle method = asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hotspot_method));
@@ -626,7 +637,7 @@
   ResourceMark rm;
   HandleMark hm;
 
-  jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode);
+  jlong nmethodValue = InstalledCode::address(hotspotInstalledCode);
   if (nmethodValue == 0L) {
     THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
   }
@@ -717,21 +728,19 @@
 
 
 C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jobject hotspotInstalledCode))
-  jlong nativeMethod = HotSpotInstalledCode::codeBlob(hotspotInstalledCode);
+  jlong nativeMethod = InstalledCode::address(hotspotInstalledCode);
   nmethod* m = (nmethod*)nativeMethod;
   if (m != NULL && !m->is_not_entrant()) {
     m->mark_for_deoptimization();
     VM_Deoptimize op;
     VMThread::execute(&op);
   }
-  HotSpotInstalledCode::set_codeBlob(hotspotInstalledCode, 0);
+  InstalledCode::set_address(hotspotInstalledCode, 0);
 C2V_END
 
-
-C2V_VMENTRY(jobject, readUnsafeUncompressedPointer, (JNIEnv *env, jobject, jobject o, jlong offset))
-  oop resolved_o = JNIHandles::resolve(o);
-  address addr = ((address)resolved_o) + offset;
-  return JNIHandles::make_local(*((oop*)addr));
+C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv *env, jobject, jlong metaspace_klass))
+  Klass* klass = asKlass(metaspace_klass);
+  return JNIHandles::make_local(klass->java_mirror());
 C2V_END
 
 C2V_VMENTRY(jlong, readUnsafeKlassPointer, (JNIEnv *env, jobject, jobject o))
@@ -748,7 +757,7 @@
 
 C2V_ENTRY(jobject, getGPUs, (JNIEnv *env, jobject))
 #if defined(TARGET_OS_FAMILY_bsd) || defined(TARGET_OS_FAMILY_linux) || defined(TARGET_OS_FAMILY_windows)
-  return gpu::probe_gpus(env);
+  return Gpu::probe_gpus(env);
 #else
   return env->NewStringUTF("");
 #endif
@@ -772,6 +781,260 @@
   return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL;
 C2V_END
 
+C2V_VMENTRY(jlong, getTimeStamp, (JNIEnv *env, jobject))
+  // tty->time_stamp is the time since VM start which should be used
+  // for all HotSpot log output when a timestamp is required.
+  return tty->time_stamp().milliseconds();
+C2V_END
+
+bool matches(jlongArray methods, Method* method) {
+  typeArrayOop methods_oop = (typeArrayOop) JNIHandles::resolve(methods);
+
+  for (int i = 0; i < methods_oop->length(); i++) {
+    if (methods_oop->long_at(i) == (jlong) method) {
+      return true;
+    }
+  }
+  return false;
+}
+
+C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv *env, jobject compilerToVM, jobject hs_frame, jlongArray methods, jint initialSkip))
+  ResourceMark rm;
+
+  if (!thread->has_last_Java_frame()) return NULL;
+  Handle result = InstanceKlass::cast(HotSpotStackFrameReference::klass())->allocate_instance(thread);
+  HotSpotStackFrameReference::klass()->initialize(thread);
+
+  StackFrameStream fst(thread);
+  if (hs_frame != NULL) {
+    // look for the correct stack frame if one is given
+    intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
+    while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
+      fst.next();
+    }
+    if (fst.current()->sp() != stack_pointer) {
+      THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
+    }
+  }
+
+  int frame_number = 0;
+  vframe* vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+  if (hs_frame != NULL) {
+    // look for the correct vframe within the stack frame if one is given
+    int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
+    while (frame_number < last_frame_number) {
+      if (vf->is_top()) {
+        THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
+      }
+      vf = vf->sender();
+      frame_number ++;
+    }
+    // move one frame forward
+    if (vf->is_top()) {
+      if (fst.is_done()) {
+        return NULL;
+      }
+      fst.next();
+      vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+      frame_number = 0;
+    } else {
+      vf = vf->sender();
+      frame_number++;
+    }
+  }
+
+  while (true) {
+    // look for the given method
+    while (true) {
+      StackValueCollection* locals = NULL;
+      if (vf->is_compiled_frame()) {
+        // compiled method frame
+        compiledVFrame* cvf = compiledVFrame::cast(vf);
+        if (methods == NULL || matches(methods, cvf->method())) {
+          if (initialSkip > 0) {
+            initialSkip --;
+          } else {
+            GrowableArray<ScopeValue*>* objects = cvf->scope()->objects();
+            bool reallocated = false;
+            if (objects != NULL) {
+              reallocated = Deoptimization::realloc_objects(thread, fst.current(), objects, THREAD);
+              if (reallocated) {
+                Deoptimization::reassign_fields(fst.current(), fst.register_map(), objects);
+              }
+
+              GrowableArray<ScopeValue*>* local_values = cvf->scope()->locals();
+              typeArrayHandle array = oopFactory::new_boolArray(local_values->length(), thread);
+              for (int i = 0; i < local_values->length(); i++) {
+                ScopeValue* value = local_values->at(i);
+                if (value->is_object()) {
+                  array->bool_at_put(i, true);
+                }
+              }
+              HotSpotStackFrameReference::set_localIsVirtual(result, array());
+            } else {
+              HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
+            }
+
+            locals = cvf->locals();
+            HotSpotStackFrameReference::set_bci(result, cvf->bci());
+            HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) cvf->method());
+          }
+        }
+      } else if (vf->is_interpreted_frame()) {
+        // interpreted method frame
+        interpretedVFrame* ivf = interpretedVFrame::cast(vf);
+        if (methods == NULL || matches(methods, ivf->method())) {
+          if (initialSkip > 0) {
+            initialSkip --;
+          } else {
+            locals = ivf->locals();
+            HotSpotStackFrameReference::set_bci(result, ivf->bci());
+            HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) ivf->method());
+            HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
+          }
+        }
+      }
+
+      // locals != NULL means that we found a matching frame and result is already partially initialized
+      if (locals != NULL) {
+        HotSpotStackFrameReference::set_compilerToVM(result, JNIHandles::resolve(compilerToVM));
+        HotSpotStackFrameReference::set_stackPointer(result, (jlong) fst.current()->sp());
+        HotSpotStackFrameReference::set_frameNumber(result, frame_number);
+
+        // initialize the locals array
+        objArrayHandle array = oopFactory::new_objectArray(locals->size(), thread);
+        for (int i = 0; i < locals->size(); i++) {
+          StackValue* var = locals->at(i);
+          if (var->type() == T_OBJECT) {
+            array->obj_at_put(i, locals->at(i)->get_obj()());
+          }
+        }
+        HotSpotStackFrameReference::set_locals(result, array());
+
+        return JNIHandles::make_local(thread, result());
+      }
+
+      if (vf->is_top()) {
+        break;
+      }
+      frame_number++;
+      vf = vf->sender();
+    } // end of vframe loop
+
+    if (fst.is_done()) {
+      break;
+    }
+    fst.next();
+    vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+    frame_number = 0;
+  } // end of frame loop
+
+  // the end was reached without finding a matching method
+  return NULL;
+C2V_END
+
+C2V_VMENTRY(void, resolveInvokeDynamic, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index))
+  ConstantPool* cp = (ConstantPool*)metaspace_constant_pool;
+  CallInfo callInfo;
+  LinkResolver::resolve_invokedynamic(callInfo, cp, index, CHECK);
+  ConstantPoolCacheEntry* cp_cache_entry = cp->invokedynamic_cp_cache_entry_at(index);
+  cp_cache_entry->set_dynamic_call(cp, callInfo);
+C2V_END
+
+// public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
+C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv *env, jobject, jobject hs_frame, bool invalidate))
+  ResourceMark rm;
+
+  if (hs_frame == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null")
+  }
+
+  HotSpotStackFrameReference::klass()->initialize(thread);
+
+  // look for the given stack frame
+  StackFrameStream fst(thread);
+  intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
+  while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
+    fst.next();
+  }
+  if (fst.current()->sp() != stack_pointer) {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
+  }
+
+  if (invalidate) {
+    assert(fst.current()->cb()->is_nmethod(), "nmethod expected");
+    ((nmethod*) fst.current()->cb())->make_not_entrant();
+  }
+  Deoptimization::deoptimize(thread, *fst.current(), fst.register_map(), Deoptimization::Reason_none);
+
+  vframe* vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+  if (!vf->is_compiled_frame()) {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+  }
+
+  GrowableArray<compiledVFrame*>* virtualFrames = new GrowableArray<compiledVFrame*>(10);
+  while (true) {
+    assert(vf->is_compiled_frame(), "Wrong frame type");
+    virtualFrames->push(compiledVFrame::cast(vf));
+    if (vf->is_top()) {
+      break;
+    }
+    vf = vf->sender();
+  }
+
+  int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
+  if (last_frame_number >= virtualFrames->length()) {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
+  }
+
+  // Reallocate the non-escaping objects and restore their fields.
+  assert (virtualFrames->at(last_frame_number)->scope() != NULL,"invalid scope");
+  GrowableArray<ScopeValue*>* objects = virtualFrames->at(last_frame_number)->scope()->objects();
+
+  if (objects == NULL) {
+    // no objects to materialize
+    return;
+  }
+
+  bool reallocated = Deoptimization::realloc_objects(thread, fst.current(), objects, THREAD);
+  if (reallocated) {
+    Deoptimization::reassign_fields(fst.current(), fst.register_map(), objects);
+
+    for (int frame_index = 0; frame_index < virtualFrames->length(); frame_index++) {
+      compiledVFrame* cvf = virtualFrames->at(frame_index);
+
+      GrowableArray<ScopeValue*>* scopeLocals = cvf->scope()->locals();
+      StackValueCollection* locals = cvf->locals();
+
+      if (locals != NULL) {
+        for (int i2 = 0; i2 < locals->size(); i2++) {
+          StackValue* var = locals->at(i2);
+          if (var->type() == T_OBJECT && scopeLocals->at(i2)->is_object()) {
+            jvalue val;
+            val.l = (jobject) locals->at(i2)->get_obj()();
+            cvf->update_local(T_OBJECT, i2, val);
+          }
+        }
+      }
+    }
+
+    // all locals are materialized by now
+    HotSpotStackFrameReference::set_localIsVirtual(hs_frame, NULL);
+
+    // update the locals array
+    objArrayHandle array = (objArrayOop) HotSpotStackFrameReference::locals(hs_frame);
+    StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals();
+    for (int i = 0; i < locals->size(); i++) {
+      StackValue* var = locals->at(i);
+      if (var->type() == T_OBJECT) {
+        array->obj_at_put(i, locals->at(i)->get_obj()());
+      }
+    }
+  }
+C2V_END
+
+
+
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
 
@@ -784,9 +1047,12 @@
 #define CLASS                 "Ljava/lang/Class;"
 #define STACK_TRACE_ELEMENT   "Ljava/lang/StackTraceElement;"
 #define HS_RESOLVED_METHOD    "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;"
+#define RESOLVED_METHOD       "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;"
 #define HS_COMPILED_CODE      "Lcom/oracle/graal/hotspot/HotSpotCompiledCode;"
 #define HS_CONFIG             "Lcom/oracle/graal/hotspot/HotSpotVMConfig;"
-#define HS_INSTALLED_CODE     "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;"
+#define INSTALLED_CODE        "Lcom/oracle/graal/api/code/InstalledCode;"
+#define NODE_CLASS            "Lcom/oracle/graal/graph/NodeClass;"
+#define HS_STACK_FRAME_REF    "Lcom/oracle/graal/hotspot/HotSpotStackFrameReference;"
 #define METASPACE_KLASS       "J"
 #define METASPACE_METHOD      "J"
 #define METASPACE_METHOD_DATA "J"
@@ -818,30 +1084,34 @@
   {CC"lookupMethodInPool",                           CC"("METASPACE_CONSTANT_POOL"IB)"METASPACE_METHOD,                FN_PTR(lookupMethodInPool)},
   {CC"constantPoolRemapInstructionOperandFromCache", CC"("METASPACE_CONSTANT_POOL"I)I",                                FN_PTR(constantPoolRemapInstructionOperandFromCache)},
   {CC"resolveField",                                 CC"("METASPACE_CONSTANT_POOL"IB[J)"METASPACE_KLASS,               FN_PTR(resolveField)},
+  {CC"resolveInvokeDynamic",                         CC"("METASPACE_CONSTANT_POOL"I)V",                                FN_PTR(resolveInvokeDynamic)},
   {CC"resolveMethod",                                CC"("METASPACE_KLASS STRING STRING")"METASPACE_METHOD,            FN_PTR(resolveMethod)},
   {CC"getClassInitializer",                          CC"("METASPACE_KLASS")"METASPACE_METHOD,                          FN_PTR(getClassInitializer)},
   {CC"hasFinalizableSubclass",                       CC"("METASPACE_KLASS")Z",                                         FN_PTR(hasFinalizableSubclass)},
   {CC"getMaxCallTargetOffset",                       CC"(J)J",                                                         FN_PTR(getMaxCallTargetOffset)},
   {CC"getMetaspaceMethod",                           CC"("CLASS"I)"METASPACE_METHOD,                                   FN_PTR(getMetaspaceMethod)},
   {CC"initializeConfiguration",                      CC"("HS_CONFIG")V",                                               FN_PTR(initializeConfiguration)},
-  {CC"installCode0",                                 CC"("HS_COMPILED_CODE HS_INSTALLED_CODE SPECULATION_LOG")I",      FN_PTR(installCode0)},
-  {CC"notifyCompilationStatistics",                  CC"(I"HS_RESOLVED_METHOD"ZIJJ"HS_INSTALLED_CODE")V",              FN_PTR(notifyCompilationStatistics)},
+  {CC"installCode0",                                 CC"("HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I",         FN_PTR(installCode0)},
+  {CC"notifyCompilationStatistics",                  CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V",                 FN_PTR(notifyCompilationStatistics)},
   {CC"printCompilationStatistics",                   CC"(ZZ)V",                                                        FN_PTR(printCompilationStatistics)},
   {CC"resetCompilationStatistics",                   CC"()V",                                                          FN_PTR(resetCompilationStatistics)},
   {CC"disassembleCodeBlob",                          CC"(J)"STRING,                                                    FN_PTR(disassembleCodeBlob)},
-  {CC"executeCompiledMethodVarargs",                 CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT,                          FN_PTR(executeCompiledMethodVarargs)},
+  {CC"executeCompiledMethodVarargs",                 CC"(["OBJECT INSTALLED_CODE")"OBJECT,                             FN_PTR(executeCompiledMethodVarargs)},
   {CC"getLineNumberTable",                           CC"("METASPACE_METHOD")[J",                                       FN_PTR(getLineNumberTable)},
   {CC"getLocalVariableTableStart",                   CC"("METASPACE_METHOD")J",                                        FN_PTR(getLocalVariableTableStart)},
   {CC"getLocalVariableTableLength",                  CC"("METASPACE_METHOD")I",                                        FN_PTR(getLocalVariableTableLength)},
   {CC"reprofile",                                    CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
-  {CC"invalidateInstalledCode",                      CC"("HS_INSTALLED_CODE")V",                                       FN_PTR(invalidateInstalledCode)},
-  {CC"readUnsafeUncompressedPointer",                CC"("OBJECT"J)"OBJECT,                                            FN_PTR(readUnsafeUncompressedPointer)},
+  {CC"invalidateInstalledCode",                      CC"("INSTALLED_CODE")V",                                          FN_PTR(invalidateInstalledCode)},
+  {CC"getJavaMirror",                                CC"("METASPACE_KLASS")"CLASS,                                     FN_PTR(getJavaMirror)},
   {CC"readUnsafeKlassPointer",                       CC"("OBJECT")J",                                                  FN_PTR(readUnsafeKlassPointer)},
   {CC"collectCounters",                              CC"()[J",                                                         FN_PTR(collectCounters)},
   {CC"getGPUs",                                      CC"()"STRING,                                                     FN_PTR(getGPUs)},
   {CC"allocateCompileId",                            CC"("METASPACE_METHOD"I)I",                                       FN_PTR(allocateCompileId)},
   {CC"isMature",                                     CC"("METASPACE_METHOD_DATA")Z",                                   FN_PTR(isMature)},
   {CC"hasCompiledCodeForOSR",                        CC"("METASPACE_METHOD"II)Z",                                      FN_PTR(hasCompiledCodeForOSR)},
+  {CC"getTimeStamp",                                 CC"()J",                                                          FN_PTR(getTimeStamp)},
+  {CC"getNextStackFrame",                            CC"("HS_STACK_FRAME_REF "[JI)"HS_STACK_FRAME_REF,                 FN_PTR(getNextStackFrame)},
+  {CC"materializeVirtualObjects",                    CC"("HS_STACK_FRAME_REF"Z)V",                                     FN_PTR(materializeVirtualObjects)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalEnv.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/graalEnv.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -515,7 +515,7 @@
       // (Put nm into the task handle *before* publishing to the Java heap.)
       if (task != NULL)  task->set_code(nm);
 
-      if (HotSpotNmethod::isDefault(installed_code())) {
+      if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) {
         if (entry_bci == InvocationEntryBci) {
           if (TieredCompilation) {
             // If there is an old version we're done with it
--- a/src/share/vm/graal/graalGlobals.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/graalGlobals.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -88,6 +88,9 @@
   product(bool, UseHSAILDeoptimization, true,                               \
           "Code gen and runtime support for deoptimizing HSAIL kernels")    \
                                                                             \
+  product(bool, UseHSAILSafepoints, true,                                   \
+          "Code gen and runtime support for safepoints in HSAIL kernels")   \
+                                                                            \
   product(bool, GPUOffload, false,                                          \
           "Offload execution to GPU whenever possible")                     \
                                                                             \
--- a/src/share/vm/graal/graalJavaAccess.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -59,11 +59,12 @@
 #define FLOAT_FIELD(klass, name) FIELD(klass, name, "F", false)
 #define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false)
 #define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true)
+#define STATIC_INT_FIELD(klass, name) FIELD(klass, name, "I", true)
 
 
 void graal_compute_offsets() {
-  COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD)
-  guarantee(HotSpotInstalledCode::_codeBlob_offset == sizeof(oopDesc), "codeBlob must be first field!");
+  COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD)
+  guarantee(InstalledCode::_address_offset == sizeof(oopDesc), "codeBlob must be first field!");
 }
 
 #define EMPTY0
@@ -72,7 +73,7 @@
 #define FIELD2(klass, name) int klass::_##name##_offset = 0;
 #define FIELD3(klass, name, sig) FIELD2(klass, name)
 
-COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3)
+COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD2)
 
 
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -47,9 +47,9 @@
  *
  */
 
-#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field)                \
+#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field, static_int_field) \
   start_class(HotSpotResolvedObjectType)                                                                                                                       \
-    oop_field(HotSpotResolvedObjectType, javaClass, "Ljava/lang/Class;")                                                                                      \
+    oop_field(HotSpotResolvedObjectType, javaClass, "Ljava/lang/Class;")                                                                                       \
   end_class                                                                                                                                                    \
   start_class(HotSpotResolvedJavaMethod)                                                                                                                       \
     oop_field(HotSpotResolvedJavaMethod, name, "Ljava/lang/String;")                                                                                           \
@@ -59,8 +59,11 @@
   start_class(HotSpotJavaType)                                                                                                                                 \
     oop_field(HotSpotJavaType, name, "Ljava/lang/String;")                                                                                                     \
   end_class                                                                                                                                                    \
+  start_class(InstalledCode)                                                                                                                                   \
+    long_field(InstalledCode, address)                                                                                                                         \
+    long_field(InstalledCode, version)                                                                                                                         \
+  end_class                                                                                                                                                    \
   start_class(HotSpotInstalledCode)                                                                                                                            \
-    long_field(HotSpotInstalledCode, codeBlob)                                                                                                                 \
     int_field(HotSpotInstalledCode, size)                                                                                                                      \
     long_field(HotSpotInstalledCode, codeStart)                                                                                                                \
     int_field(HotSpotInstalledCode, codeSize)                                                                                                                  \
@@ -113,7 +116,7 @@
     long_field(ExternalCompilationResult, entryPoint)                                                                                                          \
   end_class                                                                                                                                                    \
   start_class(CompilationResult)                                                                                                                               \
-    int_field(CompilationResult, frameSize)                                                                                                                    \
+    int_field(CompilationResult, totalFrameSize)                                                                                                               \
     int_field(CompilationResult, customStackAreaOffset)                                                                                                        \
     oop_field(CompilationResult, targetCode, "[B")                                                                                                             \
     oop_field(CompilationResult, assumptions, "Lcom/oracle/graal/api/code/Assumptions;")                                                                       \
@@ -193,6 +196,7 @@
     int_field(BytecodeFrame, numLocks)                                                                                                                         \
     boolean_field(BytecodeFrame, rethrowException)                                                                                                             \
     boolean_field(BytecodeFrame, duringCall)                                                                                                                   \
+    static_int_field(BytecodeFrame, BEFORE_BCI)                                                                                                                \
   end_class                                                                                                                                                    \
   start_class(BytecodePosition)                                                                                                                                \
     oop_field(BytecodePosition, caller, "Lcom/oracle/graal/api/code/BytecodePosition;")                                                                        \
@@ -201,8 +205,18 @@
   end_class                                                                                                                                                    \
   start_class(Constant)                                                                                                                                        \
     oop_field(Constant, kind, "Lcom/oracle/graal/api/meta/Kind;")                                                                                              \
-    oop_field(Constant, object, "Ljava/lang/Object;")                                                                                                          \
-    long_field(Constant, primitive)                                                                                                                            \
+  end_class                                                                                                                                                    \
+  start_class(PrimitiveConstant)                                                                                                                               \
+    long_field(PrimitiveConstant, primitive)                                                                                                                   \
+  end_class                                                                                                                                                    \
+  start_class(NullConstant)                                                                                                                                    \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotObjectConstant)                                                                                                                           \
+    oop_field(HotSpotObjectConstant, object, "Ljava/lang/Object;")                                                                                             \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotMetaspaceConstant)                                                                                                                        \
+    long_field(HotSpotMetaspaceConstant, primitive)                                                                                                            \
+    oop_field(HotSpotMetaspaceConstant, metaspaceObject, "Ljava/lang/Object;")                                                                                 \
   end_class                                                                                                                                                    \
   start_class(Kind)                                                                                                                                            \
     char_field(Kind, typeChar)                                                                                                                                 \
@@ -239,7 +253,16 @@
   end_class                                                                                                                                                    \
   start_class(SpeculationLog)                                                                                                                                  \
     oop_field(SpeculationLog, lastFailed, "Ljava/lang/Object;")                                                                                                \
-  end_class
+  end_class                                                                                                                                                    \
+  start_class(HotSpotStackFrameReference)                                                                                                                      \
+    oop_field(HotSpotStackFrameReference, compilerToVM, "Lcom/oracle/graal/hotspot/bridge/CompilerToVM;")                                                      \
+    long_field(HotSpotStackFrameReference, stackPointer)                                                                                                       \
+    int_field(HotSpotStackFrameReference, frameNumber)                                                                                                         \
+    int_field(HotSpotStackFrameReference, bci)                                                                                                                 \
+    long_field(HotSpotStackFrameReference, metaspaceMethod)                                                                                                    \
+    oop_field(HotSpotStackFrameReference, locals, "[Ljava/lang/Object;")                                                                                       \
+    oop_field(HotSpotStackFrameReference, localIsVirtual, "[Z")                                                                                                \
+  end_class                                                                                                                                                    \
   /* end*/
 
 #define START_CLASS(name)                                                                                                                                      \
@@ -291,7 +314,19 @@
         oop_store((oop*)addr, x);                                                                                                                              \
       }                                                                                                                                                        \
     }
-COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD)
+#define STATIC_INT_FIELD(klassName, name)                                                                                                                      \
+    static int _##name##_offset;                                                                                                                               \
+    static int name() {                                                                                                                                        \
+      InstanceKlass* ik = InstanceKlass::cast(klassName::klass());                                                                                             \
+      address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields());                                                 \
+      return *((jint *)addr);                                                                                                                                  \
+    }                                                                                                                                                          \
+    static void set_##name(int x) {                                                                                                                            \
+      InstanceKlass* ik = InstanceKlass::cast(klassName::klass());                                                                                             \
+      address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields());                                                 \
+      *((jint *)addr) = x;                                                                                                                                     \
+    }
+COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD)
 #undef START_CLASS
 #undef END_CLASS
 #undef FIELD
@@ -302,6 +337,7 @@
 #undef FLOAT_FIELD
 #undef OOP_FIELD
 #undef STATIC_OOP_FIELD
+#undef STATIC_INT_FIELD
 
 void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field);
 
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -49,12 +49,12 @@
 }
 
 Handle VMToCompiler::truffleRuntime() {
-  Symbol* name = vmSymbols::com_oracle_graal_truffle_GraalTruffleRuntime();
+  Symbol* name = vmSymbols::com_oracle_graal_truffle_hotspot_HotSpotTruffleRuntime();
   KlassHandle klass = loadClass(name);
 
   JavaValue result(T_OBJECT);
   JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::makeInstance_signature(), Thread::current());
-  check_pending_exception("Couldn't initialize GraalTruffleRuntime");
+  check_pending_exception("Couldn't initialize HotSpotTruffleRuntime");
   return Handle((oop) result.get_jobject());
 }
 
--- a/src/share/vm/graal/vmStructs_graal.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/graal/vmStructs_graal.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -31,9 +31,10 @@
 #include "graal/graalEnv.hpp"
 
 #define VM_STRUCTS_GRAAL(nonstatic_field, static_field)                       \
-  nonstatic_field(ThreadShadow, _pending_deoptimization, int)                 \
-  nonstatic_field(ThreadShadow, _pending_failed_speculation, oop)             \
-  nonstatic_field(MethodData,   _graal_node_count, int)                       \
+  nonstatic_field(InstanceKlass, _graal_node_class, oop)                      \
+  nonstatic_field(ThreadShadow,  _pending_deoptimization, int)                \
+  nonstatic_field(ThreadShadow,  _pending_failed_speculation, oop)            \
+  nonstatic_field(MethodData,    _graal_node_count, int)                      \
 
 #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type)                   \
 
--- a/src/share/vm/oops/instanceKlass.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/oops/instanceKlass.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -288,6 +288,9 @@
   set_init_state(InstanceKlass::allocated);
   set_init_thread(NULL);
   set_reference_type(rt);
+#ifdef GRAAL
+  set_graal_node_class(NULL);
+#endif
   set_oop_map_cache(NULL);
   set_jni_ids(NULL);
   set_osr_nmethods_head(NULL);
@@ -317,6 +320,12 @@
   set_layout_helper(Klass::instance_layout_helper(0, true));
 }
 
+#ifdef GRAAL
+void InstanceKlass::oops_do(OopClosure* cl) {
+  Klass::oops_do(cl);
+  cl->do_oop(adr_graal_node_class());
+}
+#endif
 
 void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
                                        Array<Method*>* methods) {
@@ -1192,6 +1201,21 @@
     JavaValue result(T_VOID);
     JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)
   }
+
+#ifdef GRAAL
+  if (this_oop->is_subtype_of(SystemDictionary::Node_klass())) {
+    if (this_oop() != SystemDictionary::Node_klass()) {
+      // Create the NodeClass for a Node subclass.
+      TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/Class;)Lcom/oracle/graal/graph/NodeClass;", CHECK);
+      JavaValue result(T_OBJECT);
+      JavaCalls::call_static(&result, SystemDictionary::NodeClass_klass(), vmSymbols::get_name(), sig, this_oop->java_mirror(), CHECK);
+      this_oop->set_graal_node_class((oop) result.get_jobject());
+    } else {
+      // A NodeClass cannot be created for Node due to checks in
+      // NodeClass.FieldScanner.scanField()
+    }
+  }
+#endif
 }
 
 
@@ -2254,6 +2278,10 @@
   }
   init_implementor();
 
+#ifdef GRAAL
+  set_graal_node_class(NULL);
+#endif
+
   constants()->remove_unshareable_info();
 
   for (int i = 0; i < methods()->length(); i++) {
--- a/src/share/vm/oops/instanceKlass.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/oops/instanceKlass.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -241,6 +241,10 @@
   Thread*         _init_thread;          // Pointer to current thread doing initialization (to handle recusive initialization)
   int             _vtable_len;           // length of Java vtable (in words)
   int             _itable_len;           // length of Java itable (in words)
+#ifdef GRAAL
+  // com/oracle/graal/graph/NodeClass instance mirroring this class
+  oop             _graal_node_class;
+#endif
   OopMapCache*    volatile _oop_map_cache;   // OopMapCache for all methods in the klass (allocated lazily)
   MemberNameTable* _member_names;        // Member names
   JNIid*          _jni_ids;              // First JNI identifier for static fields in this class
@@ -745,6 +749,16 @@
   void call_class_initializer(TRAPS);
   void set_initialization_state_and_notify(ClassState state, TRAPS);
 
+#ifdef GRAAL
+  // Graal com.oracle.graal.graph.NodeClass mirror
+  oop graal_node_class()           { return _graal_node_class;               }
+  void set_graal_node_class(oop m) { klass_oop_store(&_graal_node_class, m); }
+  oop* adr_graal_node_class()      { return (oop*)&this->_graal_node_class;  }
+
+  // GC support
+  virtual void oops_do(OopClosure* cl);
+#endif
+
   // OopMapCache support
   OopMapCache* oop_map_cache()               { return _oop_map_cache; }
   void set_oop_map_cache(OopMapCache *cache) { _oop_map_cache = cache; }
--- a/src/share/vm/oops/klass.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/oops/klass.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -298,10 +298,6 @@
   static ByteSize modifier_flags_offset()        { return in_ByteSize(offset_of(Klass, _modifier_flags)); }
   static ByteSize layout_helper_offset()         { return in_ByteSize(offset_of(Klass, _layout_helper)); }
   static ByteSize access_flags_offset()          { return in_ByteSize(offset_of(Klass, _access_flags)); }
-#ifdef GRAAL
-  static ByteSize next_sibling_offset()          { return in_ByteSize(offset_of(Klass, _next_sibling)); }
-  static ByteSize subklass_offset()              { return in_ByteSize(offset_of(Klass, _subklass)); }
-#endif
 
   // Unpacking layout_helper:
   enum {
--- a/src/share/vm/oops/method.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/oops/method.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -216,7 +216,7 @@
 
   Thread* myThread    = Thread::current();
   methodHandle h_this(myThread, this);
-#ifdef ASSERT
+#if defined(ASSERT) && !defined(GRAAL)
   bool has_capability = myThread->is_VM_thread() ||
                         myThread->is_ConcurrentGC_thread() ||
                         myThread->is_GC_task_thread();
--- a/src/share/vm/runtime/arguments.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -35,7 +35,6 @@
 #include "prims/jvmtiExport.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/globals_extension.hpp"
-#include "runtime/gpu.hpp"
 #include "runtime/java.hpp"
 #include "services/management.hpp"
 #include "services/memTracker.hpp"
@@ -183,7 +182,11 @@
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.name", VM_Version::vm_name(),  false));
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.info", VM_Version::vm_info_string(),  true));
 #ifdef GRAAL
+#ifdef GRAAL_VERSION
   PropertyList_add(&_system_properties, new SystemProperty("graal.version", GRAAL_VERSION,  true));
+#else
+  PropertyList_add(&_system_properties, new SystemProperty("graal.version", "unknown",  true));
+#endif
 #endif
 
   // following are JVMTI agent writeable properties.
--- a/src/share/vm/runtime/arguments.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/arguments.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -264,9 +264,6 @@
   static SystemProperty *_java_home;
   static SystemProperty *_java_class_path;
   static SystemProperty *_sun_boot_class_path;
-#ifdef GRAAL
-  static SystemProperty *_graal_gpu_isalist;
-#endif
 
   // Meta-index for knowing what packages are in the boot class path
   static char* _meta_index_path;
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -357,7 +357,10 @@
     unpack_sp = deoptee.unextended_sp();
 
 #ifdef ASSERT
-  assert(cb->is_deoptimization_stub() || cb->is_uncommon_trap_stub(), "just checking");
+  assert(cb->is_deoptimization_stub() ||
+         cb->is_uncommon_trap_stub() ||
+         strcmp("Stub<DeoptimizationStub.uncommonTrapHandler>", cb->name()) == 0,
+         err_msg("unexpected code blob: %s", cb->name()));
 #endif
 #else
   intptr_t* unpack_sp = stub_frame.sender(&dummy_map).unextended_sp();
@@ -1482,7 +1485,10 @@
 #ifdef GRAAL
         oop installedCode = nm->graal_installed_code();
         if (installedCode != NULL) {
-          oop installedCodeName = HotSpotNmethod::name(installedCode);
+          oop installedCodeName = NULL;
+          if (installedCode->is_a(HotSpotNmethod::klass())) {
+            installedCodeName = HotSpotNmethod::name(installedCode);
+          }
           if (installedCodeName != NULL) {
             tty->print(" (Graal: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName));
           } else {
--- a/src/share/vm/runtime/deoptimization.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/deoptimization.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -139,6 +139,8 @@
   static void revoke_biases_of_monitors(CodeBlob* cb);
 
 #if defined(COMPILER2) || defined(GRAAL)
+GRAAL_ONLY(public:)
+
   // Support for restoring non-escaping objects
   static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
   static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
--- a/src/share/vm/runtime/gpu.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/gpu.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -26,11 +26,24 @@
 #include "runtime/gpu.hpp"
 #include "runtime/handles.hpp"
 
-int gpu::_initialized_gpus = 0;
+int  Gpu::_initialized_gpus_count = 0;
+Gpu* Gpu::_initialized_gpus[MAX_GPUS];
 
-void gpu::initialized_gpu(const char* name) {
-    _initialized_gpus++;
-    if (TraceGPUInteraction) {
-      tty->print_cr("[GPU] registered initialization of %s (total initialized: %d)", name, _initialized_gpus);
+void Gpu::initialized_gpu(Gpu* gpu) {
+  // GPUs are always initialized on the same thread so no need for locking
+  guarantee(_initialized_gpus_count < MAX_GPUS, "oob");
+  _initialized_gpus[_initialized_gpus_count++] = gpu;
+  if (TraceGPUInteraction) {
+    tty->print_cr("[GPU] registered initialization of %s (total initialized: %d)", gpu->name(), _initialized_gpus_count);
+  }
+}
+
+void Gpu::safepoint_event(SafepointEvent event) {
+  for (int i = 0; i < _initialized_gpus_count; i++) {
+    if (event == SafepointBegin) {
+      _initialized_gpus[i]->notice_safepoints();
+    } else {
+      _initialized_gpus[i]->ignore_safepoints();
     }
+  }
 }
--- a/src/share/vm/runtime/gpu.hpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/gpu.hpp	Wed Apr 23 15:48:38 2014 +0200
@@ -29,21 +29,41 @@
 #include "oops/symbol.hpp"
 #include "utilities/array.hpp"
 
+#define MAX_GPUS 2
+
 // Defines the interface to the graphics processor(s).
-class gpu : AllStatic {
+class Gpu : public CHeapObj<mtInternal> {
  private:
-  static int _initialized_gpus;  // number of initialize GPU devices
+  static int _initialized_gpus_count;
+  static Gpu* _initialized_gpus[MAX_GPUS];
 
  public:
 
   // Notification of a GPU device that has been initialized.
-  static void initialized_gpu(const char* name);
+  static void initialized_gpu(Gpu* gpu);
 
   // Gets a comma separated list of supported GPU architecture names.
   static jobject probe_gpus(JNIEnv* env);
   
   // Gets the number of GPU devices that have been initialized.
-  static int initialized_gpus() { return _initialized_gpus; }
+  static int initialized_gpus() { return _initialized_gpus_count; }
+
+  enum SafepointEvent {
+    SafepointBegin,
+    SafepointEnd
+  };
+
+  // Called when a safepoint has been activated.
+  static void safepoint_event(SafepointEvent event);
+
+  // Name of this GPU
+  virtual const char* name() = 0;
+
+  // Called when a safepoint has been activated.
+  virtual void notice_safepoints() {};
+
+  // Called when a safepoint has been deactivated.
+  virtual void ignore_safepoints() {};
 };
 
 #endif // SHARE_VM_RUNTIME_GPU_HPP
--- a/src/share/vm/runtime/javaCalls.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -412,7 +412,7 @@
     if (nm->is_alive()) {
       ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point());
       oop graalInstalledCode = nm->graal_installed_code();
-      if (graalInstalledCode != NULL && HotSpotNmethod::isExternal(graalInstalledCode)) {
+      if (graalInstalledCode != NULL && graalInstalledCode->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isExternal(graalInstalledCode)) {
         entry_point = GraalCompiler::instance()->get_external_deopt_i2c_entry();
       } else {
       entry_point = method->adapter()->get_i2c_entry();
--- a/src/share/vm/runtime/safepoint.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/safepoint.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -39,6 +39,7 @@
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"
+#include "runtime/gpu.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/osThread.hpp"
@@ -205,6 +206,12 @@
     os::make_polling_page_unreadable();
   }
 
+#ifdef GRAAL
+  if (UseHSAILSafepoints) {
+    Gpu::safepoint_event(Gpu::SafepointBegin);
+  }
+#endif
+  
   // Consider using active_processor_count() ... but that call is expensive.
   int ncpus = os::processor_count() ;
 
@@ -438,6 +445,12 @@
   // Remove safepoint check from interpreter
   Interpreter::ignore_safepoints();
 
+#ifdef GRAAL
+  if (UseHSAILSafepoints) {
+    Gpu::safepoint_event(Gpu::SafepointEnd);
+  }
+#endif
+
   {
     MutexLocker mu(Safepoint_lock);
 
--- a/src/share/vm/runtime/vmStructs.cpp	Wed Apr 23 15:22:20 2014 +0200
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Apr 23 15:48:38 2014 +0200
@@ -576,6 +576,7 @@
   nonstatic_field(ThreadLocalAllocBuffer,      _start,                                        HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _top,                                          HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _end,                                          HeapWord*)                             \
+  nonstatic_field(ThreadLocalAllocBuffer,      _pf_top,                                       HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _desired_size,                                 size_t)                                \
   nonstatic_field(ThreadLocalAllocBuffer,      _refill_waste_limit,                           size_t)                                \
      static_field(ThreadLocalAllocBuffer,      _target_refills,                               unsigned)                              \
@@ -2422,6 +2423,7 @@
   declare_constant(Method::_force_inline)                                 \
   declare_constant(Method::_dont_inline)                                  \
   declare_constant(Method::_hidden)                                       \
+  declare_constant(Method::nonvirtual_vtable_index)                       \
                                                                           \
   declare_constant(ConstMethod::_has_linenumber_table)                    \
   declare_constant(ConstMethod::_has_checked_exceptions)                  \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/baseline_whitelist.txt	Wed Apr 23 15:48:38 2014 +0200
@@ -0,0 +1,19 @@
+com.oracle.graal.jtt.loop.Loop03
+com.oracle.graal.jtt.loop.Loop04
+com.oracle.graal.jtt.loop.Loop08
+com.oracle.graal.jtt.loop.Loop11
+com.oracle.graal.jtt.bytecode.BC_iadd
+com.oracle.graal.jtt.bytecode.BC_iadd2
+com.oracle.graal.jtt.bytecode.BC_iadd3
+com.oracle.graal.jtt.bytecode.BC_ifeq_2
+com.oracle.graal.jtt.bytecode.BC_ifeq_3
+com.oracle.graal.jtt.bytecode.BC_ifeq
+com.oracle.graal.jtt.bytecode.BC_aload_3
+com.oracle.graal.jtt.bytecode.BC_aload_2
+com.oracle.graal.jtt.bytecode.BC_aload_1
+com.oracle.graal.jtt.bytecode.BC_aload_0
+com.oracle.graal.jtt.bytecode.BC_areturn
+com.oracle.graal.jtt.bytecode.BC_freturn
+com.oracle.graal.jtt.bytecode.BC_iconst
+com.oracle.graal.jtt.bytecode.BC_ireturn
+com.oracle.graal.jtt.bytecode.BC_lreturn