changeset 15399:40d0022115ee

Merge.
author Roland Schatz <roland.schatz@oracle.com>
date Mon, 28 Apr 2014 11:18:15 +0200
parents 3dde8d8c95b8 (current diff) d030e31fe082 (diff)
children 619e823d69c4
files graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResultBase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlockBase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Loop.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRTypeTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampProvider.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/VoidStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/NodeIterators.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/TreeIterators.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalLongUnitTest.java graal/com.oracle.graal.test/src/com/oracle/graal/test/LongTest.java graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/substitutions/HotSpotOptimizedCallTargetSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultCompilationPolicy.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallPath.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ASTPrinter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugContext.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugManager.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DefaultDebugManager.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/MaterializedFrameNotify.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/DefaultNodeInstrumenter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeEvents.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProxyNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodeInstrumenter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodePhylum.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/PhylumMarked.java src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp src/cpu/x86/vm/graalCodeInstaller_x86.hpp
diffstat 1129 files changed, 36241 insertions(+), 14321 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Apr 25 16:21:07 2014 +0200
+++ b/.hgignore	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/CHANGELOG.md	Mon Apr 28 11:18:15 2014 +0200
@@ -7,11 +7,18 @@
 * 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
+* Added support for stack introspection.
+* New MatchRule facility to convert multiple HIR nodes into specialized LIR
 * ...
 
 ### Truffle
-* Support for collecting stack traces and for accessing the current frame in slow paths
+* 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
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -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,7 +73,7 @@
     /**
      * 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();
@@ -93,4 +93,9 @@
      * Gets a description of the target architecture.
      */
     TargetDescription getTarget();
+
+    /**
+     * Create a new speculation log for the target runtime.
+     */
+    SpeculationLog createSpeculationLog();
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Mon Apr 28 11:18:15 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.
      */
@@ -432,22 +432,20 @@
 
         private static final long serialVersionUID = 3612943150662354844L;
         public final Object id;
-        public final Mark[] references;
 
-        public Mark(int pcOffset, Object id, Mark[] references) {
+        public Mark(int pcOffset, Object id) {
             super(pcOffset);
             this.id = id;
-            this.references = references;
         }
 
         @Override
         public String toString() {
             if (id == null) {
-                return String.format("%d[<mark with %d references>]", pcOffset, references.length);
+                return String.format("%d[<mar>]", pcOffset);
             } else if (id instanceof Integer) {
-                return String.format("%d[<mark with %d references and id %s>]", pcOffset, references.length, Integer.toHexString((Integer) id));
+                return String.format("%d[<mark with id %s>]", pcOffset, Integer.toHexString((Integer) id));
             } else {
-                return String.format("%d[<mark with %d references and id %s>]", pcOffset, references.length, id.toString());
+                return String.format("%d[<mark with id %s>]", pcOffset, id.toString());
             }
         }
     }
@@ -460,7 +458,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 +523,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 +557,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 +568,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 +579,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 +593,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 +603,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 +613,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,13 +630,12 @@
 
     /**
      * 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
      */
-    public Mark recordMark(int codePos, Object markId, Mark[] references) {
-        Mark mark = new Mark(codePos, markId, references);
+    public Mark recordMark(int codePos, Object markId) {
+        Mark mark = new Mark(codePos, markId);
         marks.add(mark);
         return mark;
     }
@@ -636,7 +644,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 +653,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 +662,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Mon Apr 28 11:18:15 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/TypeCheckHints.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java	Mon Apr 28 11:18:15 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;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,10 +30,10 @@
      * Accesses the current stack, returning a collection of {@long InspectedFrame}s that can be
      * used to inspect the stack frames' contents.
      *
-     * @param initialMethod if this is non-{@code null}, then the stack trace will start at this
-     *            method
-     * @param matchingMethod if this is non-{@code null}, then only matching stack frames are
+     * @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 initialMethod, ResolvedJavaMethod matchingMethod);
+    Iterable<InspectedFrame> getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip);
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Mon Apr 28 11:18:15 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/src/com/oracle/graal/api/meta/Constant.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Mon Apr 28 11:18:15 2014 +0200
@@ -138,7 +138,11 @@
     public abstract double asDouble();
 
     public String toValueString() {
-        return getKind().format(asBoxedPrimitive());
+        if (getKind() == Kind.Illegal) {
+            return "illegal";
+        } else {
+            return getKind().format(asBoxedPrimitive());
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Mon Apr 28 11:18:15 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/MetaUtil.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Apr 28 11:18:15 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.*;
@@ -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 '%': {
@@ -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 '%': {
@@ -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);
     }
 
--- /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	Mon Apr 28 11:18:15 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());
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java	Mon Apr 28 11:18:15 2014 +0200
@@ -104,7 +104,7 @@
             case Double:
                 return Double.valueOf(asDouble());
             default:
-                throw new IllegalArgumentException();
+                throw new IllegalArgumentException("unexpected kind " + getKind());
         }
     }
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Mon Apr 28 11:18:15 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.
      */
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Mon Apr 28 11:18:15 2014 +0200
@@ -40,12 +40,30 @@
         }
     };
 
+    /**
+     * This is the Value of a node which was matched as part of a complex match. The value isn't
+     * actually useable but this marks it as having been evaluated.
+     */
+    @SuppressWarnings("serial") public static Value INTERIOR_MATCH = new Value(Kind.Illegal) {
+
+        @Override
+        public String toString() {
+            return "INTERIOR_MATCH";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            // This class is a singleton
+            return other != null && getClass() == other.getClass();
+        }
+    };
+
     private final Kind kind;
     private final PlatformKind platformKind;
 
     /**
      * Initializes a new value of the specified kind.
-     * 
+     *
      * @param platformKind the kind
      */
     protected Value(PlatformKind platformKind) {
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Mon Apr 28 11:18:15 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.hsail.*;
 
 /**
@@ -542,10 +542,28 @@
      *
      * @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)));
+    }
+
+    /**
+     * Emits an atomic_exch_global instruction.
+     *
+     * @param result result operand that gets the original contents of the memory location
+     * @param address the memory location
+     * @param newValue the new value to write to the memory location
+     */
+    public void emitAtomicExch(Kind accessKind, AllocatableValue result, HSAILAddress address, Value newValue) {
+        emitString(String.format("atomic_exch_global_b%d   %s, %s, %s;", getArgSizeFromKind(accessKind), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(newValue)));
     }
 
     /**
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Apr 28 11:18:15 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 {
 
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXMacroAssembler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXMacroAssembler.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,16 +25,11 @@
 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 {
 
-    /**
-     * Stack bias for stack and frame pointer loads.
-     */
-    private static final int STACK_BIAS = 0x7ff;
-
     private final Register base;
     private final Register index;
     private final int displacement;
@@ -42,7 +37,7 @@
     /**
      * Creates an {@link SPARCAddress} with given base register, no scaling and a given
      * displacement.
-     * 
+     *
      * @param base the base register
      * @param displacement the displacement
      */
@@ -54,7 +49,7 @@
 
     /**
      * Creates an {@link SPARCAddress} with given base register, no scaling and a given index.
-     * 
+     *
      * @param base the base register
      * @param index the index register
      */
@@ -113,7 +108,7 @@
     /**
      * This method adds the stack-bias to the displacement if the base register is either
      * {@link SPARC#sp} or {@link SPARC#fp}.
-     * 
+     *
      * @return Optional additive displacement.
      */
     public int getDisplacement() {
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Apr 28 11:18:15 2014 +0200
@@ -37,7 +37,7 @@
 
     /**
      * Constructs an assembler for the SPARC architecture.
-     * 
+     *
      * @param registerConfig the register configuration used to bind {@link Register#Frame} and
      *            {@link Register#CallerFrame} to physical registers. This value can be null if this
      *            assembler instance will not be used to assemble instructions using these logical
@@ -50,7 +50,7 @@
     // @formatter:off
     /**
      * Instruction format for sethi.
-     * 
+     *
      * | 00  |  rd    | op2 |               imm22                     |
      * |31 30|29    25|24 22|21                                      0|
      */
@@ -123,7 +123,7 @@
     // @formatter:off
     /**
      * Instruction format for branches.
-     * 
+     *
      * | 00  |a | cond | op2 |             disp22                      |
      * |31 30|29|28  25|24 22|21                                      0|
      */
@@ -142,7 +142,7 @@
     // @formatter:off
     /**
      * Instruction format for conditional branches.
-     * 
+     *
      * | 00  |a | cond | op2 |cc1|cc0|p |             disp19           |
      * |31 30|29|28  25|24 22|21 |20 |19|                             0|
      */
@@ -330,7 +330,7 @@
     // @formatter:off
     /**
      * Instruction format for calls.
-     * 
+     *
      * | 01  |                      disp30                             |
      * |31 30|29                                                      0|
      */
@@ -457,7 +457,7 @@
     // @formatter:off
     /**
      * Instruction format for Arithmetic, Logical, Moves, Tcc, Prefetch, and Misc.
-     * 
+     *
      * | 10  |   rd   |   op3   |   rs1   | i|     imm_asi   |   rs2   |
      * | 10  |   rd   |   op3   |   rs1   | i|          simm13         |
      * | 10  |   rd   |   op3   |   rs1   | i| x|            |   rs2   |
@@ -594,7 +594,7 @@
     // @formatter:off
     /**
      * Instruction format for Loads, Stores and Misc.
-     * 
+     *
      * | 11  |   rd   |   op3   |   rs1   | i|   imm_asi   |   rs2   |
      * | 11  |   rd   |   op3   |   rs1   | i|        simm13         |
      * |31 30|29    25|24     19|18     14|13|12          5|4       0|
@@ -749,7 +749,7 @@
     // @formatter:off
     /**
      * Instruction format for Movcc.
-     * 
+     *
      * | 10  |   rd   |   op3   |cc2|   cond  | i|cc1|cc0|      -      |   rs2   |
      * | 10  |   rd   |   op3   |cc2|   cond  | i|cc1|cc0|        simm11         |
      * |31 30|29    25|24     19| 18|17     14|13| 12| 11|10          5|4       0|
@@ -1007,7 +1007,7 @@
         Wrreg(0x30, "wrreg"),
         Saved(0x31, "saved"),
 
-        Fpop1(0x34, "fpop1"),
+        Fpop1(0b11_0100, "fpop1"),
         Fpop2(0x35, "fpop2"),
         Impdep1(0x36, "impdep1"),
         Impdep2(0x37, "impdep2"),
@@ -1036,14 +1036,14 @@
         Ldx(0b001011, "ldx"),
         Stx(0b001110, "stx"),
 
-        Ldf(0x20, "ldf"),
+        Ldf(0b100000, "ldf"),
         Ldfsr(0x21, "ldfsr"),
         Ldaf(0x22, "ldaf"),
-        Lddf(0x23, "lddf"),
-        Stf(0x24, "stf"),
+        Lddf(0b100011, "lddf"),
+        Stf(0b100100, "stf"),
         Stfsr(0x25, "stfsr"),
         Staf(0x26, "staf"),
-        Stdf(0x27, "stdf");
+        Stdf(0b100111, "stdf");
 
         // @formatter:on
 
@@ -1092,9 +1092,9 @@
     public enum Opfs {
         // @formatter:off
 
-        Fmovs(0x01, "fmovs"),
-        Fmovd(0x02, "fmovd"),
-        Fmovq(0x03, "fmovq"),
+        Fmovs(0b0_0000_0001, "fmovs"),
+        Fmovd(0b0_0000_0010, "fmovd"),
+        Fmovq(0b0_0000_0011, "fmovq"),
         Fnegs(0x05, "fnegs"),
         Fnegd(0x06, "fnegd"),
         Fnegq(0x07, "fnegq"),
@@ -2376,6 +2376,20 @@
         }
     }
 
+    public static class Fmovs extends Fmt3p {
+
+        public Fmovs(Register src, Register dst) {
+            super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovs, g0, src, dst);
+        }
+    }
+
+    public static class Fmovd extends Fmt3p {
+
+        public Fmovd(Register src, Register dst) {
+            super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovd, g0, src, dst);
+        }
+    }
+
     public static class Fmuls extends Fmt3p {
 
         public Fmuls(Register src1, Register src2, Register dst) {
@@ -3174,6 +3188,20 @@
         }
     }
 
+    public static class Stdf extends Fmt11 {
+
+        public Stdf(Register dst, SPARCAddress src) {
+            super(Op3s.Stdf, src, dst);
+        }
+    }
+
+    public static class Stf extends Fmt11 {
+
+        public Stf(Register dst, SPARCAddress src) {
+            super(Op3s.Stf, src, dst);
+        }
+    }
+
     public static class Sth extends Fmt11 {
 
         public Sth(Register dst, SPARCAddress addr) {
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Apr 28 11:18:15 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,31 +32,32 @@
 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.lir.StandardOp.*;
-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;
+    protected LIRGeneratorTool gen;
     private LIRGenerationResult lirGenRes;
     private BytecodeLIRBuilder lirBuilder;
     @SuppressWarnings("unused") private BciBlock[] loopHeaders;
     private LocalLiveness liveness;
     private BciBlockBitMap blockVisited;
 
-    private class BciBlockBitMap {
+    private static class BciBlockBitMap {
         BitSet bitSet;
 
         public BciBlockBitMap(BciBlockMapping blockMap) {
@@ -74,7 +74,7 @@
     }
 
     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;
@@ -105,11 +105,11 @@
                 }
             }
 
-            if (isSynchronized(method.getModifiers())) {
+            if (method.isSynchronized()) {
                 throw GraalInternalError.unimplemented("Handle synchronized methods");
             }
 
-            frameState = new LIRFrameStateBuilder(method);
+            frameState = new BaselineFrameStateBuilder(method);
             frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true);
 
             currentBlock = blockMap.startBlock;
@@ -121,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) {
@@ -261,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
@@ -584,9 +583,9 @@
         return v;
     }
 
-    private void createTarget(BciBlock block, LIRFrameStateBuilder state) {
-        assert block != null && state != null;
-        assert !block.isExceptionEntry || state.stackSize() == 1;
+    private void createTarget(BciBlock block) {
+        assert block != null && frameState != null;
+        assert !block.isExceptionEntry || frameState.stackSize() == 1;
 
         if (!blockVisited.get(block)) {
             /*
@@ -594,7 +593,14 @@
              * placeholder that later can be replaced with a MergeNode when we see this block again.
              */
             blockVisited.set(block);
-            block.entryState = state.copy();
+            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);
@@ -602,12 +608,17 @@
         }
 
         // We already saw this block before, so we have to merge states.
-        if (!((LIRFrameStateBuilder) block.entryState).isCompatibleWith(state)) {
+        if (!((BaselineFrameStateBuilder) block.entryState).isCompatibleWith(frameState)) {
             throw new BailoutException("stacks do not match; bytecodes would not verify");
         }
 
         if (block.isLoopHeader) {
-            assert currentBlock.getId() >= block.getId() : "must be backward branch";
+            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";
@@ -619,7 +630,7 @@
          */
         if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) {
             // this is the only successor of the current block so we can adjust
-            adaptFramestate((LIRFrameStateBuilder) block.entryState);
+            adaptFramestate((BaselineFrameStateBuilder) block.entryState);
             return;
         }
         GraalInternalError.unimplemented("second block visit not yet implemented");
@@ -629,35 +640,59 @@
         Debug.log("createTarget %s: merging state", block);
     }
 
-    private void adaptValues(Value dst, Value src) {
+    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)) {
-            assert dst instanceof AllocatableValue;
-            gen.emitMove((AllocatableValue) dst, src);
+            resolver.move(dst, src);
         }
     }
 
-    private void adaptFramestate(LIRFrameStateBuilder other) {
+    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);
+            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);
+            adaptValues(dst, src, resolver);
         }
+        resolver.dispose();
     }
 
     @Override
     protected void processBlock(BciBlock block) {
-        frameState = (LIRFrameStateBuilder) block.entryState;
+        frameState = (BaselineFrameStateBuilder) block.entryState;
         setCurrentFrameState(frameState);
         currentBlock = block;
         iterateBytecodesForBlock(block);
@@ -682,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);
@@ -725,7 +768,7 @@
     }
 
     LabelRef getSuccessor(int index) {
-        createTarget(currentBlock.getSuccessor(index), frameState);
+        createTarget(currentBlock.getSuccessor(index));
         return LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, index);
     }
 
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +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, LIRFrameStateBuilder> {
-
-    private static final Value[] EMPTY_ARRAY = new Value[0];
-
-    public LIRFrameStateBuilder(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 LIRFrameStateBuilder(LIRFrameStateBuilder 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 LIRFrameStateBuilder copy() {
-        return new LIRFrameStateBuilder(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(LIRFrameStateBuilder 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;
-    }
-}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Apr 28 11:18:15 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.*;
 
 /**
@@ -264,6 +263,25 @@
         }
     }
 
+    public void emitCompareBranchMemory(Kind cmpKind, Value left, AMD64AddressValue right, LIRFrameState state, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel,
+                    double trueLabelProbability) {
+        boolean mirrored = emitCompareMemory(cmpKind, left, right, state);
+        Condition finalCondition = mirrored ? cond.mirror() : cond;
+        switch (left.getKind().getStackKind()) {
+            case Int:
+            case Long:
+            case Object:
+                append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
+                break;
+            case Float:
+            case Double:
+                append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
+        }
+    }
+
     @Override
     public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
         append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow, overflowProbability));
@@ -344,6 +362,26 @@
         }
     }
 
+    /**
+     * This method emits the compare against memory instruction, and may reorder the operands. It
+     * returns true if it did so.
+     *
+     * @param b the right operand of the comparison
+     * @return true if the left and right operands were switched, false otherwise
+     */
+    private boolean emitCompareMemory(Kind cmpKind, Value a, AMD64AddressValue b, LIRFrameState state) {
+        boolean mirrored;
+        if (LIRValueUtil.isVariable(a)) {
+            Variable left = load(a);
+            emitCompareRegMemoryOp(cmpKind, left, b, state);
+            mirrored = false;
+        } else {
+            emitCompareMemoryConOp(cmpKind, b, a, state);
+            mirrored = true;
+        }
+        return mirrored;
+    }
+
     protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Value value, LIRFrameState state) {
         assert kind.getStackKind() == value.getKind().getStackKind();
         switch (kind) {
@@ -589,8 +627,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 +641,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 +665,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 +689,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 +703,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 +800,31 @@
         }
     }
 
-    private AllocatableValue emitConvert1Op(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) {
+    public Variable emitRol(Value a, Value b) {
+        switch (a.getKind().getStackKind()) {
+            case Int:
+                return emitShift(IROL, a, b);
+            case Long:
+                return emitShift(LROL, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public Variable emitRor(Value a, Value b) {
+        switch (a.getKind().getStackKind()) {
+            case Int:
+                return emitShift(IROR, a, b);
+            case Long:
+                return emitShift(LROR, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    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 +907,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 +1077,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java	Mon Apr 28 11:18:15 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.getLIRGeneratorTool().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.getLIRGeneratorTool().emitBinaryMemory(op, getMemoryKind(access), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access));
     }
 
     /**
@@ -124,12 +128,12 @@
         AMD64AddressValue address = makeAddress(access);
         LIRFrameState state = getState(access);
         evaluateDeferred();
-        return gen.getLIRGenerator().emitConvert2MemoryOp(kind, op, address, state);
+        return gen.getLIRGeneratorTool().emitConvert2MemoryOp(kind, op, address, state);
     }
 
     @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:
@@ -248,8 +252,8 @@
 
     @Override
     public Value emitReinterpretMemory(Stamp stamp, Access access) {
-        PlatformKind to = gen.getLIRGenerator().getPlatformKind(stamp);
-        Kind from = access.accessLocation().getValueKind();
+        PlatformKind to = gen.getLIRGeneratorTool().getPlatformKind(stamp);
+        Kind from = getMemoryKind(access);
         assert to != from : "should have been eliminated";
 
         /*
@@ -355,7 +359,7 @@
     @Override
     public Value emitZeroExtendMemory(int fromBits, int toBits, Access access) {
         assert fromBits != toBits;
-        Kind memoryKind = access.accessLocation().getValueKind();
+        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
@@ -366,7 +370,7 @@
             memoryKind = Kind.Char;
         }
         evaluateDeferred();
-        return gen.getLIRGenerator().emitZeroExtendMemory(memoryKind, toBits, makeAddress(access), getState(access));
+        return gen.getLIRGeneratorTool().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()) {
@@ -459,7 +463,7 @@
                 }
             }
             ensureEvaluated(other);
-            gen.getLIRGenerator().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access));
+            gen.getLIRGeneratorTool().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access));
             mirrored = uncast(right) == access;
         } else {
             if (kind == Kind.Object) {
@@ -469,7 +473,7 @@
             }
 
             evaluateDeferred();
-            gen.getLIRGenerator().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access));
+            gen.getLIRGeneratorTool().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access));
             mirrored = uncast(left) == access;
         }
 
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,19 +23,29 @@
 
 package com.oracle.graal.compiler.amd64;
 
+import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*;
+
 import com.oracle.graal.amd64.*;
 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.gen.*;
+import com.oracle.graal.compiler.match.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
+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.spi.*;
 
 public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder {
 
-    public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) {
+    public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen) {
         super(graph, gen);
     }
 
@@ -60,7 +70,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 +83,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]);
@@ -90,6 +100,525 @@
         return false;
     }
 
+    protected LIRFrameState getState(Access access) {
+        if (access instanceof DeoptimizingNode) {
+            return state((DeoptimizingNode) access);
+        }
+        return null;
+    }
+
+    protected Kind getMemoryKind(Access access) {
+        return (Kind) gen.getPlatformKind(access.asNode().stamp());
+    }
+
+    protected AMD64AddressValue makeAddress(Access access) {
+        return (AMD64AddressValue) access.accessLocation().generateAddress(this, gen, operand(access.object()));
+    }
+
+    protected ValueNode uncast(ValueNode value) {
+        if (value instanceof UnsafeCastNode) {
+            UnsafeCastNode cast = (UnsafeCastNode) value;
+            return cast.getOriginalNode();
+        }
+        return value;
+    }
+
+    protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, Access access) {
+        Condition cond = compare.condition();
+        Kind kind = getMemoryKind(access);
+
+        if (value.isConstant()) {
+            Constant constant = value.asConstant();
+            if (kind == Kind.Long && !NumUtil.isInt(constant.asLong())) {
+                // Only imm32 as long
+                return null;
+            }
+            if (kind.isNumericFloat()) {
+                Debug.log("Skipping constant compares for float kinds");
+                return null;
+            }
+            if (kind == Kind.Object) {
+                if (!constant.isNull()) {
+                    Debug.log("Skipping constant compares for Object kinds");
+                    return null;
+                }
+            }
+        } else {
+            if (kind == Kind.Object) {
+                // Can't compare against objects since they require encode/decode
+                Debug.log("Skipping compares for Object kinds");
+                return null;
+            }
+        }
+
+        PlatformKind cmpKind = gen.getPlatformKind(compare.x().stamp());
+        if (cmpKind instanceof Kind) {
+            // emitCompareBranchMemory expects the memory on the right, so mirror the condition if
+            // that's not true. It might be mirrored again the actual compare is emitted but that's
+            // ok.
+            Condition finalCondition = uncast(compare.x()) == access ? cond.mirror() : cond;
+            return new ComplexMatchResult() {
+                public Value evaluate(NodeLIRBuilder builder) {
+                    LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor());
+                    LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor());
+                    boolean unorderedIsTrue = compare.unorderedIsTrue();
+                    double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor());
+                    Value other;
+                    if (value.isConstant()) {
+                        other = value.asConstant();
+                    } else {
+                        other = operand(value);
+                    }
+
+                    getLIRGeneratorTool().emitCompareBranchMemory((Kind) cmpKind, other, makeAddress(access), getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel,
+                                    trueLabelProbability);
+                    return null;
+                }
+            };
+        }
+        return null;
+
+    }
+
+    private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, Access access) {
+        LabelRef trueLabel = getLIRBlock(x.trueSuccessor());
+        LabelRef falseLabel = getLIRBlock(x.falseSuccessor());
+        double trueLabelProbability = x.probability(x.trueSuccessor());
+        Kind kind = getMemoryKind(access);
+        if (value.isConstant()) {
+            if (kind != kind.getStackKind()) {
+                return null;
+            }
+            Constant constant = value.asConstant();
+            if (kind == Kind.Long && !NumUtil.isInt(constant.asLong())) {
+                // Only imm32 as long
+                return null;
+            }
+            return new ComplexMatchResult() {
+                public Value evaluate(NodeLIRBuilder builder) {
+                    gen.append(new AMD64TestMemoryOp(kind, makeAddress(access), constant, getState(access)));
+                    gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability));
+                    return null;
+                }
+            };
+        } else {
+            return new ComplexMatchResult() {
+                public Value evaluate(NodeLIRBuilder builder) {
+                    gen.append(new AMD64TestMemoryOp(kind, makeAddress(access), operand(value), getState(access)));
+                    gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability));
+                    return null;
+                }
+            };
+        }
+    }
+
+    protected Value emitConvert2MemoryOp(PlatformKind kind, AMD64Arithmetic op, Access access) {
+        AMD64AddressValue address = makeAddress(access);
+        LIRFrameState state = getState(access);
+        return getLIRGeneratorTool().emitConvert2MemoryOp(kind, op, address, state);
+    }
+
+    private Value emitFloatConvertMemory(FloatConvertNode op, Access access) {
+        switch (op.getOp()) {
+            case D2F:
+                return emitConvert2MemoryOp(Kind.Float, D2F, access);
+            case D2I:
+                return emitConvert2MemoryOp(Kind.Int, D2I, access);
+            case D2L:
+                return emitConvert2MemoryOp(Kind.Long, D2L, access);
+            case F2D:
+                return emitConvert2MemoryOp(Kind.Double, F2D, access);
+            case F2I:
+                return emitConvert2MemoryOp(Kind.Int, F2I, access);
+            case F2L:
+                return emitConvert2MemoryOp(Kind.Long, F2L, access);
+            case I2D:
+                return emitConvert2MemoryOp(Kind.Double, I2D, access);
+            case I2F:
+                return emitConvert2MemoryOp(Kind.Float, I2F, access);
+            case L2D:
+                return emitConvert2MemoryOp(Kind.Double, L2D, access);
+            case L2F:
+                return emitConvert2MemoryOp(Kind.Float, L2F, access);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) {
+        assert fromBits <= toBits && toBits <= 64;
+        Kind kind = null;
+        AMD64Arithmetic op = null;
+        if (fromBits == toBits) {
+            return null;
+        } else if (toBits > 32) {
+            kind = Kind.Long;
+            // sign extend to 64 bits
+            switch (fromBits) {
+                case 8:
+                    op = B2L;
+                    break;
+                case 16:
+                    op = S2L;
+                    break;
+                case 32:
+                    op = I2L;
+                    break;
+                default:
+                    throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
+            }
+        } else {
+            kind = Kind.Int;
+            // sign extend to 32 bits (smaller values are internally represented as 32 bit values)
+            switch (fromBits) {
+                case 8:
+                    op = B2I;
+                    break;
+                case 16:
+                    op = S2I;
+                    break;
+                case 32:
+                    return null;
+                default:
+                    throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
+            }
+        }
+        if (kind != null && op != null) {
+            Kind localKind = kind;
+            AMD64Arithmetic localOp = op;
+            return new ComplexMatchResult() {
+                public Value evaluate(NodeLIRBuilder builder) {
+                    return emitConvert2MemoryOp(localKind, localOp, access);
+                }
+            };
+        }
+        return null;
+    }
+
+    private Value emitReinterpretMemory(PlatformKind to, Access access) {
+        Kind from = getMemoryKind(access);
+        assert to != from : "should have been eliminated";
+
+        /*
+         * Conversions between integer to floating point types require moves between CPU and FPU
+         * registers.
+         */
+        switch ((Kind) to) {
+            case Int:
+                switch (from) {
+                    case Float:
+                        return emitConvert2MemoryOp(to, MOV_F2I, access);
+                }
+                break;
+            case Long:
+                switch (from) {
+                    case Double:
+                        return emitConvert2MemoryOp(to, MOV_D2L, access);
+                }
+                break;
+            case Float:
+                switch (from) {
+                    case Int:
+                        return emitConvert2MemoryOp(to, MOV_I2F, access);
+                }
+                break;
+            case Double:
+                switch (from) {
+                    case Long:
+                        return emitConvert2MemoryOp(to, MOV_L2D, access);
+                }
+                break;
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    static Object lock = new Object();
+
+    private AMD64Arithmetic getOp(ValueNode operation, Access access) {
+        Kind memoryKind = getMemoryKind(access);
+        if (operation.getClass() == IntegerAddNode.class) {
+            switch (memoryKind) {
+                case Int:
+                    return IADD;
+                case Long:
+                    return LADD;
+            }
+        } else if (operation.getClass() == FloatAddNode.class) {
+            switch (memoryKind) {
+                case Float:
+                    return FADD;
+                case Double:
+                    return DADD;
+            }
+        } else if (operation.getClass() == AndNode.class) {
+            switch (memoryKind) {
+                case Int:
+                    return IAND;
+                case Long:
+                    return LAND;
+            }
+        } else if (operation.getClass() == OrNode.class) {
+            switch (memoryKind) {
+                case Int:
+                    return IOR;
+                case Long:
+                    return LOR;
+            }
+        } else if (operation.getClass() == XorNode.class) {
+            switch (memoryKind) {
+                case Int:
+                    return IXOR;
+                case Long:
+                    return LXOR;
+            }
+        } else if (operation.getClass() == IntegerSubNode.class) {
+            switch (memoryKind) {
+                case Int:
+                    return ISUB;
+                case Long:
+                    return LSUB;
+            }
+        } else if (operation.getClass() == FloatSubNode.class) {
+            switch (memoryKind) {
+                case Float:
+                    return FSUB;
+                case Double:
+                    return DSUB;
+            }
+        } else if (operation.getClass() == IntegerMulNode.class) {
+            switch (memoryKind) {
+                case Int:
+                    return IMUL;
+                case Long:
+                    return LMUL;
+            }
+        } else if (operation.getClass() == FloatMulNode.class) {
+            switch (memoryKind) {
+                case Float:
+                    return FMUL;
+                case Double:
+                    return DMUL;
+            }
+        }
+        return null;
+    }
+
+    @MatchRule("(If (IntegerTest=compare Read=access value))")
+    @MatchRule("(If (IntegerTest=compare FloatingRead=access value))")
+    public static class IfIntegerTest extends AMD64MatchGenerator {
+        IfNode root;
+        Access access;
+        ValueNode value;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            return gen.emitIntegerTestBranchMemory(root, value, access);
+        }
+    }
+
+    @MatchRule("(If (IntegerEquals=compare value Read=access))")
+    @MatchRule("(If (IntegerLessThan=compare value Read=access))")
+    @MatchRule("(If (IntegerBelowThan=compare value Read=access))")
+    @MatchRule("(If (IntegerEquals=compare value FloatingRead=access))")
+    @MatchRule("(If (IntegerLessThan=compare value FloatingRead=access))")
+    @MatchRule("(If (IntegerBelowThan=compare value FloatingRead=access))")
+    @MatchRule("(If (FloatEquals=compare value Read=access))")
+    @MatchRule("(If (FloatEquals=compare value FloatingRead=access))")
+    @MatchRule("(If (FloatLessThan=compare value Read=access))")
+    @MatchRule("(If (FloatLessThan=compare value FloatingRead=access))")
+    public static class IfCompareMemory extends AMD64MatchGenerator {
+        IfNode root;
+        Access access;
+        ValueNode value;
+        CompareNode compare;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            return gen.emitCompareBranchMemory(root, compare, value, access);
+        }
+    }
+
+    @MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))")
+    public static class RotateLeftConstant extends AMD64MatchGenerator {
+        LeftShiftNode lshift;
+        UnsignedRightShiftNode rshift;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            if ((lshift.getShiftAmountMask() & (lshift.y().asConstant().asInt() + rshift.y().asConstant().asInt())) == 0) {
+                return builder -> gen.getLIRGeneratorTool().emitRol(gen.operand(lshift.x()), gen.operand(lshift.y()));
+            }
+            return null;
+        }
+
+    }
+
+    @MatchRule("(Or (LeftShift=lshift value (IntegerSub Constant=delta shiftAmount)) (UnsignedRightShift value shiftAmount))")
+    public static class RotateRightVariable extends AMD64MatchGenerator {
+        ValueNode value;
+        ValueNode shiftAmount;
+        ConstantNode delta;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            if (delta.asConstant().asLong() == 0 || delta.asConstant().asLong() == 32) {
+                return builder -> gen.getLIRGeneratorTool().emitRor(gen.operand(value), gen.operand(shiftAmount));
+            }
+            return null;
+        }
+
+    }
+
+    @MatchRule("(Or (LeftShift value shiftAmount) (UnsignedRightShift value (IntegerSub Constant=delta shiftAmount)))")
+    public static class RotateLeftVariable extends AMD64MatchGenerator {
+        ValueNode value;
+        ValueNode shiftAmount;
+        ConstantNode delta;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            if (delta.asConstant().asLong() == 0 || delta.asConstant().asLong() == 32) {
+                return builder -> gen.getLIRGeneratorTool().emitRol(gen.operand(value), gen.operand(shiftAmount));
+            }
+            return null;
+        }
+    }
+
+    @MatchRule("(IntegerAdd value Read=access)")
+    @MatchRule("(IntegerSub value Read=access)")
+    @MatchRule("(IntegerMul value Read=access)")
+    @MatchRule("(FloatAdd value Read=access)")
+    @MatchRule("(FloatSub value Read=access)")
+    @MatchRule("(FloatMul value Read=access)")
+    @MatchRule("(Or value Read=access)")
+    @MatchRule("(Xor value Read=access)")
+    @MatchRule("(And value Read=access)")
+    @MatchRule("(IntegerAdd value FloatingRead=access)")
+    @MatchRule("(IntegerSub value FloatingRead=access)")
+    @MatchRule("(IntegerMul value FloatingRead=access)")
+    @MatchRule("(FloatAdd value FloatingRead=access)")
+    @MatchRule("(FloatSub value FloatingRead=access)")
+    @MatchRule("(FloatMul value FloatingRead=access)")
+    @MatchRule("(Or value FloatingRead=access)")
+    @MatchRule("(Xor value FloatingRead=access)")
+    @MatchRule("(And value FloatingRead=access)")
+    public static class BinaryRead extends AMD64MatchGenerator {
+        BinaryNode root;
+        Access access;
+        ValueNode value;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            AMD64Arithmetic op = gen.getOp(root, access);
+            if (op != null) {
+                return builder -> gen.getLIRGeneratorTool().emitBinaryMemory(op, gen.getMemoryKind(access), gen.getLIRGeneratorTool().asAllocatable(gen.operand(value)), gen.makeAddress(access),
+                                gen.getState(access));
+            }
+            return null;
+        }
+    }
+
+    @MatchRule("(Write Narrow=narrow value)")
+    public static class WriteNarrow extends AMD64MatchGenerator {
+        WriteNode root;
+        NarrowNode narrow;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            return new ComplexMatchResult() {
+                @Override
+                public Value evaluate(NodeLIRBuilder builder) {
+                    PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(root.value().stamp());
+                    Value address = root.location().generateAddress(builder, gen.getLIRGeneratorTool(), gen.operand(root.object()));
+                    Value v = gen.operand(narrow.getInput());
+                    gen.getLIRGeneratorTool().emitStore(writeKind, address, v, gen.state(root));
+                    return null;
+                }
+            };
+        }
+    }
+
+    @MatchRule("(SignExtend Read=access)")
+    @MatchRule("(SignExtend FloatingRead=access)")
+    public static class SignExtend extends AMD64MatchGenerator {
+        Access access;
+        SignExtendNode root;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            return gen.emitSignExtendMemory(access, root.getInputBits(), root.getResultBits());
+        }
+    }
+
+    static abstract class AMD64MatchGenerator implements MatchGenerator {
+        public AMD64MatchGenerator() {
+        }
+
+        public ComplexMatchResult match(NodeLIRBuilder gen) {
+            return match((AMD64NodeLIRBuilder) gen);
+        }
+
+        abstract public ComplexMatchResult match(AMD64NodeLIRBuilder gen);
+    }
+
+    @MatchRule("(ZeroExtend Read=access)")
+    @MatchRule("(ZeroExtend FloatingRead=access)")
+    public static class ZeroExtend extends AMD64MatchGenerator {
+        Access access;
+        ZeroExtendNode root;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            Kind memoryKind = gen.getMemoryKind(access);
+            if (memoryKind.getBitCount() != root.getInputBits() && !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.
+                 */
+                return null;
+            }
+            return new ComplexMatchResult() {
+                public Value evaluate(NodeLIRBuilder unused) {
+                    return gen.getLIRGeneratorTool().emitZeroExtendMemory(memoryKind == Kind.Short ? Kind.Char : memoryKind, root.getResultBits(), gen.makeAddress(access), gen.getState(access));
+                }
+            };
+        }
+    }
+
+    @MatchRule("(FloatConvert Read=access)")
+    @MatchRule("(FloatConvert FloatingRead=access)")
+    public static class FloatConvert extends AMD64MatchGenerator {
+        Access access;
+        FloatConvertNode root;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            return new ComplexMatchResult() {
+                public Value evaluate(NodeLIRBuilder builder) {
+                    return gen.emitFloatConvertMemory(root, access);
+                }
+            };
+        }
+    }
+
+    @MatchRule("(Reinterpret Read=access)")
+    @MatchRule("(Reinterpret FloatingRead=access)")
+    public static class Reinterpret extends AMD64MatchGenerator {
+        Access access;
+        ReinterpretNode root;
+
+        @Override
+        public ComplexMatchResult match(AMD64NodeLIRBuilder gen) {
+            return new ComplexMatchResult() {
+                public Value evaluate(NodeLIRBuilder builder) {
+                    PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(root.stamp());
+                    return gen.emitReinterpretMemory(kind, access);
+                }
+            };
+        }
+    }
+
     @Override
     public void visitBreakpointNode(BreakpointNode node) {
         JavaType[] sig = new JavaType[node.arguments().size()];
@@ -103,11 +632,11 @@
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        append(new InfopointOp(gen.stateFor(i.getState()), i.reason));
+        append(new InfopointOp(stateFor(i.getState()), i.reason));
     }
 
     @Override
-    public AMD64LIRGenerator getLIRGenerator() {
+    public AMD64LIRGenerator getLIRGeneratorTool() {
         return (AMD64LIRGenerator) gen;
     }
 }
--- /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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,287 @@
+/*
+ * 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> FlowSensitiveReduction = new OptionValue<>(false);
+    @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<>(false);
+    @Option(help = "Allow backend to match complex expressions.")
+    public static final OptionValue<Boolean> MatchExpressions = 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Mon Apr 28 11:18:15 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.
      */
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java	Mon Apr 28 11:18:15 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/AtomicIntGetAndAddTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,13 +27,10 @@
 
 import org.junit.*;
 
-import sun.misc.*;
-
 import com.oracle.graal.compiler.hsail.test.infra.*;
 
 /**
- * Tests {@link AtomicInteger#getAndAdd(int)} which indirectly tests
- * {@link Unsafe#compareAndSwapInt(Object, long, int, int)}.
+ * Tests {@link AtomicInteger#getAndAdd(int)} which tests HSAIL atomic_add codegen.
  */
 public class AtomicIntGetAndAddTest extends GraalKernelTester {
 
--- /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/AtomicIntGetAndSetTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests {@link AtomicInteger#getAndSet(int)} which tests HSAIL atomic_exch codegen.
+ */
+public class AtomicIntGetAndSetTest extends GraalKernelTester {
+
+    static final int NUM = 1000;
+    @Result public int[] outArray = new int[NUM];
+    AtomicInteger atomicInt = new AtomicInteger(Integer.MAX_VALUE);
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchMethodKernel(NUM);
+        // to complete the circle, replace the initial get value with that of the last executor
+        for (int i = 0; i < NUM; i++) {
+            if (outArray[i] == Integer.MAX_VALUE) {
+                outArray[i] = atomicInt.get();
+            }
+        }
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    public void run(int gid) {
+        outArray[gid] = atomicInt.getAndSet(gid);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,13 +27,10 @@
 
 import org.junit.*;
 
-import sun.misc.*;
-
 import com.oracle.graal.compiler.hsail.test.infra.*;
 
 /**
- * Tests {@link AtomicLong#getAndAdd(long)} which indirectly tests
- * {@link Unsafe#compareAndSwapLong(Object, long, long, long)}.
+ * Tests {@link AtomicLong#getAndAdd(long)} which tests HSAIL atomic_add codegen.
  */
 public class AtomicLongGetAndAddTest extends GraalKernelTester {
 
--- /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/AtomicLongGetAndSetTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests {@link AtomicLong#getAndSet(long)} which tests HSAIL atomic_exch codegen.
+ */
+public class AtomicLongGetAndSetTest extends GraalKernelTester {
+
+    static final int NUM = 1000;
+    @Result public long[] outArray = new long[NUM];
+    AtomicLong atomicLong = new AtomicLong(Long.MAX_VALUE);
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchMethodKernel(NUM);
+        // to complete the circle, replace the initial get value with that of the last executor
+        for (int i = 0; i < NUM; i++) {
+            if (outArray[i] == Long.MAX_VALUE) {
+                outArray[i] = atomicLong.get();
+            }
+        }
+
+        // note: the actual order of entries in outArray is not predictable
+        // thus we sort before we compare results
+        Arrays.sort(outArray);
+    }
+
+    public void run(int gid) {
+        outArray[gid] = atomicLong.getAndSet(gid);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BoundsCatchBase.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/SingleExceptionTestBase.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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/StaticDoubleSpillTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -118,9 +118,8 @@
         dispatchMethodKernel(size, out, in);
     }
 
-    // Marked to only run on hardware until simulator spill bug is fixed.
-    @Ignore
     @Test
+    @Ignore("until stack slots are supported in deopt")
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -87,9 +87,8 @@
         dispatchMethodKernel(size, out, in);
     }
 
-    // Marked to only run on hardware until simulator spill bug is fixed.
-    @Ignore
     @Test
+    @Ignore("until stack slots are supported in deopt")
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelBoundsCheckTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelBoundsCheckTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMethod16InArraysTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyCallTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsAcceptTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringSwitchTest.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Apr 28 11:18:15 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.*;
 
 /**
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,20 +24,20 @@
 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.
  */
 public abstract class HSAILNodeLIRBuilder extends NodeLIRBuilder {
 
-    public HSAILNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) {
+    public HSAILNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         super(graph, lirGen);
     }
 
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Mon Apr 28 11:18:15 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/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Apr 28 11:18:15 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
@@ -909,6 +891,7 @@
     }
 
     public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitCompareAndSwap()");
+        throw GraalInternalError.unimplemented();
     }
+
 }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,10 +27,11 @@
 
 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.*;
 
@@ -55,7 +56,7 @@
         }
     }
 
-    public PTXNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) {
+    public PTXNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         super(graph, lirGen);
     }
 
@@ -135,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,40 +27,21 @@
 import static com.oracle.graal.lir.sparc.SPARCArithmetic.*;
 import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.sparc.SPARCCompare.*;
+import static com.oracle.graal.lir.sparc.SPARCControlFlow.*;
 import static com.oracle.graal.lir.sparc.SPARCMathIntrinsicOp.IntrinsicOpcode.*;
+import static com.oracle.graal.lir.sparc.SPARCMove.*;
 
 import com.oracle.graal.api.code.*;
 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;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegReg;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.Op1Stack;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Stack;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary2Op;
-import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.CondMoveOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.FloatCondMoveOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.StrategySwitchOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp;
-import com.oracle.graal.lir.sparc.SPARCMove.LoadAddressOp;
-import com.oracle.graal.lir.sparc.SPARCMove.MembarOp;
-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.*;
 
 /**
@@ -131,7 +112,7 @@
 
     @Override
     public void emitData(AllocatableValue dst, byte[] data) {
-        throw GraalInternalError.unimplemented();
+        append(new LoadDataAddressOp(dst, data));
     }
 
     @Override
@@ -158,7 +139,7 @@
                 indexRegister = Value.ILLEGAL;
             } else {
                 if (scale != 1) {
-                    Value longIndex = emitSignExtend(index, 32, 64);
+                    Value longIndex = index.getKind() == Kind.Long ? index : emitSignExtend(index, 32, 64);
                     if (CodeUtil.isPowerOf2(scale)) {
                         indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale)));
                     } else {
@@ -186,16 +167,20 @@
         // If we don't have an index register we can use a displacement, otherwise load the
         // displacement into a register and add it to the base.
         if (indexRegister.equals(Value.ILLEGAL)) {
-            // TODO What if displacement if too big?
             displacementInt = (int) finalDisp;
+            assert SPARCAssembler.isSimm13(displacementInt) : displacementInt;
         } else {
             displacementInt = 0;
             if (baseRegister.equals(Value.ILLEGAL)) {
                 baseRegister = load(Constant.forLong(finalDisp));
             } else {
-                Variable longBaseRegister = newVariable(Kind.Long);
-                emitMove(longBaseRegister, baseRegister);  // FIXME get rid of this move
-                baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp));
+                if (finalDisp == 0) {
+                    // Nothing to do. Just use the base register.
+                } else {
+                    Variable longBaseRegister = newVariable(Kind.Long);
+                    emitMove(longBaseRegister, baseRegister);
+                    baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp));
+                }
             }
         }
 
@@ -284,15 +269,16 @@
         Condition finalCondition = mirrored ? cond.mirror() : cond;
 
         Variable result = newVariable(trueValue.getKind());
-        switch (left.getKind().getStackKind()) {
+        Kind kind = left.getKind().getStackKind();
+        switch (kind) {
             case Int:
             case Long:
             case Object:
-                append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
+                append(new CondMoveOp(kind, result, finalCondition, load(trueValue), loadNonConst(falseValue)));
                 break;
             case Float:
             case Double:
-                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
+                append(new FloatCondMoveOp(kind, result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -347,7 +333,8 @@
     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)));
+        Kind kind = left.getKind().getStackKind();
+        append(new CondMoveOp(kind, result, Condition.EQ, load(trueValue), loadNonConst(falseValue)));
         return result;
     }
 
@@ -362,7 +349,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 +580,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 +602,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 +618,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 +633,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:
@@ -814,22 +800,23 @@
             return inputVal;
         } else if (toBits > 32) {
             // sign extend to 64 bits
-            if (fromBits == 32) {
-                return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal));
-            } else if (fromBits < 32) {
-                // TODO implement direct x2L sign extension conversions
-                Value intVal = emitSignExtend(inputVal, fromBits, 32);
-                return emitSignExtend(intVal, 32, toBits);
-            } else {
-                throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
+            switch (fromBits) {
+                case 8:
+                    return emitConvert2Op(Kind.Long, B2L, asAllocatable(inputVal));
+                case 16:
+                    return emitConvert2Op(Kind.Long, S2L, asAllocatable(inputVal));
+                case 32:
+                    return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal));
+                default:
+                    throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
             }
         } else {
             // sign extend to 32 bits (smaller values are internally represented as 32 bit values)
             switch (fromBits) {
                 case 8:
-                    return emitConvert2Op(Kind.Int, I2B, asAllocatable(inputVal));
+                    return emitConvert2Op(Kind.Int, B2I, asAllocatable(inputVal));
                 case 16:
-                    return emitConvert2Op(Kind.Int, I2S, asAllocatable(inputVal));
+                    return emitConvert2Op(Kind.Int, S2I, asAllocatable(inputVal));
                 case 32:
                     return inputVal;
                 default:
@@ -917,7 +904,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,7 +25,9 @@
 
 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.*;
@@ -35,7 +37,7 @@
  */
 public abstract class SPARCNodeLIRBuilder extends NodeLIRBuilder {
 
-    public SPARCNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) {
+    public SPARCNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         super(graph, lirGen);
     }
 
@@ -59,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Mon Apr 28 11:18:15 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,13 +43,14 @@
 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
     public void test() {
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java	Mon Apr 28 11:18:15 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/ConditionalEliminationTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,23 +22,16 @@
  */
 package com.oracle.graal.compiler.test;
 
-import static com.oracle.graal.nodes.ConstantNode.*;
-import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
-import static org.junit.Assert.*;
-
 import org.junit.*;
 
 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;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
 /**
- * Collection of tests for {@link ConditionalEliminationPhase} including those that triggered bugs
- * in this phase.
+ * Collection of tests for {@link com.oracle.graal.phases.common.ConditionalEliminationPhase}
+ * including those that triggered bugs in this phase.
  */
 public class ConditionalEliminationTest extends GraalCompilerTest {
 
@@ -88,174 +81,6 @@
         } while (true);
     }
 
-    /**
-     * This test presents a code pattern that triggered a bug where a (non-eliminated) checkcast
-     * caused an enclosing instanceof (for the same object and target type) to be incorrectly
-     * eliminated.
-     */
-    @Test
-    public void testReanchoringIssue() {
-        Entry end = new Entry("end");
-        EntryWithNext e1 = new EntryWithNext("e1", end);
-        EntryWithNext e2 = new EntryWithNext("e2", e1);
-
-        test("search", e2, "e3", new Entry("e4"));
-    }
-
-    @SuppressWarnings("unused")
-    public static int testNullnessSnippet(Object a, Object b) {
-        if (a == null) {
-            if (a == b) {
-                if (b == null) {
-                    return 1;
-                } else {
-                    return -2;
-                }
-            } else {
-                if (b == null) {
-                    return -3;
-                } else {
-                    return 4;
-                }
-            }
-        } else {
-            if (a == b) {
-                if (b == null) {
-                    return -5;
-                } else {
-                    return 6;
-                }
-            } else {
-                if (b == null) {
-                    return 7;
-                } else {
-                    return 8;
-                }
-            }
-        }
-    }
-
-    @Test
-    public void testNullness() {
-        test("testNullnessSnippet", null, null);
-        test("testNullnessSnippet", null, new Object());
-        test("testNullnessSnippet", new Object(), null);
-        test("testNullnessSnippet", new Object(), new Object());
-
-        StructuredGraph graph = parse("testNullnessSnippet");
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        for (ConstantNode constant : getConstantNodes(graph)) {
-            if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) {
-                assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
-            }
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public static int testDisjunctionSnippet(Object a) {
-        try {
-            if (a instanceof Integer) {
-                if (a == null) {
-                    return -1;
-                } else {
-                    return 2;
-                }
-            } else {
-                return 3;
-            }
-        } finally {
-            field = null;
-        }
-    }
-
-    @Test
-    public void testDisjunction() {
-        StructuredGraph graph = parse("testDisjunctionSnippet");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        IfNode ifNode = (IfNode) graph.start().next();
-        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
-        IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0)));
-        InstanceOfNode y = instanceOf;
-        ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY));
-        LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction));
-        ifNode.setCondition(negation);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        for (ConstantNode constant : getConstantNodes(graph)) {
-            if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) {
-                assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
-            }
-        }
-    }
-
-    public static int testInvokeSnippet(Number n) {
-        if (n instanceof Integer) {
-            return n.intValue();
-        } else {
-            return 1;
-        }
-    }
-
-    @Test
-    public void testInvoke() {
-        test("testInvokeSnippet", new Integer(16));
-        StructuredGraph graph = parse("testInvokeSnippet");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
-
-        InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first();
-        assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind());
-    }
-
-    public static void testTypeMergingSnippet(Object o, boolean b) {
-        if (b) {
-            if (!(o instanceof Double)) {
-                return;
-            }
-        } else {
-            if (!(o instanceof Integer)) {
-                return;
-            }
-        }
-
-        /*
-         * For this test the conditional elimination has to correctly merge the type information it
-         * has about o, so that it can remove the check on Number.
-         */
-        if (!(o instanceof Number)) {
-            field = o;
-        }
-    }
-
-    @Test
-    public void testTypeMerging() {
-        StructuredGraph graph = parse("testTypeMergingSnippet");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-
-        assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count());
-    }
-
-    public static String testInstanceOfCheckCastSnippet(Object e) {
-        if (e instanceof Entry) {
-            return ((Entry) e).name;
-        }
-        return null;
-    }
-
-    @Test
-    public void testInstanceOfCheckCast() {
-        StructuredGraph graph = parse("testInstanceOfCheckCastSnippet");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-
-        assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count());
-    }
-
     public static int testRedundantComparesSnippet(int[] array) {
         if (array == null) {
             return 0;
@@ -272,39 +97,17 @@
         new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
         canonicalizer.apply(graph, context);
         new FloatingReadPhase().apply(graph);
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
+        new ConditionalEliminationPhase(getMetaAccess()).apply(graph, context);
         canonicalizer.apply(graph, context);
 
         assertEquals(1, graph.getNodes().filter(GuardNode.class).count());
     }
 
-    public static int testDuplicateNullChecksSnippet(Object a) {
-        if (a == null) {
-            return 2;
-        }
-        try {
-            return ((Integer) a).intValue();
-        } catch (ClassCastException e) {
-            return 0;
+    public static String testInstanceOfCheckCastSnippet(Object e) {
+        if (e instanceof Entry) {
+            return ((Entry) e).name;
         }
-    }
-
-    @Test
-    @Ignore
-    public void testDuplicateNullChecks() {
-        // This tests whether explicit null checks properly eliminate later null guards. Currently
-        // it's failing.
-        StructuredGraph graph = parse("testDuplicateNullChecksSnippet");
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-        PhaseContext context = new PhaseContext(getProviders(), null);
-
-        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
-        canonicalizer.apply(graph, context);
-        new FloatingReadPhase().apply(graph);
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
-        canonicalizer.apply(graph, context);
-
-        assertEquals(1, graph.getNodes().filter(GuardNode.class).count());
+        return null;
     }
 
     @Test
@@ -317,9 +120,10 @@
 
         new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
         canonicalizer.apply(graph, context);
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
+        new ConditionalEliminationPhase(getMetaAccess()).apply(graph, context);
         canonicalizer.apply(graph, context);
 
         assertEquals(0, graph.getNodes().filter(GuardNode.class).count());
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,395 @@
+/*
+ * 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 com.oracle.graal.debug.Debug;
+import com.oracle.graal.debug.DebugConfig;
+import com.oracle.graal.debug.DebugConfigScope;
+import com.oracle.graal.debug.internal.DebugScope;
+import com.oracle.graal.graph.Node;
+import com.oracle.graal.nodes.calc.ObjectEqualsNode;
+import com.oracle.graal.nodes.util.GraphUtil;
+import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase;
+import org.junit.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Tests whether {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} actually
+ * performs some graph rewritings that it's supposed to perform.
+ */
+public class FlowSenReduTest extends GraalCompilerTest {
+
+    /*
+     * A previous instanceof makes redundant a follow-up checkcast.
+     */
+    public Object redundantCheckCastSnippet(Number o) {
+        Integer z = null;
+        if (o instanceof Integer) {
+            z = (Integer) o; // this CheckCastNode will be removed
+        }
+        return z;
+    }
+
+    static final Integer i7 = new Integer(7);
+
+    @Test
+    public void redundantCheckCastTest() {
+        assertEquals(i7, redundantCheckCastSnippet(i7));
+        StructuredGraph result = afterFlowSensitiveReduce("redundantCheckCastSnippet");
+        nodeCountEquals(result, CheckCastNode.class, 0);
+        nodeCountEquals(result, InstanceOfNode.class, 1);
+    }
+
+    @SuppressWarnings("unused")
+    public boolean redundantInstanceOfSnippet01(Object o) {
+        if (o != null) {
+            Integer x = (Integer) o;
+            return (o instanceof Number); // this InstanceOfNode will be removed
+        }
+        return false;
+    }
+
+    @Test
+    public void redundantInstanceOfTest01() {
+        String snippet = "redundantInstanceOfSnippet01";
+        assertEquals(true, redundantInstanceOfSnippet01(i7));
+        nodeCountEquals(afterFlowSensitiveReduce(snippet), InstanceOfNode.class, 1);
+    }
+
+    /*
+     * The combination of (previous) non-null-check and checkcast make redundant an instanceof.
+     */
+    @SuppressWarnings("unused")
+    public Object redundantInstanceOfSnippet02(Object o) {
+        Integer x = (Integer) o;
+        if (o != null) {
+            if (o instanceof Number) { // this InstanceOfNode will be removed
+                return o;
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void redundantInstanceOfTest02() {
+        String snippet = "redundantInstanceOfSnippet02";
+        assertEquals(i7, redundantInstanceOfSnippet02(i7));
+        int ioAfter = getNodes(afterFlowSensitiveReduce(snippet), InstanceOfNode.class).size();
+        assertEquals(ioAfter, 1);
+    }
+
+    /*
+     * Once an exact-type has been inferred (due to instanceof final-class) a callsite is
+     * devirtualized.
+     */
+    public int devirtualizationSnippet(Object x, Object y) {
+        boolean c = x instanceof Integer;
+        if (c && x == y) {
+            Number z = (Number) y; // this CheckCastNode will be removed
+            return z.intValue(); // devirtualized into InvokeSpecial on Integer.intValue()
+        }
+        return 0;
+    }
+
+    @Test
+    public void devirtualizationTest() {
+        String snippet = "devirtualizationSnippet";
+        assertEquals(i7, devirtualizationSnippet(i7, i7));
+        nodeCountEquals(afterFlowSensitiveReduce(snippet), CheckCastNode.class, 0);
+
+        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
+        assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count());
+
+        List<InvokeNode> invokeNodes = getNodes(afterFlowSensitiveReduce(snippet), InvokeNode.class);
+        assertEquals(1, invokeNodes.size());
+
+        MethodCallTargetNode target = (MethodCallTargetNode) invokeNodes.get(0).callTarget();
+        assertEquals(MethodCallTargetNode.InvokeKind.Special, target.invokeKind());
+        assertEquals("HotSpotMethod<Integer.intValue()>", target.targetMethod().toString());
+    }
+
+    /*
+     * At the return statement, the returned value has been inferred to have type j.l.Number. The
+     * instanceof is deemed to always evaluate to false. The interplay with tail-duplication is also
+     * taken into account (resulting in two return statements, each with "false" as input).
+     */
+    @SuppressWarnings("unused")
+    public boolean t5Snippet(Object o, boolean b) {
+        Number z;
+        if (b) {
+            z = (Number) o; // tail duplication of return stmt, which becomes "return false"
+        } else {
+            z = (Integer) o; // tail duplication of return stmt, which becomes "return false"
+        }
+        return o instanceof String; // unreachable
+    }
+
+    @Test
+    public void t5a() {
+        String snippet = "t5Snippet";
+        assertEquals(false, t5Snippet(null, true));
+        StructuredGraph resultGraph = canonicalize(afterFlowSensitiveReduce(snippet));
+        nodeCountEquals(resultGraph, ReturnNode.class, 2);
+
+        List<ReturnNode> returnNodes = getNodes(resultGraph, ReturnNode.class);
+        Iterator<ReturnNode> iter = returnNodes.iterator();
+
+        ConstantNode c1 = (ConstantNode) iter.next().result();
+        ConstantNode c2 = (ConstantNode) iter.next().result();
+
+        assertEquals(c1, c2);
+        assertEquals(0, c1.getValue().asInt());
+    }
+
+    @Test
+    public void t5b() {
+        String snippet = "t5Snippet";
+        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
+        canonicalize(graph);
+        nodeCountEquals(graph, InstanceOfNode.class, 2);
+    }
+
+    public boolean t6Snippet(Object x, Object y) {
+        if (!(x instanceof String)) {
+            return false;
+        }
+        if (!(y instanceof Number)) {
+            return false;
+        }
+        return x == y; // two known-not-to-conform reference values can't be ==
+    }
+
+    // TODO: two known-not-to-conform reference values can't be ==
+    // but baseCaseObjectEqualsNode doesn't check that as of now.
+    public void t6() {
+        String snippet = "t6Snippet";
+        // visualize(snippet);
+        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
+        canonicalize(graph);
+        nodeCountEquals(graph, ObjectEqualsNode.class, 0);
+    }
+
+    /*
+     * A previous instanceof check causes a follow-up instanceof to be deemed unsatisfiable,
+     * resulting in constant-substitution at that usage.
+     */
+    public Object t7Snippet(Object o) {
+        if (o instanceof Number) {
+            if (o instanceof String) { // condition amounts to false
+                return o; // made unreachable
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void t7() {
+        String snippet = "t7Snippet";
+        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
+        graph = dce(canonicalize(graph));
+        // TODO how to simplify IfNode(false)
+        assertEquals(1, getNodes(graph, InstanceOfNode.class).size());
+
+        List<ReturnNode> returnNodes = getNodes(graph, ReturnNode.class);
+        assertEquals(2, returnNodes.size());
+        Iterator<ReturnNode> iter = returnNodes.iterator();
+
+        ConstantNode c1 = (ConstantNode) iter.next().result();
+        ConstantNode c2 = (ConstantNode) iter.next().result();
+
+        assertEquals(c1, c2);
+        Assert.assertTrue(c1.getValue().isNull());
+    }
+
+    /*
+     * During FlowSensitiveReduction, an unreachable branch doesn't contribute to the merged state.
+     * The resulting ("non-polluted") more precise inferred type after the merge allows
+     * devirtualizing a callsite.
+     */
+    public int devirtualizationSnippet02(Number o) {
+        if (o instanceof Integer) {
+            Number z = o;
+            if (o instanceof Long) {
+                z = o;
+            }
+            /*
+             * devirtualized into InvokeSpecial on Integer.intValue() ie the inferred-type is not
+             * polluted with values from the unreachable branch.
+             */
+            return z.intValue();
+        }
+        return 0;
+    }
+
+    @Test
+    public void devirtualizationTest02() {
+        String snippet = "devirtualizationSnippet02";
+        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
+
+        assertEquals(1, getNodes(graph, InvokeNode.class).size());
+
+        List<InvokeNode> invokeNodes = getNodes(graph, InvokeNode.class);
+        assertEquals(1, invokeNodes.size());
+
+        MethodCallTargetNode target = (MethodCallTargetNode) invokeNodes.get(0).callTarget();
+        assertEquals(MethodCallTargetNode.InvokeKind.Special, target.invokeKind());
+        assertEquals("HotSpotMethod<Integer.intValue()>", target.targetMethod().toString());
+    }
+
+    /*
+     * TODO ClassCastException known to fail --- either Deopt or throw ObjectGetClassNode The latter
+     * might lead to direct jump to EH if present.
+     */
+    @SuppressWarnings("unused")
+    public int t9Snippet(Object o) {
+        try {
+            if (o instanceof Number) {
+                String s = (String) o;
+                /*
+                 * make a long story short: replace the above with throw new ClassCastException (ok,
+                 * actual type of o unknown).
+                 */
+                return 1;
+            }
+        } catch (ClassCastException e) {
+            return 2;
+        }
+        return 3;
+    }
+
+    /*
+     * "Partial evaluation" via canonicalization of an expression (in the last return statement) one
+     * of whose leaf sub-expressions was determined to be constant.
+     */
+    @SuppressWarnings("unused")
+    public Object partialEvalSnippet01(Object o, boolean b) {
+        if (o == null) {
+            return o; // turned into "return null;"
+        } else {
+            Number z;
+            if (b) {
+                z = (Number) o;
+            } else {
+                z = (Integer) o;
+            }
+            return o instanceof String ? this : null; // turned into "return null;"
+        }
+    }
+
+    @Test
+    public void partialEvalTest01() {
+        String snippet = "partialEvalSnippet01";
+
+        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
+        canonicalize(graph);
+        dce(graph);
+
+        List<ReturnNode> returnNodes = getNodes(graph, ReturnNode.class);
+        assertEquals(2, returnNodes.size());
+        Iterator<ReturnNode> iter = returnNodes.iterator();
+
+        ValueNode c1 = GraphUtil.unproxify(iter.next().result());
+        ValueNode c2 = GraphUtil.unproxify(iter.next().result());
+        assert !iter.hasNext();
+
+        Assert.assertTrue(c1.isNullConstant());
+        Assert.assertTrue(c2.isNullConstant());
+    }
+
+    public static class C {
+        public int f;
+    }
+
+    /*
+     * A previous (assumed successful) instanceof check is reused later on to remove a checkcast.
+     */
+    public void deduplicateInstanceOfSnippet(Object o) {
+        ((C) o).f = ((C) o).f; // boils down to a single instanceof test
+    }
+
+    @Test
+    public void deduplicateInstanceOfTest() {
+        String snippet = "deduplicateInstanceOfSnippet";
+        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
+        List<InstanceOfNode> ioNodes = getNodes(graph, InstanceOfNode.class);
+        assertEquals(1, ioNodes.size());
+
+    }
+
+    // ---------------------------------------------
+    // ----------------- UTILITIES -----------------
+    // ---------------------------------------------
+
+    private PhaseContext getPhaseContext() {
+        return new PhaseContext(getProviders(), null);
+    }
+
+    private static StructuredGraph dce(StructuredGraph graph) {
+        new DeadCodeEliminationPhase().apply(graph);
+        return graph;
+    }
+
+    private StructuredGraph canonicalize(StructuredGraph graph) {
+        new CanonicalizerPhase(true).apply(graph, getPhaseContext());
+        return graph;
+    }
+
+    private StructuredGraph flowSensitiveReduce(StructuredGraph graph) {
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, getPhaseContext());
+        return graph;
+    }
+
+    public static <N extends Node> List<N> getNodes(StructuredGraph graph, Class<N> nodeClass) {
+        return graph.getNodes().filter(nodeClass).snapshot();
+    }
+
+    public <N extends Node> void nodeCountEquals(StructuredGraph graph, Class<N> nodeClass, int expected) {
+        assertEquals(expected, getNodes(graph, nodeClass).size());
+    }
+
+    public StructuredGraph afterFlowSensitiveReduce(String snippet) {
+        StructuredGraph before = canonicalize(parse(snippet));
+        // visualize(before, snippet + "-before");
+        StructuredGraph result = flowSensitiveReduce(before);
+        // visualize(result, snippet + "-after");
+        return result;
+    }
+
+    public StructuredGraph visualize(StructuredGraph graph, String title) {
+        DebugConfig debugConfig = DebugScope.getConfig();
+        DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, debugConfig.dumpHandlers(), debugConfig.output());
+        try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
+            Debug.dump(graph, title);
+
+            return graph;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,293 @@
+/*
+ * 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 static com.oracle.graal.nodes.ConstantNode.*;
+import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
+import static org.junit.Assert.*;
+
+import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase;
+import org.junit.*;
+
+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;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * Collection of tests for {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase}
+ * including those that triggered bugs in this phase.
+ */
+public class FlowSensitiveReductionTest extends GraalCompilerTest {
+
+    public static Object field;
+
+    static class Entry {
+
+        final String name;
+
+        public Entry(String name) {
+            this.name = name;
+        }
+    }
+
+    static class EntryWithNext extends Entry {
+
+        public EntryWithNext(String name, Entry next) {
+            super(name);
+            this.next = next;
+        }
+
+        final Entry next;
+    }
+
+    public static Entry search(Entry start, String name, Entry alternative) {
+        Entry current = start;
+        do {
+            while (current instanceof EntryWithNext) {
+                if (name != null && current.name == name) {
+                    current = null;
+                } else {
+                    Entry next = ((EntryWithNext) current).next;
+                    current = next;
+                }
+            }
+
+            if (current != null) {
+                if (current.name.equals(name)) {
+                    return current;
+                }
+            }
+            if (current == alternative) {
+                return null;
+            }
+            current = alternative;
+
+        } while (true);
+    }
+
+    /**
+     * This test presents a code pattern that triggered a bug where a (non-eliminated) checkcast
+     * caused an enclosing instanceof (for the same object and target type) to be incorrectly
+     * eliminated.
+     */
+    @Test
+    public void testReanchoringIssue() {
+        Entry end = new Entry("end");
+        EntryWithNext e1 = new EntryWithNext("e1", end);
+        EntryWithNext e2 = new EntryWithNext("e2", e1);
+
+        test("search", e2, "e3", new Entry("e4"));
+    }
+
+    @SuppressWarnings("unused")
+    public static int testNullnessSnippet(Object a, Object b) {
+        if (a == null) {
+            if (a == b) {
+                if (b == null) {
+                    return 1;
+                } else {
+                    return -2;
+                }
+            } else {
+                if (b == null) {
+                    return -3;
+                } else {
+                    return 4;
+                }
+            }
+        } else {
+            if (a == b) {
+                if (b == null) {
+                    return -5;
+                } else {
+                    return 6;
+                }
+            } else {
+                if (b == null) {
+                    return 7;
+                } else {
+                    return 8;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testNullness() {
+        test("testNullnessSnippet", null, null);
+        test("testNullnessSnippet", null, new Object());
+        test("testNullnessSnippet", new Object(), null);
+        test("testNullnessSnippet", new Object(), new Object());
+
+        StructuredGraph graph = parse("testNullnessSnippet");
+        PhaseContext context = new PhaseContext(getProviders(), null);
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, context);
+        for (ConstantNode constant : getConstantNodes(graph)) {
+            if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) {
+                assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static int testDisjunctionSnippet(Object a) {
+        try {
+            if (a instanceof Integer) {
+                if (a == null) {
+                    return -1;
+                } else {
+                    return 2;
+                }
+            } else {
+                return 3;
+            }
+        } finally {
+            field = null;
+        }
+    }
+
+    @Test
+    public void testDisjunction() {
+        StructuredGraph graph = parse("testDisjunctionSnippet");
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
+        IfNode ifNode = (IfNode) graph.start().next();
+        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
+        IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0)));
+        InstanceOfNode y = instanceOf;
+        ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY));
+        LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction));
+        ifNode.setCondition(negation);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), null));
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
+        for (ConstantNode constant : getConstantNodes(graph)) {
+            if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) {
+                assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
+            }
+        }
+    }
+
+    public static int testInvokeSnippet(Number n) {
+        if (n instanceof Integer) {
+            return n.intValue();
+        } else {
+            return 1;
+        }
+    }
+
+    @Test
+    public void testInvoke() {
+        test("testInvokeSnippet", new Integer(16));
+        StructuredGraph graph = parse("testInvokeSnippet");
+        PhaseContext context = new PhaseContext(getProviders(), null);
+        new CanonicalizerPhase(true).apply(graph, context);
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
+
+        InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first();
+        assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind());
+    }
+
+    public static void testTypeMergingSnippet(Object o, boolean b) {
+        if (b) {
+            if (!(o instanceof Double)) {
+                return;
+            }
+        } else {
+            if (!(o instanceof Integer)) {
+                return;
+            }
+        }
+
+        /*
+         * For this test the conditional elimination has to correctly merge the type information it
+         * has about o, so that it can remove the check on Number.
+         */
+        if (!(o instanceof Number)) {
+            field = o;
+        }
+    }
+
+    @Test
+    public void testTypeMerging() {
+        StructuredGraph graph = parse("testTypeMergingSnippet");
+        PhaseContext context = new PhaseContext(getProviders(), null);
+        new CanonicalizerPhase(true).apply(graph, context);
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
+
+        assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count());
+    }
+
+    public static String testInstanceOfCheckCastSnippet(Object e) {
+        if (e instanceof Entry) {
+            return ((Entry) e).name;
+        }
+        return null;
+    }
+
+    @Test
+    public void testInstanceOfCheckCast() {
+        StructuredGraph graph = parse("testInstanceOfCheckCastSnippet");
+        PhaseContext context = new PhaseContext(getProviders(), null);
+        new CanonicalizerPhase(true).apply(graph, context);
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
+
+        assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count());
+    }
+
+    public static int testDuplicateNullChecksSnippet(Object a) {
+        if (a == null) {
+            return 2;
+        }
+        try {
+            return ((Integer) a).intValue();
+        } catch (ClassCastException e) {
+            return 0;
+        }
+    }
+
+    @Test
+    @Ignore
+    public void testDuplicateNullChecks() {
+        // This tests whether explicit null checks properly eliminate later null guards. Currently
+        // it's failing.
+        StructuredGraph graph = parse("testDuplicateNullChecksSnippet");
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+        PhaseContext context = new PhaseContext(getProviders(), null);
+
+        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        canonicalizer.apply(graph, context);
+        new FloatingReadPhase().apply(graph);
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
+        canonicalizer.apply(graph, context);
+
+        assertEquals(1, graph.getNodes().filter(GuardNode.class).count());
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Apr 28 11:18:15 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.*;
@@ -41,6 +41,7 @@
 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;
@@ -169,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");
@@ -675,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/InfopointReasonTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -39,7 +39,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.test.*;
 
 /**
  * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons.
@@ -72,7 +71,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void lineInfopoints() {
         final Method method = getMethod("testMethod");
         final StructuredGraph graph = parseDebug(method);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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/ScalarTypeSystemTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.compiler.test;
 
+import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase;
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
@@ -167,8 +168,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
+        PhaseContext context = new PhaseContext(getProviders(), assumptions);
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, context);
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Apr 28 11:18:15 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/TypeSystemTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.io.*;
 
+import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase;
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
@@ -184,7 +185,12 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
+        /*
+         * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase,
+         * tail-duplication gets activated thus resulting in a graph with more nodes than the
+         * reference graph.
+         */
+        new ConditionalEliminationPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), assumptions));
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         // a second canonicalizer is needed to process nested MaterializeNodes
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
@@ -239,7 +245,7 @@
         StructuredGraph graph = parse(snippet);
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
-        new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
+        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), assumptions));
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         Debug.dump(graph, "Graph " + snippet);
         Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Apr 28 11:18:15 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.*;
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.test.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant
@@ -51,7 +50,7 @@
         return f1 + " " + arg1 + " " + arg2 + " " + arg3;
     }
 
-    @LongTest
+    @Test
     public void test1() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
@@ -74,7 +73,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void test3() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
@@ -88,7 +87,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void test4() {
         Method method = getMethod("testMethodVirtual");
         final StructuredGraph graph = parse(method);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Apr 28 11:18:15 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.*;
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java	Mon Apr 28 11:18:15 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/inlining/InliningTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -38,7 +38,6 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.test.*;
 
 public class InliningTest extends GraalCompilerTest {
 
@@ -73,7 +72,7 @@
         assertInlined(getGraph("invokeMethodOnFieldSnippet", false));
     }
 
-    @LongTest
+    @Test
     public void testStaticBindableInliningIP() {
         assertManyMethodInfopoints(assertInlined(getGraph("invokeConstructorSnippet", true)));
         assertManyMethodInfopoints(assertInlined(getGraph("invokeFinalMethodSnippet", true)));
@@ -82,7 +81,7 @@
     }
 
     @Ignore("would need read elimination/EA before inlining")
-    @LongTest
+    @Test
     public void testDependentStaticBindableInliningIP() {
         assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFinalFieldSnippet", true)));
         assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFieldSnippet", true)));
@@ -180,7 +179,7 @@
         assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", false));
     }
 
-    @LongTest
+    @Test
     public void testClassHierarchyAnalysisIP() {
         assertManyMethodInfopoints(assertInlined(getGraph("invokeLeafClassMethodSnippet", true)));
         assertManyMethodInfopoints(assertInlined(getGraph("invokeConcreteMethodSnippet", true)));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java	Mon Apr 28 11:18:15 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.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/META-INF/services/javax.annotation.processing.Processor	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,1 @@
+com.oracle.graal.compiler.match.MatchProcessor
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Apr 28 11:18:15 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,15 +34,17 @@
 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.gen.*;
+import com.oracle.graal.compiler.common.cfg.*;
 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.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.spi.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
@@ -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,
@@ -207,7 +208,7 @@
         }
     }
 
-    private static void emitBlock(NodeLIRBuilder nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) {
+    private static void emitBlock(NodeLIRBuilderTool nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) {
         if (lirGenRes.getLIR().getLIRforBlock(b) == null) {
             for (Block pred : b.getPredecessors()) {
                 if (!b.isLoopHeader() || !pred.isLoopEnd()) {
@@ -245,8 +246,8 @@
         try (Scope ds = Debug.scope("BackEnd", lir)) {
             FrameMap frameMap = backend.newFrameMap(registerConfig);
             LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(lir, frameMap, stub);
-            LIRGenerator lirGen = backend.newLIRGenerator(cc, lirGenRes);
-            NodeLIRBuilder nodeLirGen = backend.newNodeLIRGenerator(graph, lirGen);
+            LIRGeneratorTool lirGen = backend.newLIRGenerator(cc, lirGenRes);
+            NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen);
 
             try (Scope s = Debug.scope("LIRGen", lirGen)) {
                 for (Block b : linearScanOrder) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Mon Apr 28 11:18:15 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) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,16 +22,15 @@
  */
 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;
+    protected final LIRGeneratorTool gen;
     protected final BytecodeParserTool parser;
 
-    public BytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) {
+    public BytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) {
         this.gen = gen;
         this.parser = parser;
     }
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Apr 28 11:18:15 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.*;
@@ -115,21 +116,33 @@
     }
 
     protected BytecodeFrame computeFrameForState(FrameState state) {
-        int numLocals = state.localsSize();
-        int numStack = state.stackSize();
-        int numLocks = state.locksSize();
+        try {
+            assert state.bci != BytecodeFrame.INVALID_FRAMESTATE_BCI;
+            assert state.bci != BytecodeFrame.UNKNOWN_BCI;
+            assert state.bci != BytecodeFrame.BEFORE_BCI || state.locksSize() == 0;
+            assert state.bci != BytecodeFrame.AFTER_BCI || state.locksSize() == 0;
+            assert state.bci != BytecodeFrame.AFTER_EXCEPTION_BCI || state.locksSize() == 0;
+            assert !(state.method().isSynchronized() && state.bci != BytecodeFrame.BEFORE_BCI && state.bci != BytecodeFrame.AFTER_BCI && state.bci != BytecodeFrame.AFTER_EXCEPTION_BCI) ||
+                            state.locksSize() > 0;
+            assert state.verify();
+
+            int numLocals = state.localsSize();
+            int numStack = state.stackSize();
+            int numLocks = state.locksSize();
 
-        Value[] values = new Value[numLocals + numStack + numLocks];
-        computeLocals(state, numLocals, values);
-        computeStack(state, numLocals, numStack, values);
-        computeLocks(state, values);
+            Value[] values = new Value[numLocals + numStack + numLocks];
+            computeLocals(state, numLocals, values);
+            computeStack(state, numLocals, numStack, values);
+            computeLocks(state, values);
 
-        BytecodeFrame caller = null;
-        if (state.outerFrameState() != null) {
-            caller = computeFrameForState(state.outerFrameState());
+            BytecodeFrame caller = null;
+            if (state.outerFrameState() != null) {
+                caller = computeFrameForState(state.outerFrameState());
+            }
+            return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks);
+        } catch (GraalInternalError e) {
+            throw e.addContext("FrameState: ", state);
         }
-        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);
     }
 
     protected void computeLocals(FrameState state, int numLocals, Value[] values) {
@@ -168,39 +181,43 @@
     private static final DebugMetric STATE_CONSTANTS = Debug.metric("StateConstants");
 
     protected Value toValue(ValueNode value) {
-        if (value instanceof VirtualObjectNode) {
-            VirtualObjectNode obj = (VirtualObjectNode) value;
-            EscapeObjectState state = objectStates.get(obj);
-            if (state == null && obj.entryCount() > 0) {
-                // null states occur for objects with 0 fields
-                throw new GraalInternalError("no mapping found for virtual object %s", obj);
-            }
-            if (state instanceof MaterializedObjectState) {
-                return toValue(((MaterializedObjectState) state).materializedValue());
-            } else {
-                assert obj.entryCount() == 0 || state instanceof VirtualObjectState;
-                VirtualObject vobject = virtualObjects.get(value);
-                if (vobject == null) {
-                    vobject = VirtualObject.get(obj.type(), null, virtualObjects.size());
-                    virtualObjects.put(obj, vobject);
+        try {
+            if (value instanceof VirtualObjectNode) {
+                VirtualObjectNode obj = (VirtualObjectNode) value;
+                EscapeObjectState state = objectStates.get(obj);
+                if (state == null && obj.entryCount() > 0) {
+                    // null states occur for objects with 0 fields
+                    throw new GraalInternalError("no mapping found for virtual object %s", obj);
                 }
-                STATE_VIRTUAL_OBJECTS.increment();
-                return vobject;
-            }
-        } else if (value instanceof ConstantNode) {
-            STATE_CONSTANTS.increment();
-            return ((ConstantNode) value).getValue();
+                if (state instanceof MaterializedObjectState) {
+                    return toValue(((MaterializedObjectState) state).materializedValue());
+                } else {
+                    assert obj.entryCount() == 0 || state instanceof VirtualObjectState;
+                    VirtualObject vobject = virtualObjects.get(value);
+                    if (vobject == null) {
+                        vobject = VirtualObject.get(obj.type(), null, virtualObjects.size());
+                        virtualObjects.put(obj, vobject);
+                    }
+                    STATE_VIRTUAL_OBJECTS.increment();
+                    return vobject;
+                }
+            } else if (value instanceof ConstantNode) {
+                STATE_CONSTANTS.increment();
+                return ((ConstantNode) value).getValue();
 
-        } else if (value != null) {
-            STATE_VARIABLES.increment();
-            Value operand = nodeOperands.get(value);
-            assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value;
-            return operand;
+            } else if (value != null) {
+                STATE_VARIABLES.increment();
+                Value operand = nodeOperands.get(value);
+                assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value;
+                return operand;
 
-        } else {
-            // return a dummy value because real value not needed
-            STATE_ILLEGALS.increment();
-            return Value.ILLEGAL;
+            } else {
+                // return a dummy value because real value not needed
+                STATE_ILLEGALS.increment();
+                return Value.ILLEGAL;
+            }
+        } catch (GraalInternalError e) {
+            throw e.addContext("toValue: ", value);
         }
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.gen;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.lir.LIR.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
 
@@ -31,21 +32,25 @@
 
 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.target.*;
+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.match.*;
 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.LoadConstant;
+import com.oracle.graal.lir.gen.LIRGenerator.Options;
 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.
@@ -55,16 +60,18 @@
     private final NodeMap<Value> nodeOperands;
     private final DebugInfoBuilder debugInfoBuilder;
 
-    protected final LIRGenerator gen;
+    protected final LIRGeneratorTool gen;
 
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
 
-    public NodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) {
+    private Map<Class<? extends ValueNode>, List<MatchStatement>> matchRules;
+
+    public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen) {
         this.gen = gen;
         this.nodeOperands = graph.createNodeMap();
         this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands);
-        gen.setDebugInfoBuilder(debugInfoBuilder);
+        matchRules = MatchRuleRegistry.lookup(getClass());
     }
 
     @SuppressWarnings("hiding")
@@ -110,25 +117,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;
                 }
@@ -151,13 +158,25 @@
     @Override
     public Value setResult(ValueNode x, Value operand) {
         assert (!isRegister(operand) || !gen.attributes(asRegister(operand)).isAllocatable());
-        assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice";
+        assert nodeOperands != null && (nodeOperands.get(x) == null || nodeOperands.get(x) instanceof ComplexMatchValue) : "operand cannot be set twice";
         assert operand != null && isLegal(operand) : "operand must be legal";
         assert !(x instanceof VirtualObjectNode);
         nodeOperands.set(x, operand);
         return operand;
     }
 
+    /**
+     * Used by the {@link MatchStatement} machinery to override the generation LIR for some
+     * ValueNodes.
+     */
+    public void setMatchResult(ValueNode x, Value operand) {
+        assert operand.equals(Value.INTERIOR_MATCH) || operand instanceof ComplexMatchValue;
+        assert operand instanceof ComplexMatchValue || x.usages().count() == 1 : "interior matches must be single user";
+        assert nodeOperands != null && nodeOperands.get(x) == null : "operand cannot be set twice";
+        assert !(x instanceof VirtualObjectNode);
+        nodeOperands.set(x, operand);
+    }
+
     public LabelRef getLIRBlock(FixedNode b) {
         assert gen.getResult().getLIR().getControlFlowGraph() instanceof ControlFlowGraph;
         Block result = ((ControlFlowGraph) gen.getResult().getLIR().getControlFlowGraph()).blockFor(b);
@@ -169,7 +188,7 @@
     }
 
     public final void append(LIRInstruction op) {
-        if (gen.printIRWithLIR && !TTY.isSuppressed()) {
+        if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) {
             if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
                 lastInstructionPrinted = currentInstruction;
                 InstructionPrinter ip = new InstructionPrinter(TTY.out());
@@ -190,10 +209,17 @@
         }
 
         List<ScheduledNode> nodes = blockMap.get(block);
+
+        if (MatchExpressions.getValue()) {
+            // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups
+            // of instructions
+            matchComplexExpressions(nodes);
+        }
+
         int instructionsFolded = 0;
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
-            if (gen.traceLevel >= 3) {
+            if (Options.TraceLIRGeneratorLevel.getValue() >= 3) {
                 TTY.println("LIRGen for " + instr);
             }
             if (instructionsFolded > 0) {
@@ -205,19 +231,30 @@
 
             } else if (instr instanceof ValueNode) {
                 ValueNode valueNode = (ValueNode) instr;
-                if (!hasOperand(valueNode)) {
+                Value operand = getOperand(valueNode);
+                if (operand == null) {
                     if (!peephole(valueNode)) {
                         instructionsFolded = maybeFoldMemory(nodes, i, valueNode);
                         if (instructionsFolded == 0) {
                             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);
                             }
                         }
                     }
+                } else if (Value.INTERIOR_MATCH.equals(operand)) {
+                    // Doesn't need to be evaluated
+                    Debug.log("interior match for %s", valueNode);
+                } else if (operand instanceof ComplexMatchValue) {
+                    Debug.log("complex match for %s", valueNode);
+                    ComplexMatchValue match = (ComplexMatchValue) operand;
+                    operand = match.evaluate(this);
+                    if (operand != null) {
+                        setResult(valueNode, operand);
+                    }
                 } else {
                     // There can be cases in which the result of an instruction is already set
                     // before by other instructions.
@@ -242,6 +279,31 @@
         gen.doBlockEnd(block);
     }
 
+    protected void matchComplexExpressions(List<ScheduledNode> nodes) {
+        if (matchRules != null) {
+            try (Scope s = Debug.scope("MatchComplexExpressions")) {
+                // Match the nodes in backwards order to encourage longer matches.
+                for (int index = nodes.size() - 1; index >= 0; index--) {
+                    ScheduledNode snode = nodes.get(index);
+                    if (!(snode instanceof ValueNode)) {
+                        continue;
+                    }
+                    ValueNode node = (ValueNode) snode;
+                    // See if this node is the root of any MatchStatements
+                    List<MatchStatement> statements = matchRules.get(node.getClass());
+                    if (statements != null) {
+                        for (MatchStatement statement : statements) {
+                            if (statement.generate(this, node, nodes)) {
+                                // Found a match so skip to the next
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private static final DebugMetric MemoryFoldSuccess = Debug.metric("MemoryFoldSuccess");
     private static final DebugMetric MemoryFoldFailed = Debug.metric("MemoryFoldFailed");
     private static final DebugMetric MemoryFoldFailedNonAdjacent = Debug.metric("MemoryFoldedFailedNonAdjacent");
@@ -391,7 +453,7 @@
     protected abstract boolean peephole(ValueNode valueNode);
 
     private void doRoot(ValueNode instr) {
-        if (gen.traceLevel >= 2) {
+        if (Options.TraceLIRGeneratorLevel.getValue() >= 2) {
             TTY.println("Emitting LIR for instruction " + instr);
         }
         currentInstruction = instr;
@@ -405,14 +467,10 @@
         if (Debug.isLogEnabled() && node.stamp() instanceof IllegalStamp) {
             Debug.log("This node has invalid type, we are emitting dead code(?): %s", node);
         }
-        if (node instanceof LIRGenLowerable) {
-            ((LIRGenLowerable) node).generate(this);
-        } else if (node instanceof LIRGenResLowerable) {
-            ((LIRGenResLowerable) node).generate(this, gen.getResult());
-        } else if (node instanceof LIRLowerable) {
+        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);
         }
@@ -458,7 +516,7 @@
     }
 
     private void moveToPhi(MergeNode merge, AbstractEndNode pred) {
-        if (gen.traceLevel >= 1) {
+        if (Options.TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("MOVE TO PHI from " + pred + " to " + merge);
         }
         PhiResolver resolver = new PhiResolver(gen);
@@ -566,7 +624,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 +717,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);
     }
 
@@ -684,11 +781,7 @@
     }
 
     @Override
-    public LIRGenerator getLIRGeneratorTool() {
-        return gen;
-    }
-
-    public LIRGenerator getLIRGenerator() {
+    public LIRGeneratorTool getLIRGeneratorTool() {
         return gen;
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Mon Apr 28 11:18:15 2014 +0200
@@ -29,22 +29,23 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * Converts {@link ValuePhiNode} instructions into moves.
- * 
+ *
  * Resolves cycles:
- * 
+ *
  * <pre>
- * 
+ *
  *  r1 := r2  becomes  temp := r1
  *  r2 := r1           r1 := r2
  *                     r2 := temp
  * </pre>
- * 
+ *
  * and orders moves:
- * 
+ *
  * <pre>
  *  r2 := r3  becomes  r1 := r2
  *  r1 := r2           r2 := r3
@@ -103,7 +104,7 @@
         }
     }
 
-    private final LIRGenerator gen;
+    private final LIRGeneratorTool gen;
 
     /**
      * The operand loop header phi for the operand currently being process in {@link #dispose()}.
@@ -120,7 +121,7 @@
      */
     private final HashMap<Value, PhiResolverNode> operandToNodeMap = new HashMap<>();
 
-    public PhiResolver(LIRGenerator gen) {
+    public PhiResolver(LIRGeneratorTool gen) {
         this.gen = gen;
         temp = ILLEGAL;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchResult.java	Mon Apr 28 11:18:15 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle 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.match;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+
+/*
+ * A closure that can be evaluated to produce the LIR for some complex match. Using a closure
+ * allows normal evaluation in NodeLIRBuilder for all the simple nodes with the complex nodes
+ * evaluated at the proper time.
+ */
+public interface ComplexMatchResult {
+    Value evaluate(NodeLIRBuilder gen);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java	Mon Apr 28 11:18:15 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.match;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+
+/**
+ * A wrapper value for the lazy evaluation of a complex match. There's an intermediate class for the
+ * closure because Value is serializable which is a hassle for the little inner classes which
+ * usually occur here.
+ */
+public class ComplexMatchValue extends Value {
+    /**
+     *
+     */
+    private static final long serialVersionUID = -4734670273590368770L;
+
+    final ComplexMatchResult result;
+
+    public ComplexMatchValue(ComplexMatchResult result) {
+        super(Kind.Illegal);
+        this.result = result;
+    }
+
+    public Value evaluate(NodeLIRBuilder builder) {
+        return result.evaluate(builder);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/GraalMatchableNodes.java	Mon Apr 28 11:18:15 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.compiler.match;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * Helper class to describe the matchable nodes in the core Graal IR. These could possibly live in
+ * their respective classes but for simplicity in the {@link MatchProcessor} they are grouped here.
+ */
+@MatchableNode(shortName = "Constant", value = ConstantNode.class, inputs = 0)
+@MatchableNode(shortName = "FloatConvert", value = FloatConvertNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
+@MatchableNode(shortName = "FloatSub", value = FloatSubNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
+@MatchableNode(shortName = "FloatingRead", value = FloatingReadNode.class, inputs = 1, adapter = GraalMatchableNodes.ReadNodeAdapter.class)
+@MatchableNode(shortName = "If", value = IfNode.class, inputs = 1, adapter = GraalMatchableNodes.IfNodeAdapter.class)
+@MatchableNode(shortName = "IntegerSub", value = IntegerSubNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
+@MatchableNode(shortName = "LeftShift", value = LeftShiftNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
+@MatchableNode(shortName = "Narrow", value = NarrowNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
+@MatchableNode(shortName = "Read", value = ReadNode.class, inputs = 1, adapter = GraalMatchableNodes.ReadNodeAdapter.class)
+@MatchableNode(shortName = "Reinterpret", value = ReinterpretNode.class, inputs = 1, adapter = GraalMatchableNodes.ReinterpretNodeAdapter.class)
+@MatchableNode(shortName = "SignExtend", value = SignExtendNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
+@MatchableNode(shortName = "UnsignedRightShift", value = UnsignedRightShiftNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
+@MatchableNode(shortName = "Write", value = WriteNode.class, inputs = 2, adapter = GraalMatchableNodes.WriteNodeAdapter.class)
+@MatchableNode(shortName = "ZeroExtend", value = ZeroExtendNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
+@MatchableNode(shortName = "And", value = AndNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "FloatAdd", value = FloatAddNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "FloatEquals", value = FloatEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "FloatLessThan", value = FloatLessThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "FloatMul", value = FloatMulNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerAdd", value = IntegerAddNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerBelowThan", value = IntegerBelowThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerEquals", value = IntegerEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerLessThan", value = IntegerLessThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerMul", value = IntegerMulNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerTest", value = IntegerTestNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "ObjectEquals", value = ObjectEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "Or", value = OrNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "Xor", value = XorNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+public class GraalMatchableNodes {
+    public static class BinaryNodeAdapter extends MatchNodeAdapter {
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((BinaryNode) node).x();
+        }
+
+        @Override
+        protected ValueNode getSecondInput(ValueNode node) {
+            return ((BinaryNode) node).y();
+        }
+    }
+
+    public static class WriteNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((WriteNode) node).object();
+        }
+
+        @Override
+        protected ValueNode getSecondInput(ValueNode node) {
+            return ((WriteNode) node).value();
+        }
+    }
+
+    public static class ConvertNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((ConvertNode) node).getInput();
+        }
+    }
+
+    public static class ReinterpretNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((ReinterpretNode) node).value();
+        }
+    }
+
+    public static class IfNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((IfNode) node).condition();
+        }
+    }
+
+    public static class ReadNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((Access) node).object();
+        }
+    }
+
+    public static class BinaryOpLogicNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((BinaryOpLogicNode) node).x();
+        }
+
+        @Override
+        protected ValueNode getSecondInput(ValueNode node) {
+            return ((BinaryOpLogicNode) node).y();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchContext.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,191 @@
+/*
+ * 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.match;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.match.MatchPattern.Result;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.virtual.*;
+
+/**
+ * Container for state captured during a match.
+ */
+public class MatchContext {
+    private final ArrayList<ValueNode> consumed = new ArrayList<>();
+    private final List<ScheduledNode> nodes;
+    private final ValueNode root;
+    private List<String> names;
+    private List<Class<? extends ValueNode>> types;
+    private List<ValueNode> values;
+    private final MatchStatement rule;
+    private int startIndex;
+    private int endIndex;
+    private final NodeLIRBuilder builder;
+
+    public MatchContext(NodeLIRBuilder builder, MatchStatement rule, ValueNode node, List<ScheduledNode> nodes) {
+        this.builder = builder;
+        this.rule = rule;
+        this.root = node;
+        this.nodes = nodes;
+        // The root should be the last index since all the inputs must be scheduled before.
+        startIndex = endIndex = nodes.indexOf(node);
+    }
+
+    public ValueNode getRoot() {
+        return root;
+    }
+
+    public Result captureNamedValue(String name, Class<? extends ValueNode> type, ValueNode value) {
+        if (names == null) {
+            names = new ArrayList<>(2);
+            values = new ArrayList<>(2);
+            types = new ArrayList<>(2);
+        }
+        int index = names.indexOf(name);
+        if (index == -1) {
+            names.add(name);
+            values.add(value);
+            types.add(type);
+            return Result.OK;
+        } else {
+            if (values.get(index) != value) {
+                return Result.NAMED_VALUE_MISMATCH(value, rule.getPattern());
+            }
+            return Result.OK;
+        }
+    }
+
+    public Result validate() {
+        // Ensure that there's no unsafe work in between these operations.
+        for (int i = startIndex; i <= endIndex; i++) {
+            ScheduledNode node = getNodes().get(i);
+            if (node instanceof ConstantNode || node instanceof LocationNode || node instanceof VirtualObjectNode || node instanceof ParameterNode) {
+                // these can be evaluated lazily so don't worry about them. This should probably be
+                // captured by some interface that indicates that their generate method is empty.
+                continue;
+            } else if (!consumed.contains(node) && node != root) {
+                // This is too verbose for normal logging.
+                // Debug.log("unexpected node %s", node);
+                // for (int j = startIndex; j <= endIndex; j++) {
+                // ScheduledNode theNode = getNodes().get(j);
+                // Debug.log("%s(%s) %1s", (consumed.contains(theNode) || theNode == root) ? "*" :
+                // " ",
+                // theNode.usages().count(), theNode);
+                // }
+                return Result.NOT_SAFE(node, rule.getPattern());
+            }
+        }
+        return Result.OK;
+    }
+
+    /**
+     * Transfers the captured value into the MatchGenerator instance. The reflective information
+     * should really be generated and checking during construction of the MatchStatement but this is
+     * ok for now.
+     */
+    public void transferState(MatchGenerator generator) {
+        try {
+            for (int i = 0; i < names.size(); i++) {
+                String name = names.get(i);
+                try {
+                    Field field = generator.getClass().getDeclaredField(name);
+                    field.setAccessible(true);
+                    field.set(generator, values.get(i));
+                } catch (NoSuchFieldException e) {
+                    // Doesn't exist so the generator doesn't care about the value.
+                }
+            }
+        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
+            throw new GraalInternalError(e);
+        }
+        try {
+            Field field = generator.getClass().getDeclaredField("root");
+            field.setAccessible(true);
+            field.set(generator, getRoot());
+        } catch (NoSuchFieldException e) {
+            // Doesn't exist
+        } catch (SecurityException | IllegalAccessException | IllegalArgumentException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    public void setResult(ComplexMatchResult result) {
+        setResult(new ComplexMatchValue(result));
+    }
+
+    /**
+     * Mark the interior nodes with INTERIOR_MATCH and set the Value of the root to be the result.
+     * During final LIR generation it will be evaluated to produce the actual LIR value.
+     *
+     * @param result
+     */
+    public void setResult(ComplexMatchValue result) {
+        Debug.log("matched %s %s", rule.getName(), rule.getPattern());
+        // Debug.log("%s", rule.formatMatch(root));
+        for (ValueNode node : consumed) {
+            // All the interior nodes should be skipped during the normal doRoot calls in
+            // NodeLIRBuilder so mark them as interior matches. The root of the match will get a
+            // closure which will be evaluated to produce the final LIR.
+            getBuilder().setMatchResult(node, Value.INTERIOR_MATCH);
+        }
+        getBuilder().setMatchResult(root, result);
+    }
+
+    /**
+     * Mark a node as consumed by the match. Consumed nodes will never be evaluated.
+     *
+     * @return Result.OK if the node can be safely consumed.
+     */
+    public Result consume(ValueNode node) {
+        if (node.usages().count() != 1) {
+            return Result.TOO_MANY_USERS(node, rule.getPattern());
+        }
+
+        if (getBuilder().hasOperand(node)) {
+            return Result.ALREADY_USED(node, rule.getPattern());
+        }
+
+        int index = getNodes().indexOf(node);
+        if (index == -1) {
+            return Result.NOT_IN_BLOCK(node, rule.getPattern());
+        }
+        startIndex = Math.min(startIndex, index);
+        consumed.add(node);
+        return Result.OK;
+    }
+
+    private NodeLIRBuilder getBuilder() {
+        return builder;
+    }
+
+    private List<ScheduledNode> getNodes() {
+        return nodes;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchGenerator.java	Mon Apr 28 11:18:15 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle 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.match;
+
+import com.oracle.graal.compiler.gen.*;
+
+/**
+ * Code generator for complex match patterns.
+ *
+ * @returns null if the match can't be generated or a {@link ComplexMatchResult} that can be
+ *          evaluated during LIR generation to produce the final LIR value.
+ */
+public interface MatchGenerator {
+    ComplexMatchResult match(NodeLIRBuilder gen);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchNodeAdapter.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.match;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * Helper class to visit the matchable inputs of a node in a specified order. This may not be needed
+ * in the end since this could probably be done using the inputs iterator but it simplifies things
+ * for the moment.
+ */
+public class MatchNodeAdapter {
+    @SuppressWarnings("unused")
+    protected ValueNode getFirstInput(ValueNode node) {
+        throw new InternalError();
+    }
+
+    @SuppressWarnings("unused")
+    protected ValueNode getSecondInput(ValueNode node) {
+        throw new InternalError();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,201 @@
+/*
+ * 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.match;
+
+import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodes.*;
+
+/**
+ * A simple recursive pattern matcher for a DAG of nodes.
+ */
+
+public class MatchPattern {
+
+    enum MatchResultCode {
+        OK,
+        WRONG_CLASS,
+        NAMED_VALUE_MISMATCH,
+        TOO_MANY_USERS,
+        NOT_IN_BLOCK,
+        NOT_SAFE,
+        ALREADY_USED,
+    }
+
+    /**
+     * A descriptive result for match failures. This can be helpful for debugging why a match
+     * doesn't work as expected.
+     */
+    static class Result {
+        final MatchResultCode code;
+        final ScheduledNode node;
+        final MatchPattern matcher;
+
+        Result(MatchResultCode result, ScheduledNode node, MatchPattern matcher) {
+            this.code = result;
+            this.node = node;
+            this.matcher = matcher;
+        }
+
+        static final Result OK = new Result(MatchResultCode.OK, null, null);
+
+        static Result WRONG_CLASS(ValueNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.WRONG_CLASS, node, matcher);
+        }
+
+        static Result NAMED_VALUE_MISMATCH(ValueNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher);
+        }
+
+        static Result TOO_MANY_USERS(ValueNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.TOO_MANY_USERS, node, matcher);
+        }
+
+        static Result NOT_IN_BLOCK(ScheduledNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher);
+        }
+
+        static Result NOT_SAFE(ScheduledNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.NOT_SAFE, node, matcher);
+        }
+
+        static Result ALREADY_USED(ValueNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.ALREADY_USED, node, matcher);
+        }
+
+        @Override
+        public String toString() {
+            if (code == MatchResultCode.OK) {
+                return "OK";
+            }
+            return code + " " + node.toString(Verbosity.Id) + "|" + node.getClass().getSimpleName() + " " + matcher;
+        }
+    }
+
+    /**
+     * The expected type of the node. It must match exactly.
+     */
+    private final Class<? extends ValueNode> nodeClass;
+    /**
+     * An optional name for this node. A name can occur multiple times in a match and that name must
+     * always refer to the same node of the match will fail.
+     */
+    private final String name;
+    /**
+     * An optional pattern for the first input.
+     */
+    private final MatchPattern first;
+    /**
+     * An optional pattern for the second input.
+     */
+    private final MatchPattern second;
+    /**
+     * Helper class to visit the inputs.
+     */
+    private final MatchNodeAdapter adapter;
+    /**
+     * Can there only be one user of the node. Constant nodes can be matched even if there are other
+     * users.
+     */
+    private final boolean singleUser;
+
+    public MatchPattern(String name, boolean singleUser) {
+        this(null, name, null, null, null, singleUser);
+    }
+
+    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, boolean singleUser) {
+        this(nodeClass, name, null, null, null, singleUser);
+    }
+
+    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchNodeAdapter adapter, boolean singleUser) {
+        this(nodeClass, name, first, null, adapter, singleUser);
+    }
+
+    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, MatchNodeAdapter adapter, boolean singleUser) {
+        this.nodeClass = nodeClass;
+        this.name = name;
+        this.singleUser = singleUser;
+        this.first = first;
+        this.second = second;
+        this.adapter = adapter;
+    }
+
+    Class<? extends ValueNode> nodeClass() {
+        return nodeClass;
+    }
+
+    Result match(ValueNode node, MatchContext context) {
+        return matchTree(node, context, true);
+    }
+
+    private Result matchTree(ValueNode node, MatchContext context, boolean atRoot) {
+        Result result = Result.OK;
+        if (nodeClass != null && node.getClass() != nodeClass) {
+            return Result.WRONG_CLASS(node, this);
+        }
+        if (singleUser && !atRoot) {
+            result = context.consume(node);
+            if (result != Result.OK) {
+                return result;
+            }
+        }
+
+        if (name != null) {
+            result = context.captureNamedValue(name, nodeClass, node);
+        }
+
+        if (first != null) {
+            result = first.matchTree(adapter.getFirstInput(node), context, false);
+            if (result == Result.OK && second != null) {
+                result = second.matchTree(adapter.getSecondInput(node), context, false);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * For a node starting at root, produce a String showing the inputs that matched against this
+     * rule. It's assumed that a match has already succeeded against this rule, otherwise the
+     * printing may produce exceptions.
+     */
+    public String formatMatch(ValueNode root) {
+        String result = String.format("%s", root);
+        if (first == null && second == null) {
+            return result;
+        } else {
+            return "(" + result + (first != null ? " " + first.formatMatch(adapter.getFirstInput(root)) : "") + (second != null ? " " + second.formatMatch(adapter.getSecondInput(root)) : "") + ")";
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (nodeClass == null) {
+            return name;
+        } else {
+            String pre = first != null || second != null ? "(" : "";
+            String post = first != null || second != null ? ")" : "";
+            String nodeName = nodeClass.getSimpleName();
+            return pre + nodeName + (name != null ? "=\"" + name + "\"" : "") + (first != null ? (" " + first.toString()) : "") + (second != null ? (" " + second.toString()) : "") + post;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,574 @@
+/*
+ * 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.match;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.*;
+
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is
+ * generated for each top level class containing at least one such field. These service objects can
+ * be retrieved as follows:
+ *
+ * <pre>
+ *     ServiceLoader<MatchStatementSet> sl = ServiceLoader.loadInstalled(MatchStatementSet.class);
+ *     for (MatchStatementSet rules : sl) {
+ *         ...
+ *     }
+ * </pre>
+ */
+@SupportedAnnotationTypes({"com.oracle.graal.compiler.match.MatchRule", "com.oracle.graal.compiler.match.MatchRules", "com.oracle.graal.compiler.match.MatchableNode"})
+public class MatchProcessor extends AbstractProcessor {
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    private final Set<Element> processedMatchRule = new HashSet<>();
+    private final Set<Element> processedMatchableNode = new HashSet<>();
+
+    private static class RuleParseError extends RuntimeException {
+        private static final long serialVersionUID = 6456128283609257490L;
+
+        RuleParseError(String message) {
+            super(message);
+        }
+    }
+
+    private class RuleParser {
+        final String[] tokens;
+        int current;
+
+        RuleParser(String rule) {
+            Matcher m = tokenizer.matcher(rule);
+            List<String> list = new ArrayList<>();
+            int end = 0;
+            while (m.lookingAt()) {
+                list.add(m.group(1));
+                end = m.end();
+                m.region(m.end(), m.regionEnd());
+            }
+            if (end != m.regionEnd()) {
+                throw new RuleParseError("unexpected tokens :" + rule.substring(m.end(), m.regionEnd()));
+            }
+            tokens = list.toArray(new String[0]);
+        }
+
+        String next() {
+            return tokens[current++];
+        }
+
+        String peek() {
+            return tokens[current];
+        }
+
+        boolean done() {
+            return current == tokens.length;
+        }
+
+        private MatchDescriptor parseSexp() {
+            if (peek().equals("(")) {
+                next();
+                MatchDescriptor descriptor = parseType(true);
+                for (int n = 0; n < descriptor.nodeType.inputs; n++) {
+                    if (peek().equals("(")) {
+                        descriptor.inputs[n] = parseSexp();
+                    } else {
+                        descriptor.inputs[n] = parseType(false);
+                    }
+                }
+                for (int n = 0; n < descriptor.nodeType.inputs; n++) {
+                    if (descriptor.inputs[n] == null) {
+                        throw new RuleParseError("not enough inputs for " + descriptor.name);
+                    }
+                }
+                if (peek().equals(")")) {
+                    next();
+                    return descriptor;
+                }
+            }
+            throw new RuleParseError("didn't swallow sexp at: " + peek());
+        }
+
+        private MatchDescriptor parseType(boolean sexp) {
+            TypeDescriptor type = null;
+            String name = null;
+            if (Character.isUpperCase(peek().charAt(0))) {
+                String token = next();
+                type = types.get(token);
+                if (type == null) {
+                    throw new RuleParseError("unknown node type: " + token);
+                }
+                if (peek().equals("=")) {
+                    next();
+                    name = next();
+                }
+            } else {
+                name = next();
+                type = null;
+            }
+            return new MatchDescriptor(type, name, sexp);
+        }
+
+        ArrayList<String> generateVariants() {
+            MatchDescriptor descriptor = parseSexp();
+            if (!done()) {
+                throw new RuleParseError("didn't consume all tokens");
+            }
+            return descriptor.generateVariants();
+        }
+    }
+
+    static Pattern tokenizer = Pattern.compile("\\s*([()=]|[A-Za-z][A-Za-z0-9]*)\\s*");
+
+    static class TypeDescriptor {
+        /**
+         * The name uses in match expressions to refer to this type.
+         */
+        final String shortName;
+        /**
+         * The {@link ValueNode} class represented by this type.
+         */
+        final String nodeClass;
+
+        /**
+         * The {@link ValueNode} class represented by this type.
+         */
+        final String nodePackage;
+
+        /**
+         * Expected number of matchable inputs. Should be less <= 2 at the moment.
+         */
+        final int inputs;
+
+        /**
+         * An adapter class to read the proper matchable inputs of the class.
+         */
+        final String adapter;
+
+        /**
+         * Should swapped variants of this match be generated. The user of the match is expected to
+         * compensate for any ordering differences in compare which are commutative but require
+         * reinterpreting the condition in that case.
+         */
+        final boolean commutative;
+
+        /**
+         * Can multiple users of this node subsume it. Constants can be swallowed into a match even
+         * if there are multiple users.
+         */
+        final boolean cloneable;
+
+        TypeDescriptor(String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative) {
+            this.shortName = shortName;
+            this.nodeClass = nodeClass;
+            this.nodePackage = nodePackage;
+            this.inputs = inputs;
+            this.adapter = adapter;
+            this.commutative = commutative;
+            this.cloneable = (nodePackage + "." + nodeClass).equals(ConstantNode.class.getName());
+            assert !commutative || inputs == 2;
+        }
+    }
+
+    HashMap<String, TypeDescriptor> types = new HashMap<>();
+    ArrayList<String> packages = new ArrayList<>();
+
+    private void declareType(String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative) {
+        TypeDescriptor descriptor = new TypeDescriptor(shortName, nodeClass, nodePackage, inputs, adapter, commutative);
+        types.put(shortName, descriptor);
+        if (!packages.contains(descriptor.nodePackage)) {
+            packages.add(descriptor.nodePackage);
+        }
+    }
+
+    private static String findPackage(Element type) {
+        Element enclosing = type.getEnclosingElement();
+        while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) {
+            enclosing = enclosing.getEnclosingElement();
+        }
+        if (enclosing != null && enclosing.getKind() == ElementKind.PACKAGE) {
+            return ((PackageElement) enclosing).getQualifiedName().toString();
+        }
+        throw new GraalInternalError("can't find package for %s", type);
+    }
+
+    static class MatchDescriptor {
+        TypeDescriptor nodeType;
+        String name;
+        MatchDescriptor[] inputs;
+
+        MatchDescriptor(TypeDescriptor nodeType, String name, boolean sexp) {
+            this.nodeType = nodeType;
+            this.name = name;
+            if (sexp) {
+                this.inputs = new MatchDescriptor[nodeType.inputs];
+            } else {
+                this.inputs = new MatchDescriptor[0];
+            }
+        }
+
+        ArrayList<String> generateVariants() {
+            String prefix = formatPrefix();
+            String suffix = formatSuffix();
+            ArrayList<String> variants = new ArrayList<>();
+            if (inputs.length == 2) {
+                // Generate this version and a swapped version
+                for (String first : inputs[0].generateVariants()) {
+                    for (String second : inputs[1].generateVariants()) {
+                        variants.add(prefix + ", " + first + ", " + second + suffix);
+                        if (nodeType.commutative) {
+                            variants.add(prefix + ", " + second + ", " + first + suffix);
+                        }
+                    }
+                }
+            } else if (inputs.length == 1) {
+                for (String first : inputs[0].generateVariants()) {
+                    variants.add(prefix + ", " + first + suffix);
+                }
+            } else {
+                variants.add(prefix + suffix);
+            }
+            return variants;
+        }
+
+        private String formatPrefix() {
+            if (nodeType == null) {
+                return String.format("new MatchPattern(%s, false", name != null ? ("\"" + name + "\"") : "null");
+            } else {
+                return String.format("new MatchPattern(%s.class, %s", nodeType.nodeClass, name != null ? ("\"" + name + "\"") : "null");
+            }
+        }
+
+        private String formatSuffix() {
+            if (nodeType != null) {
+                if (inputs.length != nodeType.inputs) {
+                    return ", true)";
+                } else {
+                    if (nodeType.adapter != null) {
+                        return ", " + nodeType.adapter + "," + !nodeType.cloneable + ")";
+                    }
+                    if (nodeType.cloneable) {
+                        return ", false)";
+                    }
+                }
+            }
+            return ")";
+        }
+
+    }
+
+    private void createFiles(MatchRuleDescriptor info) {
+        String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString();
+        Name topDeclaringClass = info.topDeclaringType.getSimpleName();
+
+        String optionsClassName = topDeclaringClass + "_" + MatchStatementSet.class.getSimpleName();
+        Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]);
+
+        Filer filer = processingEnv.getFiler();
+        try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) {
+
+            out.println("// CheckStyle: stop header check");
+            out.println("// GENERATED CONTENT - DO NOT EDIT");
+            out.println("// Source: " + topDeclaringClass + ".java");
+            out.println("package " + pkg + ";");
+            out.println("");
+            out.println("import java.util.*;");
+            out.println("import " + MatchStatementSet.class.getPackage().getName() + ".*;");
+            out.println("import " + NodeLIRBuilder.class.getName() + ";");
+            for (String p : packages) {
+                out.println("import " + p + ".*;");
+            }
+            out.println("");
+            out.println("public class " + optionsClassName + " implements " + MatchStatementSet.class.getSimpleName() + " {");
+            String desc = MatchStatement.class.getSimpleName();
+            out.println("    // CheckStyle: stop line length check");
+            out.println("    private static final List<" + desc + "> options = Collections.unmodifiableList(Arrays.asList(");
+
+            int i = 0;
+            for (MatchRuleItem option : info.options) {
+                String optionValue;
+                if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
+                    optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")";
+                } else {
+                    optionValue = option.declaringClass + "." + option.field.getSimpleName();
+                }
+                String name = option.name;
+                Name fieldName = option.field.getSimpleName();
+                String comma = i == info.options.size() - 1 ? "" : ",";
+                out.printf("        new MatchStatement(\"%s\", %s, %s.class)%s\n", fieldName, name, optionValue, comma);
+                i++;
+            }
+            out.println("    ));");
+            out.println("    // CheckStyle: resume line length check");
+            out.println();
+
+            out.println("    public Class<? extends NodeLIRBuilder> forClass() {");
+            out.println("        return " + topDeclaringClass + ".class;");
+            out.println("    }");
+            out.println();
+            out.println("    @Override");
+            out.println("    public List<" + desc + "> statements() {");
+            out.println("        return options;");
+            out.println("    }");
+            out.println("}");
+        }
+
+        try {
+            createProviderFile(pkg, optionsClassName, originatingElements);
+        } catch (IOException e) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType);
+        }
+    }
+
+    private void createProviderFile(String pkg, String providerClassName, Element... originatingElements) throws IOException {
+        String filename = "META-INF/providers/" + pkg + "." + providerClassName;
+        FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements);
+        PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"));
+        writer.println(MatchStatementSet.class.getName());
+        writer.close();
+    }
+
+    protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) {
+        try {
+            // Ensure Unix line endings to comply with Graal code style guide checked by Checkstyle
+            JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, originatingElements);
+            return new PrintWriter(sourceFile.openWriter()) {
+
+                @Override
+                public void println() {
+                    print("\n");
+                }
+            };
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static class MatchRuleItem implements Comparable<MatchRuleItem> {
+
+        final String name;
+        final String declaringClass;
+        final TypeElement field;
+
+        public MatchRuleItem(String name, String declaringClass, TypeElement field) {
+            this.name = name;
+            this.declaringClass = declaringClass;
+            this.field = field;
+        }
+
+        @Override
+        public int compareTo(MatchRuleItem other) {
+            return name.compareTo(other.name);
+        }
+
+        @Override
+        public String toString() {
+            return declaringClass + "." + field;
+        }
+    }
+
+    static class MatchRuleDescriptor {
+
+        final TypeElement topDeclaringType;
+        final List<MatchRuleItem> options = new ArrayList<>();
+        final Set<Element> originatingElements = new HashSet<>();
+
+        public MatchRuleDescriptor(TypeElement topDeclaringType) {
+            this.topDeclaringType = topDeclaringType;
+        }
+    }
+
+    private static TypeElement topDeclaringType(Element element) {
+        Element enclosing = element.getEnclosingElement();
+        if (enclosing == null || enclosing.getKind() == ElementKind.PACKAGE) {
+            assert element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE;
+            return (TypeElement) element;
+        }
+        return topDeclaringType(enclosing);
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver()) {
+            return true;
+        }
+
+        try {
+            // Import default definitions
+            processMatchableNode(processingEnv.getElementUtils().getTypeElement(GraalMatchableNodes.class.getName()));
+            for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNodeImport.class)) {
+                // Import any other definitions required by this element
+                String[] imports = element.getAnnotation(MatchableNodeImport.class).value();
+                for (String m : imports) {
+                    TypeElement el = processingEnv.getElementUtils().getTypeElement(m);
+                    processMatchableNode(el);
+                }
+            }
+
+            // Process any local MatchableNode declarations
+            for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNode.class)) {
+                processMatchableNode(element);
+            }
+
+            Map<TypeElement, MatchRuleDescriptor> map = new HashMap<>();
+            for (Element element : roundEnv.getElementsAnnotatedWith(MatchRule.class)) {
+                processMatchRule(map, element);
+            }
+            for (Element element : roundEnv.getElementsAnnotatedWith(MatchRules.class)) {
+                processMatchRule(map, element);
+            }
+
+            for (MatchRuleDescriptor info : map.values()) {
+                createFiles(info);
+            }
+
+        } catch (Throwable t) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Exception throw during processing: " + t);
+        }
+
+        return true;
+    }
+
+    /**
+     * Build up the type table to be used during parsing of the MatchRule.
+     */
+    private void processMatchableNode(Element element) {
+        if (!processedMatchableNode.contains(element)) {
+            processedMatchableNode.add(element);
+            TypeElement topDeclaringType = topDeclaringType(element);
+            MatchableNode[] matchables = element.getAnnotationsByType(MatchableNode.class);
+            for (MatchableNode matchable : matchables) {
+                String nodeClass;
+                String nodePackage;
+                String shortName = matchable.shortName();
+                TypeMirror nodeClassMirror = null;
+                try {
+                    matchable.value();
+                } catch (MirroredTypeException e) {
+                    nodeClassMirror = e.getTypeMirror();
+                }
+                if (nodeClassMirror == null) {
+                    throw new GraalInternalError("Can't get mirror for node class %s", element);
+                }
+                if (nodeClassMirror.toString().equals(MatchableNode.class.getName())) {
+                    nodeClass = topDeclaringType.getQualifiedName().toString();
+                } else {
+                    nodeClass = nodeClassMirror.toString();
+                }
+                nodePackage = findPackage(processingEnv.getElementUtils().getTypeElement(nodeClass));
+                assert nodeClass.startsWith(nodePackage);
+                nodeClass = nodeClass.substring(nodePackage.length() + 1);
+
+                TypeMirror nodeAdapterMirror = null;
+                try {
+                    matchable.adapter();
+                } catch (MirroredTypeException e) {
+                    nodeAdapterMirror = e.getTypeMirror();
+                }
+                if (nodeAdapterMirror == null) {
+                    throw new GraalInternalError("Can't get mirror for adapter %s", element);
+                }
+                String nodeAdapter = null;
+                if (!nodeAdapterMirror.toString().equals(MatchableNode.class.getName())) {
+                    nodeAdapter = String.format("new %s()", nodeAdapterMirror.toString());
+                }
+
+                declareType(shortName, nodeClass, nodePackage, matchable.inputs(), nodeAdapter, matchable.commutative());
+            }
+        }
+    }
+
+    private void processMatchRule(Map<TypeElement, MatchRuleDescriptor> map, Element element) {
+        if (!processedMatchRule.contains(element)) {
+            processedMatchRule.add(element);
+            TypeElement topDeclaringType = topDeclaringType(element);
+            MatchRuleDescriptor options = map.get(topDeclaringType);
+            if (options == null) {
+                options = new MatchRuleDescriptor(topDeclaringType);
+                map.put(topDeclaringType, options);
+            }
+            MatchRule[] matchRules = element.getAnnotationsByType(MatchRule.class);
+            for (MatchRule matchRule : matchRules) {
+                processMatchRule(element, options, matchRule);
+            }
+        }
+    }
+
+    private void processMatchRule(Element element, MatchRuleDescriptor info, MatchRule matchRule) {
+        assert element instanceof TypeElement;
+        assert element.getKind() == ElementKind.CLASS;
+        TypeElement field = (TypeElement) element;
+
+        TypeMirror fieldType = field.asType();
+        if (fieldType.getKind() != TypeKind.DECLARED) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + MatchRule.class.getName(), element);
+            return;
+        }
+
+        Element enclosing = element.getEnclosingElement();
+        String declaringClass = "";
+        String separator = "";
+        Set<Element> originatingElementsList = info.originatingElements;
+        originatingElementsList.add(field);
+        while (enclosing != null) {
+            if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) {
+                if (enclosing.getModifiers().contains(Modifier.PRIVATE)) {
+                    String msg = String.format("Option field cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing);
+                    processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
+                    return;
+                }
+                originatingElementsList.add(enclosing);
+                declaringClass = enclosing.getSimpleName() + separator + declaringClass;
+                separator = ".";
+            } else {
+                assert enclosing.getKind() == ElementKind.PACKAGE;
+            }
+            enclosing = enclosing.getEnclosingElement();
+        }
+
+        String rule = matchRule.value();
+        try {
+            ArrayList<String> matches = new RuleParser(rule).generateVariants();
+            for (String match : matches) {
+                info.options.add(new MatchRuleItem(match, declaringClass, field));
+            }
+        } catch (RuleParseError e) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), element);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRule.java	Mon Apr 28 11:18:15 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.match;
+
+import java.lang.annotation.*;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * This annotation declares a textual pattern for matching an HIR DAG. It's an s-expression with a
+ * node followed by its inputs. Node types are always uppercase and lowercase words are the names of
+ * nodes.
+ *
+ * <pre>
+ *   NAME := [a-z][a-zA-Z0-9]*
+ *   NODETYPE := [A-Z][a-zA-Z0-9]*
+ *   NODEORNAME :=  NODE [ = NAME ] | NAME
+ *   EXPRESSION := ( NODEORNAME [ EXPRESSION | NODEORNAME [ EXPRESSION | NODEORNAME ] )
+ * </pre>
+ *
+ * All matched nodes except the root of the match and {@link ConstantNode}s must have a single user.
+ * All matched nodes must be in the same block.
+ */
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Repeatable(value = MatchRules.class)
+public @interface MatchRule {
+    String value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.match;
+
+import java.util.*;
+
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.nodes.*;
+
+public class MatchRuleRegistry {
+
+    private static final HashMap<Class<? extends NodeLIRBuilder>, Map<Class<? extends ValueNode>, List<MatchStatement>>> registry = new HashMap<>();
+
+    /**
+     * Collect all the {@link MatchStatement}s defined by the superclass chain of theClass.
+     *
+     * @param theClass
+     * @return the set of {@link MatchStatement}s applicable to theClass.
+     */
+    public synchronized static Map<Class<? extends ValueNode>, List<MatchStatement>> lookup(Class<? extends NodeLIRBuilder> theClass) {
+        Map<Class<? extends ValueNode>, List<MatchStatement>> result = registry.get(theClass);
+
+        if (result == null) {
+            HashMap<Class<? extends NodeLIRBuilder>, List<MatchStatement>> localRules = new HashMap<>();
+            ServiceLoader<MatchStatementSet> sl = ServiceLoader.loadInstalled(MatchStatementSet.class);
+            for (MatchStatementSet rules : sl) {
+                localRules.put(rules.forClass(), rules.statements());
+            }
+
+            // Walk the class hierarchy collecting lists and merge them together. The subclass
+            // rules are first which gives them preference over earlier rules.
+            Map<Class<? extends ValueNode>, List<MatchStatement>> rules = new HashMap<>();
+            Class<?> currentClass = theClass;
+            do {
+                List<MatchStatement> statements = localRules.get(currentClass);
+                if (statements != null) {
+                    for (MatchStatement statement : statements) {
+                        Class<? extends ValueNode> nodeClass = statement.getPattern().nodeClass();
+                        List<MatchStatement> current = rules.get(nodeClass);
+                        if (current == null) {
+                            current = new ArrayList<>();
+                            rules.put(nodeClass, current);
+                        }
+                        current.add(statement);
+                    }
+                }
+                currentClass = currentClass.getSuperclass();
+            } while (currentClass != NodeLIRBuilder.class);
+            registry.put(theClass, rules);
+            assert registry.get(theClass) == rules;
+            result = rules;
+        }
+
+        if (result.size() == 0) {
+            return null;
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRules.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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.match;
+
+import java.lang.annotation.*;
+
+/**
+ * The repeatable representation of {@link MatchRule}. Should never be used directly.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface MatchRules {
+    MatchRule[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.match.MatchPattern.Result;
+import com.oracle.graal.nodes.*;
+
+/**
+ * A named {@link MatchPattern} along with a {@link MatchGenerator} that can be evaluated to replace
+ * one or more {@link ValueNode}s with a single {@link Value}.
+ */
+
+public class MatchStatement {
+    private final String name;
+    private final MatchPattern pattern;
+    private final Class<? extends MatchGenerator> generatorClass;
+
+    public MatchStatement(String name, MatchPattern pattern) {
+        this.name = name;
+        this.pattern = pattern;
+        this.generatorClass = null;
+    }
+
+    public MatchStatement(String name, MatchPattern pattern, Class<? extends MatchGenerator> generator) {
+        this.name = name;
+        this.pattern = pattern;
+        this.generatorClass = generator;
+    }
+
+    /**
+     * Attempt to match the current statement against a Node.
+     *
+     * @param builder the current builder instance.
+     * @param node the node to be matched
+     * @param nodes the nodes in the current block
+     * @return true if the statement matched something and set a {@link ComplexMatchResult} to be
+     *         evaluated by the NodeLIRBuilder.
+     */
+    public boolean generate(NodeLIRBuilder builder, ValueNode node, List<ScheduledNode> nodes) {
+        MatchContext context = new MatchContext(builder, this, node, nodes);
+        Result result = pattern.match(node, context);
+        if (result == Result.OK) {
+            result = context.validate();
+        }
+        if (result == Result.OK) {
+            MatchGenerator generator = null;
+            try {
+                generator = generatorClass.newInstance();
+                // Transfer values into gen
+                context.transferState(generator);
+                ComplexMatchResult value = generator.match(builder);
+                if (value != null) {
+                    context.setResult(value);
+                    return true;
+                }
+            } catch (InstantiationException | IllegalAccessException e) {
+                throw new GraalInternalError(e);
+            }
+        } else {
+            // This is fairly verbose for normal usage.
+            // if (result.code != MatchResultCode.WRONG_CLASS) {
+            // // Don't bother logging if it's just the wrong shape.
+            // Debug.log("while matching %s|%s %s %s %s", context.getRoot().toString(Verbosity.Id),
+            // context.getRoot().getClass().getSimpleName(), getName(), result, node.graph());
+            // }
+        }
+        return false;
+    }
+
+    public String formatMatch(ValueNode root) {
+        return pattern.formatMatch(root);
+    }
+
+    public MatchPattern getPattern() {
+        return pattern;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatementSet.java	Mon Apr 28 11:18:15 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.match;
+
+import java.util.*;
+
+import com.oracle.graal.compiler.gen.*;
+
+public interface MatchStatementSet {
+    /**
+     * @return the {@link NodeLIRBuilder} subclass which defined this set of {@link MatchStatement}
+     *         instances.
+     */
+    public Class<? extends NodeLIRBuilder> forClass();
+
+    /**
+     * @return the {@link MatchStatement}s available with this {@link NodeLIRBuilder} subclass.
+     */
+    public List<MatchStatement> statements();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNode.java	Mon Apr 28 11:18:15 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle 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.match;
+
+import java.lang.annotation.*;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * Describes the properties of a node for use when building a {@link MatchPattern}s.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Repeatable(value = MatchableNodes.class)
+public @interface MatchableNode {
+
+    /**
+     * The {@link ValueNode} subclass this annotation describes. These annotations might work better
+     * if they were directly on the node being described but that may complicate the annotation
+     * processing.
+     */
+    Class<? extends ValueNode> value();
+
+    /**
+     * The name used in match patterns. Defaults to class.getSimpleName() with the word Node removed
+     * from the end.
+     */
+    String shortName() default "";
+
+    /**
+     * The number of matchable inputs, which may be less than the real number of inputs.
+     */
+    int inputs() default 0;
+
+    /**
+     * A helper class to visit the inputs in a specified order. Should be a subclass of
+     * {@link MatchNodeAdapter}.
+     */
+    Class<?> adapter() default MatchableNode.class;
+
+    /**
+     * Can a pattern be matched with the operands swapped. This will cause swapped versions of
+     * patterns to be automatically generated.
+     */
+    boolean commutative() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNodeImport.java	Mon Apr 28 11:18:15 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle 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.match;
+
+import java.lang.annotation.*;
+
+/**
+ * A list of classes which contain one or more {@link MatchableNode} annotations describing nodes
+ * that may be used in match expressions. Those {@link MatchableNode} declarations are parsed before
+ * processing any {@link MatchRule}s.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface MatchableNodeImport {
+    String[] value() default {};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNodes.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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.match;
+
+import java.lang.annotation.*;
+
+/**
+ * The repeatable representation of {@link MatchableNode}. Should never be used directly.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface MatchableNodes {
+    MatchableNode[] value() default {};
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,14 +22,15 @@
  */
 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.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.cfs.IterativeFlowSensitiveReductionPhase;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
@@ -57,9 +58,14 @@
                 appendPhase(new InliningPhase(canonicalizer));
                 appendPhase(new DeadCodeEliminationPhase());
 
-                if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
+                boolean reduceOrEliminate = FlowSensitiveReduction.getValue() || ConditionalElimination.getValue();
+                if (reduceOrEliminate && OptCanonicalizer.getValue()) {
                     appendPhase(canonicalizer);
-                    appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
+                    if (FlowSensitiveReduction.getValue()) {
+                        appendPhase(new IterativeFlowSensitiveReductionPhase(canonicalizer));
+                    } else {
+                        appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
+                    }
                 }
             }
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,11 +26,13 @@
 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.nodes.spi.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
 
@@ -71,17 +73,17 @@
      */
     public abstract FrameMap newFrameMap(RegisterConfig registerConfig);
 
-    public abstract LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes);
+    public abstract LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes);
 
     public abstract LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub);
 
-    public abstract NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen);
+    public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
 
     /**
      * @param gen the LIRGenerator the BytecodeLIRBuilder should use
      * @param parser the bytecode parser the BytecodeLIRBuilder should use
      */
-    public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) {
+    public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) {
         throw GraalInternalError.unimplemented("Baseline compilation is not available for this Backend!");
     }
 
@@ -102,9 +104,8 @@
     /**
      * 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	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.target;
-
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * An alternative to {@link LIRLowerable} for lowering that is tightly coupled to
- * {@link LIRGenerator} and {@link LIRInstruction}.
- */
-public interface LIRGenLowerable {
-
-    void generate(NodeLIRBuilder generator);
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.target;
-
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * An alternative to {@link LIRLowerable} for lowering that is tightly coupled to
- * {@link LIRGenerationResult} and {@link LIRInstruction}.
- */
-public interface LIRGenResLowerable {
-
-    void generate(NodeLIRBuilderTool generator, LIRGenerationResult genRes);
-}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Apr 28 11:18:15 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));
     }
 
     /**
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Apr 28 11:18:15 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/Node.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Apr 28 11:18:15 2014 +0200
@@ -184,12 +184,10 @@
 
     class NodeUsageIterator implements Iterator<Node> {
 
-        private final int expectedModCount = usageModCount();
         int index = -1;
         Node current;
 
         private void advance() {
-            assert index == -1 || current != null;
             current = null;
             index++;
             if (index == 0) {
@@ -208,12 +206,10 @@
         }
 
         public boolean hasNext() {
-            assert expectedModCount == usageModCount();
             return current != null;
         }
 
         public Node next() {
-            assert expectedModCount == usageModCount();
             Node result = current;
             if (result == null) {
                 throw new NoSuchElementException();
@@ -228,10 +224,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 +267,7 @@
 
         @Override
         public int count() {
-            if (usage0 == null) {
-                return 0;
-            }
-            if (usage1 == null) {
-                return 1;
-            }
-            return 2 + indexOfLastNonNull(extraUsages) + 1;
+            return usageCount();
         }
     }
 
@@ -349,6 +364,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 +447,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 +479,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,13 +633,47 @@
         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()) {
             NodeClassIterator iter = usage.inputs().iterator();
             while (iter.hasNext()) {
                 Position pos = iter.nextPosition();
-                if (pos.getInputType(usage) == type) {
+                if (pos.getInputType(usage) == type && pos.get(usage) == this) {
                     pos.set(usage, other);
                 }
             }
@@ -707,7 +831,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);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Apr 28 11:18:15 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) {
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctFilteredNodeIterable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicate.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicates.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/PredicatedProxyNodeIterator.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Apr 28 11:18:15 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,7 +46,9 @@
 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.*;
+import com.oracle.graal.nodes.spi.*;
 
 /**
  * HotSpot AMD64 specific backend.
@@ -72,7 +72,7 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+    public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
         return new AMD64HotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
     }
 
@@ -82,12 +82,12 @@
     }
 
     @Override
-    public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) {
+    public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         return new AMD64HotSpotNodeLIRBuilder(graph, lirGen);
     }
 
     @Override
-    public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) {
+    public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) {
         return new AMD64HotSpotBytecodeLIRBuilder(gen, parser);
 
     }
@@ -225,7 +225,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 +264,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/AMD64HotSpotBytecodeLIRBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,17 +24,16 @@
 
 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 {
 
-    public AMD64HotSpotBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) {
+    public AMD64HotSpotBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) {
         super(gen, parser);
     }
 
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,26 +25,29 @@
 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 static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import java.util.*;
 
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
 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.data.*;
 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.BranchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
@@ -53,9 +56,8 @@
 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.calc.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 
 /**
  * LIR generator specialized for AMD64 HotSpot.
@@ -63,6 +65,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);
@@ -129,7 +132,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() {
@@ -158,7 +171,7 @@
     }
 
     @Override
-    protected boolean needOnlyOopMaps() {
+    public boolean needOnlyOopMaps() {
         // Stubs only need oop maps
         return ((AMD64HotSpotLIRGenerationResult) getResult()).getStub() != null;
     }
@@ -176,12 +189,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));
     }
@@ -191,32 +257,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();
         }
@@ -227,15 +286,16 @@
             result = super.emitForeignCall(hotspotLinkage, deoptInfo, args);
             append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread));
         } else {
-            result = super.emitForeignCall(hotspotLinkage, deoptInfo, args);
+            assert deoptInfo == null;
+            result = super.emitForeignCall(hotspotLinkage, null, args);
         }
 
         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();
@@ -246,6 +306,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);
@@ -310,9 +385,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
@@ -336,13 +411,6 @@
     }
 
     /**
-     * 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) {
@@ -374,86 +442,34 @@
         }
     }
 
+    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));
-            }
-        } else {
-            append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
-        }
+        append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
     }
 
     @Override
@@ -507,7 +523,6 @@
         }
     }
 
-    @Override
     public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
         PlatformKind kind = newValue.getPlatformKind();
         assert kind == expectedValue.getPlatformKind();
@@ -523,4 +538,73 @@
         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;
+    }
+
+    public static class CompareMemoryCompressedOp extends AMD64LIRInstruction {
+        @Alive({COMPOSITE}) protected AMD64AddressValue x;
+        @Use({CONST, REG}) protected Value y;
+        @State protected LIRFrameState state;
+
+        public CompareMemoryCompressedOp(AMD64AddressValue x, Value y, LIRFrameState state) {
+            assert HotSpotGraalRuntime.runtime().getConfig().useCompressedOops;
+            this.x = x;
+            this.y = y;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            if (state != null) {
+                crb.recordImplicitException(masm.position(), state);
+            }
+            if (y instanceof Constant) {
+                Constant constant = (Constant) y;
+                if (constant.isNull()) {
+                    masm.cmpl(x.toAddress(), 0);
+                } else {
+                    if (y.getKind() == Kind.Object) {
+                        crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(constant), true));
+                    } else if (y.getKind() == Kind.Long) {
+                        crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), true));
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere();
+                    }
+                    masm.cmpl(x.toAddress(), 0xdeaddead);
+                }
+            } else {
+                masm.cmpl(asRegister(y), x.toAddress());
+            }
+        }
+    }
+
+    protected void emitCompareBranchMemoryCompressed(Value left, Value right, Condition cond, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability, LIRFrameState state) {
+        boolean mirrored = false;
+        if (left instanceof AMD64AddressValue) {
+            append(new CompareMemoryCompressedOp((AMD64AddressValue) left, right, state));
+        } else {
+            assert right instanceof AMD64AddressValue;
+            append(new CompareMemoryCompressedOp((AMD64AddressValue) right, left, state));
+            mirrored = true;
+        }
+
+        Condition finalCondition = mirrored ? cond.mirror() : cond;
+        append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
+    }
 }
--- /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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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/AMD64HotSpotMemoryPeephole.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,21 +23,15 @@
 
 package com.oracle.graal.hotspot.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.compiler.amd64.*;
-import com.oracle.graal.graph.*;
+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.amd64.AMD64HotSpotLIRGenerator.CompareMemoryCompressedOp;
+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.*;
 
 /**
@@ -45,41 +39,18 @@
  */
 
 public class AMD64HotSpotMemoryPeephole extends AMD64MemoryPeephole {
-    public static class CompareMemoryCompressedOp extends AMD64LIRInstruction {
-        @Alive({COMPOSITE}) protected AMD64AddressValue x;
-        @Use({CONST}) protected Value y;
-        @State protected LIRFrameState state;
-
-        public CompareMemoryCompressedOp(AMD64AddressValue x, Constant y, LIRFrameState state) {
-            assert HotSpotGraalRuntime.runtime().getConfig().useCompressedOops;
-            this.x = x;
-            this.y = y;
-            this.state = state;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            Constant constant = (Constant) y;
-            if (constant.isNull()) {
-                masm.cmpl(x.toAddress(), 0);
-            } else {
-                if (y.getKind() == Kind.Object) {
-                    crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(constant), true));
-                } else if (y.getKind() == Kind.Long) {
-                    crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), true));
-                } else {
-                    throw GraalInternalError.shouldNotReachHere();
-                }
-                if (state != null) {
-                    crb.recordImplicitException(masm.position(), state);
-                }
-                masm.cmpl(x.toAddress(), 0xdeaddead);
-            }
-        }
+    AMD64HotSpotMemoryPeephole(AMD64NodeLIRBuilder gen) {
+        super(gen);
     }
 
-    AMD64HotSpotMemoryPeephole(AMD64NodeLIRBuilder gen) {
-        super(gen);
+    @Override
+    protected Kind getMemoryKind(Access access) {
+        PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(access.asNode().stamp());
+        if (kind == NarrowOopStamp.NarrowOop) {
+            return Kind.Int;
+        } else {
+            return (Kind) kind;
+        }
     }
 
     @Override
@@ -87,7 +58,7 @@
                     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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,7 +31,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.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.data.*;
 import com.oracle.graal.hotspot.meta.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,15 +26,15 @@
 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.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.compiler.amd64.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.match.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
@@ -45,17 +45,55 @@
 import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.lir.amd64.*;
 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.extended.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
  * LIR generator specialized for AMD64 HotSpot.
  */
+@MatchableNodeImport({"com.oracle.graal.hotspot.nodes.HotSpotMatchableNodes"})
 public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements HotSpotNodeLIRBuilder {
 
-    public AMD64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) {
+    private static ValueNode filterCompression(ValueNode node) {
+        ValueNode result = node;
+        while (result instanceof CompressionNode) {
+            result = ((CompressionNode) result).getInput();
+        }
+        return result;
+    }
+
+    private void emitCompareCompressedMemory(IfNode ifNode, ValueNode value, Access access, CompareNode compare) {
+        Condition cond = compare.condition();
+        LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor());
+        LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor());
+        double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor());
+        Value left;
+        Value right;
+        if (access == filterCompression(compare.x())) {
+            if (value.isConstant()) {
+                left = value.asConstant();
+            } else {
+                left = gen.loadNonConst(operand(value));
+            }
+            right = makeAddress(access);
+        } else {
+            assert access == filterCompression(compare.y());
+            left = makeAddress(access);
+            right = gen.loadNonConst(operand(value));
+            cond = cond.mirror();
+        }
+        getGen().emitCompareBranchMemoryCompressed(left, right, cond, trueLabel, falseLabel, trueLabelProbability, getState(access));
+    }
+
+    public AMD64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool 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() {
@@ -107,7 +145,7 @@
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
-        LIRFrameState info = gen.state(i);
+        LIRFrameState info = state(i);
         append(new AMD64HotSpotSafepointOp(info, getGen().config, this));
     }
 
@@ -119,7 +157,7 @@
         } 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.";
+            assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method.";
             append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
         }
     }
@@ -160,7 +198,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);
@@ -199,4 +237,40 @@
         gen.emitMove(result, raxLocal);
         setResult(x, result);
     }
+
+    /**
+     * Helper class to convert the NodeLIRBuilder into the current subclass.
+     */
+    static abstract class AMD64HotSpotMatchGenerator implements MatchGenerator {
+        public AMD64HotSpotMatchGenerator() {
+        }
+
+        public ComplexMatchResult match(NodeLIRBuilder gen) {
+            return match((AMD64HotSpotNodeLIRBuilder) gen);
+        }
+
+        abstract public ComplexMatchResult match(AMD64HotSpotNodeLIRBuilder gen);
+    }
+
+    @MatchRule("(If (ObjectEquals=compare Constant=value (Compression Read=access)))")
+    @MatchRule("(If (ObjectEquals=compare Constant=value (Compression FloatingRead=access)))")
+    @MatchRule("(If (ObjectEquals=compare (Compression value) (Compression Read=access)))")
+    @MatchRule("(If (ObjectEquals=compare (Compression value) (Compression FloatingRead=access)))")
+    public static class IfCompareMemory extends AMD64HotSpotMatchGenerator {
+        IfNode root;
+        Access access;
+        ValueNode value;
+        CompareNode compare;
+
+        @Override
+        public ComplexMatchResult match(AMD64HotSpotNodeLIRBuilder gen) {
+            if (HotSpotGraalRuntime.runtime().getConfig().useCompressedOops) {
+                return builder -> {
+                    gen.emitCompareCompressedMemory(root, value, access, compare);
+                    return null;
+                };
+            }
+            return null;
+        }
+    }
 }
--- /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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,8 +31,8 @@
 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 {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,13 +26,12 @@
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.amd64.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.spi.*;
 
-public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRGenLowerable {
+public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable {
 
     private final Constant functionPointer;
     @Input private final NodeInputList<ValueNode> args;
@@ -44,7 +43,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder generator) {
+    public void generate(NodeLIRBuilderTool generator) {
         AMD64NodeLIRBuilder gen = (AMD64NodeLIRBuilder) generator;
         Value[] parameter = new Value[args.count()];
         JavaType[] parameterTypes = new JavaType[args.count()];
@@ -55,7 +54,7 @@
         ResolvedJavaType returnType = stamp().javaType(gen.getLIRGeneratorTool().getMetaAccess());
         CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes,
                         generator.getLIRGeneratorTool().target(), false);
-        ((AMD64LIRGenerator) gen.getLIRGeneratorTool()).emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args));
+        gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args));
         if (this.getKind() != Kind.Void) {
             generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn()));
         }
--- /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	Mon Apr 28 11:18:15 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/HSAILHotSpotBackend.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Mon Apr 28 11:18:15 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,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.type.*;
 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 +60,17 @@
 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.nodes.spi.*;
+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,16 +295,15 @@
         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());
         for (CodeAnnotation annotation : hostCode.getAnnotations()) {
             result.addAnnotation(annotation);
         }
-        CompilationResult.Mark[] noMarks = {};
         for (Mark mark : hostCode.getMarks()) {
-            result.recordMark(mark.pcOffset, mark.id, noMarks);
+            result.recordMark(mark.pcOffset, mark.id);
         }
         for (ExceptionHandler handler : hostCode.getExceptionHandlers()) {
             result.recordExceptionHandler(handler.pcOffset, handler.handlerPos);
@@ -347,15 +348,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.
@@ -366,7 +375,7 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+    public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
         return new HSAILHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
     }
 
@@ -376,7 +385,7 @@
     }
 
     @Override
-    public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) {
+    public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         return new HSAILHotSpotNodeLIRBuilder(graph, lirGen);
     }
 
@@ -423,15 +432,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 +468,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 +568,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(Kind.Int, 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 +625,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 +645,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 +688,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 +727,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
@@ -694,7 +753,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 +784,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 +841,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 +853,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 +885,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 +924,7 @@
         return frameState;
     }
 
-    @SuppressWarnings({"unused"})
+    @SuppressWarnings("unused")
     private static MonitorIdNode getMonitorIdForHotSpotMonitorValueFromFrame(HotSpotMonitorValue lockValue, ParameterNode hsailFrame, StructuredGraph hsailGraph) {
         if (lockValue.isEliminated()) {
             return null;
@@ -910,7 +966,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Mon Apr 28 11:18:15 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 {
@@ -44,7 +44,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();
@@ -56,9 +56,12 @@
         Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null);
         Replacements replacements = new HSAILHotSpotReplacementsImpl(p, host.getSnippetReflection(), assumptions, codeCache.getTarget(), host.getReplacements());
         HotSpotDisassemblerProvider disassembler = host.getDisassembler();
-        SuitesProvider suites = new DefaultSuitesProvider();
+        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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Mon Apr 28 11:18:15 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,14 +27,16 @@
 
 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;
@@ -42,16 +44,11 @@
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall2ArgOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp;
 import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp;
-import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer;
 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.calc.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -95,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;
@@ -120,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));
@@ -142,40 +118,17 @@
     }
 
     @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));
@@ -199,8 +152,28 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting) {
-        emitDeoptimizeInner(actionAndReason, state(deopting), "emitDeoptimize");
+    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 Value emitAtomicReadAndWrite(Value address, Value newValue) {
+        PlatformKind kind = newValue.getPlatformKind();
+        Kind memKind = getMemoryKind(kind);
+        Variable result = newVariable(kind);
+        HSAILAddressValue addressValue = asAddressValue(address);
+        append(new HSAILMove.AtomicReadAndWriteOp(memKind, result, addressValue, asAllocatable(newValue)));
+        return result;
+    }
+
+    @Override
+    public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state) {
+        emitDeoptimizeInner(actionAndReason, state, "emitDeoptimize");
     }
 
     /***
@@ -218,7 +191,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
@@ -283,15 +256,15 @@
     }
 
     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();
     }
 
     @Override
@@ -307,4 +280,32 @@
         append(new HSAILMove.UncompressPointer(result, asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment, nonNull));
         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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Mon Apr 28 11:18:15 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 DefaultHotSpotLoweringProvider {
 
-    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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Mon Apr 28 11:18:15 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,21 +23,28 @@
 
 package com.oracle.graal.hotspot.hsail;
 
+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.HSAILMove.CompareAndSwapOp;
 import com.oracle.graal.nodes.*;
 
 /**
  * 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) {
+    public HSAILHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         super(graph, lirGen);
     }
 
@@ -50,6 +57,10 @@
         }
     }
 
+    private HSAILHotSpotLIRGenerator getGen() {
+        return (HSAILHotSpotLIRGenerator) gen;
+    }
+
     /**
      * @return a compressed version of the incoming constant lifted from AMD64HotSpotLIRGenerator
      */
@@ -65,4 +76,56 @@
             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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java	Mon Apr 28 11:18:15 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.*;
 
--- /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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Mon Apr 28 11:18:15 2014 +0200
@@ -36,11 +36,11 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 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 +49,12 @@
 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.nodes.spi.*;
 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;
     }
 
@@ -354,12 +356,12 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+    public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
         return new PTXHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
     }
 
     @Override
-    public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) {
+    public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         return new PTXHotSpotNodeLIRBuilder(graph, lirGen);
     }
 
@@ -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/PTXHotSpotForeignCallsProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java	Mon Apr 28 11:18:15 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.
@@ -70,4 +71,32 @@
         // TODO
         throw GraalInternalError.unimplemented();
     }
+
+    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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java	Mon Apr 28 11:18:15 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.*;
 
 /**
@@ -35,7 +35,7 @@
  */
 public class PTXHotSpotNodeLIRBuilder extends PTXNodeLIRBuilder implements HotSpotNodeLIRBuilder {
 
-    protected PTXHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) {
+    protected PTXHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         super(graph, lirGen);
     }
 
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Mon Apr 28 11:18:15 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];
@@ -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
      */
--- /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	Mon Apr 28 11:18:15 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.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);
+        // This is basically the maximum we can spare. All other G and O register are used.
+        Register[] allocatable = new Register[]{g1, g3, g4, g5, o0, o1, o2, o3, o4};
+        registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable);
+    }
+
+    @Override
+    public RegisterConfig getRegisterConfig() {
+        return registerConfig;
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Apr 28 11:18:15 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,7 @@
 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.gen.*;
-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.*;
@@ -54,8 +51,10 @@
 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.*;
+import com.oracle.graal.nodes.spi.*;
 
 /**
  * HotSpot SPARC specific backend.
@@ -79,12 +78,17 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+    public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
         return new SPARCHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
     }
 
     @Override
-    public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) {
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        return new SPARCHotSpotLIRGenerationResult(lir, frameMap, stub);
+    }
+
+    @Override
+    public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         return new SPARCHotSpotNodeLIRBuilder(graph, lirGen);
     }
 
@@ -174,7 +178,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));
@@ -191,17 +195,12 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
-        return new LIRGenerationResultBase(lir, frameMap);
-    }
-
-    @Override
     public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
         SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
         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/SPARCHotSpotCRuntimeCallPrologueOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 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
@@ -48,9 +48,8 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-
         // Save last Java frame.
-        new Add(stackPointer, new SPARCAddress(stackPointer, 0).getDisplacement(), g4).emit(masm);
+        new Add(stackPointer, STACK_BIAS, g4).emit(masm);
         new Stx(g4, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
 
         // Save the thread register when calling out to the runtime.
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Mon Apr 28 11:18:15 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);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,96 @@
+/*
+ * 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.sparc;
+
+import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+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.sparc.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+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 SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction {
+
+    private final Register thread;
+    private final int threadLastJavaSpOffset;
+    private final int threadLastJavaPcOffset;
+    @Alive(REG) AllocatableValue framePc;
+    @Alive(REG) AllocatableValue senderSp;
+    @Temp(REG) AllocatableValue scratch;
+
+    SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch) {
+        this.thread = thread;
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.threadLastJavaPcOffset = threadLastJavaPcOffset;
+        this.framePc = framePc;
+        this.senderSp = senderSp;
+        this.scratch = scratch;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        final int totalFrameSize = crb.frameMap.totalFrameSize();
+        Register framePcRegister = asRegister(framePc);
+        Register senderSpRegister = asRegister(senderSp);
+        Register scratchRegister = asRegister(scratch);
+
+        // Save final sender SP to O5_savedSP.
+        new Mov(senderSpRegister, o5).emit(masm);
+
+        // Load final frame PC.
+        new Mov(framePcRegister, o7).emit(masm);
+
+        // Allocate a full sized frame.
+        new Save(sp, -totalFrameSize, sp).emit(masm);
+
+        new Mov(i0, o0).emit(masm);
+        new Mov(i1, o1).emit(masm);
+        new Mov(i2, o2).emit(masm);
+        new Mov(i3, o3).emit(masm);
+        new Mov(i4, o4).emit(masm);
+
+        // Set up last Java values.
+        new Add(sp, STACK_BIAS, scratchRegister).emit(masm);
+        new Stx(scratchRegister, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
+
+        // Clear last Java PC.
+        new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm);
+
+        /*
+         * Safe thread register manually since we are not using LEAF_SP for {@link
+         * DeoptimizationStub#UNPACK_FRAMES}.
+         */
+        new Mov(thread, l7).emit(masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,14 +22,49 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+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.*;
+import com.oracle.graal.lir.gen.*;
+
+public class SPARCHotSpotLIRGenerationResult extends LIRGenerationResultBase {
+
+    /**
+     * The slot reserved for storing the original return address when a frame is marked for
+     * deoptimization. The return address slot in the callee is overwritten with the address of a
+     * deoptimization stub.
+     */
+    private StackSlot deoptimizationRescueSlot;
+    private final Object stub;
 
-public interface SPARCHotSpotLIRGenerationResult extends LIRGenerationResult {
+    /**
+     * Map from debug infos that need to be updated with callee save information to the operations
+     * that provide the information.
+     */
+    private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>();
+
+    public SPARCHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        super(lir, frameMap);
+        this.stub = stub;
+    }
 
-    StackSlot getDeoptimizationRescueSlot();
+    StackSlot getDeoptimizationRescueSlot() {
+        return deoptimizationRescueSlot;
+    }
+
+    public final void setDeoptimizationRescueSlot(StackSlot deoptimizationRescueSlot) {
+        this.deoptimizationRescueSlot = deoptimizationRescueSlot;
+    }
 
-    Stub getStub();
+    Stub getStub() {
+        return (Stub) stub;
+    }
+
+    Map<LIRFrameState, SaveRegistersOp> getCalleeSaveInfo() {
+        return calleeSaveInfo;
+    }
 
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Apr 28 11:18:15 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,27 +24,30 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*;
+import static com.oracle.graal.sparc.SPARC.*;
 
 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 +68,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 +92,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 +155,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 +171,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 +197,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 +213,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);
@@ -234,7 +240,8 @@
     }
 
     public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
-        throw new InternalError("NYI");
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -258,4 +265,79 @@
         // TODO
         throw GraalInternalError.unimplemented();
     }
+
+    /**
+     * @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 SPARCSaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations, boolean supportsRemove) {
+        SPARCSaveRegistersOp save = new SPARCSaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove);
+        append(save);
+        return save;
+    }
+
+    public SaveRegistersOp emitSaveAllRegisters() {
+        // We save all registers that were not saved by the save instruction.
+        // @formatter:off
+        Register[] savedRegisters = {
+                        // CPU
+                        g1, g3, g4, g5,
+                        // FPU
+                        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+                        f8,  f9,  f10, f11, f12, f13, f14, f15,
+                        f16, f17, f18, f19, f20, f21, f22, f23,
+                        f24, f25, f26, f27, f28, f29, f30, f31
+        };
+        // @formatter:on
+        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, false);
+    }
+
+    public void emitLeaveCurrentStackFrame() {
+        append(new SPARCHotSpotLeaveCurrentStackFrameOp());
+    }
+
+    public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
+        append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp());
+    }
+
+    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        Variable framePcVariable = load(framePc);
+        Variable senderSpVariable = load(senderSp);
+        Variable scratchVariable = newVariable(getHostWordKind());
+        append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable));
+    }
+
+    public void emitLeaveUnpackFramesStackFrame() {
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset()));
+    }
+
+    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 SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable));
+    }
+
+    public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
+        ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP);
+
+        Register threadRegister = getProviders().getRegisters().getThreadRegister();
+        Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister();
+        append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister));
+        Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(Kind.Long), trapRequest);
+        append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister));
+
+        return result;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java	Mon Apr 28 11:18:15 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.hotspot.sparc;
+
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Pops the current frame off the stack.
+ */
+@Opcode("LEAVE_CURRENT_STACK_FRAME")
+final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCHotSpotEpilogueOp {
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        // Save O registers over restore.
+        new Mov(o0, i0).emit(masm);
+        new Mov(o1, i1).emit(masm);
+        new Mov(o2, i2).emit(masm);
+        new Mov(o3, i3).emit(masm);
+        new Mov(o4, i4).emit(masm);
+
+        leaveFrame(crb);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java	Mon Apr 28 11:18:15 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.hotspot.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.asm.sparc.*;
+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 SPARCHotSpotLeaveDeoptimizedStackFrameOp extends SPARCHotSpotEpilogueOp {
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        // Save O registers over restore.
+        new Mov(o0, i0).emit(masm);
+        new Mov(o1, i1).emit(masm);
+        new Mov(o2, i2).emit(masm);
+        new Mov(o3, i3).emit(masm);
+        new Mov(o4, i4).emit(masm);
+
+        new RestoreWindow().emit(masm);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+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 SPARCHotSpotLeaveUnpackFramesStackFrameOp extends SPARCLIRInstruction {
+
+    private final Register thread;
+    private final int threadLastJavaSpOffset;
+    private final int threadLastJavaPcOffset;
+    private final int threadJavaFrameAnchorFlagsOffset;
+
+    SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) {
+        this.thread = thread;
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.threadLastJavaPcOffset = threadLastJavaPcOffset;
+        this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        /*
+         * Safe thread register manually since we are not using LEAF_SP for {@link
+         * DeoptimizationStub#UNPACK_FRAMES}.
+         */
+        new Mov(l7, thread).emit(masm);
+
+        // Clear last Java frame values.
+        new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
+        new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm);
+        new Stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)).emit(masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Mon Apr 28 11:18:15 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.*;
@@ -44,8 +43,11 @@
 
 public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements HotSpotNodeLIRBuilder {
 
-    public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) {
+    public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool 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));
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.sparc.SPARC.*;
+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.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Pushes an interpreter frame to the stack.
+ */
+@Opcode("PUSH_INTERPRETER_FRAME")
+final class SPARCHotSpotPushInterpreterFrameOp extends SPARCLIRInstruction {
+
+    @Alive(REG) AllocatableValue frameSize;
+    @Alive(REG) AllocatableValue framePc;
+    @Alive(REG) AllocatableValue senderSp;
+    @Alive(REG) AllocatableValue initialInfo;
+
+    SPARCHotSpotPushInterpreterFrameOp(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, SPARCMacroAssembler masm) {
+        final Register frameSizeRegister = asRegister(frameSize);
+        final Register framePcRegister = asRegister(framePc);
+        final Register senderSpRegister = asRegister(senderSp);
+
+        // Save sender SP to O5_savedSP.
+        new Mov(senderSpRegister, o5).emit(masm);
+
+        new Neg(frameSizeRegister).emit(masm);
+        new Save(sp, frameSizeRegister, sp).emit(masm);
+
+        new Mov(i0, o0).emit(masm);
+        new Mov(i1, o1).emit(masm);
+        new Mov(i2, o2).emit(masm);
+        new Mov(i3, o3).emit(masm);
+        new Mov(i4, o4).emit(masm);
+
+        // NOTE: Don't touch I5 as it contains valuable saved SP!
+
+        // Move frame's new PC into i7
+        new Mov(framePcRegister, i7).emit(masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Apr 28 11:18:15 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.*;
@@ -98,25 +98,27 @@
 
     private static Register[] initAllocatable(boolean reserveForHeapBase) {
         Register[] registers = null;
-        // @formatter:off
         if (reserveForHeapBase) {
-            registers = new Register[] {
+            // @formatter:off
+            registers = new Register[]{
                         // TODO this is not complete
                         o0, o1, o2, o3, o4, o5, /*o6,*/ o7,
                         l0, l1, l2, l3, l4, l5, l6, l7,
                         i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
                         f0, f1, f2, f3, f4, f5, f6, f7
-                      };
+            };
+            // @formatter:on
         } else {
-            registers = new Register[] {
+            // @formatter:off
+            registers = new Register[]{
                         // TODO this is not complete
                         o0, o1, o2, o3, o4, o5, /*o6,*/ o7,
                         l0, l1, l2, l3, l4, l5, l6, l7,
                         i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
                         f0, f1, f2, f3, f4, f5, f6, f7
-                      };
+            };
+            // @formatter:on
         }
-       // @formatter:on
 
         if (RegisterPressure.getValue() != null) {
             String[] names = RegisterPressure.getValue().split(",");
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -33,8 +33,10 @@
 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.*;
+
+import edu.umd.cs.findbugs.annotations.*;
 
 /**
  * Emits a safepoint poll.
@@ -43,7 +45,7 @@
 public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction {
 
     @State protected LIRFrameState state;
-    @Temp({OperandFlag.REG}) private AllocatableValue temp;
+    @SuppressFBWarnings(value = "BC_IMPOSSIBLE_CAST", justification = "changed by the register allocator") @Temp({OperandFlag.REG}) private AllocatableValue temp;
 
     private final HotSpotVMConfig config;
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Apr 28 11:18:15 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.*;
 
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Mon Apr 28 11:18:15 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/HotSpotMonitorValueTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java	Mon Apr 28 11:18:15 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 {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Mon Apr 28 11:18:15 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.*;
 
@@ -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/WriteBarrierVerificationTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Apr 28 11:18:15 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.*;
@@ -312,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());
@@ -363,7 +363,6 @@
      */
     private void printCompilation() {
         final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI;
-        final int mod = method.getModifiers();
         String compilerName = "";
         if (HotSpotCIPrintCompilerName.getValue()) {
             compilerName = "Graal:";
@@ -380,14 +379,14 @@
             compLevelString = "";
         }
         boolean hasExceptionHandlers = method.getExceptionHandlers().length > 0;
-        TTY.println(String.format("%s%7d %4d %c%c%c%c%c %s      %s %s(%d bytes)", compilerName, backend.getRuntime().compilerToVm.getTimeStamp(), id, isOSR ? '%' : ' ',
-                        Modifier.isSynchronized(mod) ? 's' : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', Modifier.isNative(mod) ? 'n' : ' ', compLevelString,
-                        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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,6 +27,7 @@
 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.*;
@@ -35,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.*;
 
@@ -45,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
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Mon Apr 28 11:18:15 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/HotSpotGraalRuntime.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Apr 28 11:18:15 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.*;
@@ -37,8 +37,8 @@
 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.*;
@@ -445,10 +445,12 @@
         }
     }
 
-    public Iterable<InspectedFrame> getStackTrace(final ResolvedJavaMethod initialMethod, final ResolvedJavaMethod matchingMethod) {
+    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, (HotSpotResolvedJavaMethod) initialMethod);
+            private HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, initialMetaMethods, initialSkip);
             // we don't want to read ahead if hasNext isn't called
             private boolean advanced = true;
 
@@ -465,7 +467,7 @@
 
             private void update() {
                 if (!advanced) {
-                    current = compilerToVm.getNextStackFrame(current, (HotSpotResolvedJavaMethod) matchingMethod);
+                    current = compilerToVm.getNextStackFrame(current, matchingMetaMethods, 0);
                     advanced = true;
                 }
             }
@@ -476,4 +478,16 @@
             }
         };
     }
+
+    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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Mon Apr 28 11:18:15 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.*;
 
@@ -63,7 +63,7 @@
             try (Scope s = Debug.scope("RegisterReplacements", new DebugDumpScope("RegisterReplacements"))) {
                 ServiceLoader<ReplacementsProvider> sl = ServiceLoader.loadInstalled(ReplacementsProvider.class);
                 for (ReplacementsProvider replacementsProvider : sl) {
-                    replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, replacements, providers.getCodeCache().getTarget());
+                    replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, providers.getSnippetReflection(), replacements, providers.getCodeCache().getTarget());
                 }
                 if (BootstrapReplacements.getValue()) {
                     for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,16 +24,16 @@
 
 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.
@@ -43,8 +43,22 @@
      */
     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.
      */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,10 +27,10 @@
 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.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Apr 28 11:18:15 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 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.*;
 
@@ -794,6 +794,7 @@
     // offsets, ...
     @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages;
     @HotSpotVMFlag(name = "UseStackBanging") @Stable public boolean useStackBanging;
+    @HotSpotVMConstant(name = "STACK_BIAS") @Stable public int stackBias;
 
     @HotSpotVMField(name = "oopDesc::_mark", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset;
     @HotSpotVMField(name = "oopDesc::_metadata._klass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset;
@@ -962,7 +963,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;
@@ -1010,16 +1014,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;
@@ -1055,6 +1062,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;
@@ -1245,6 +1253,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;
@@ -1283,6 +1292,10 @@
         return threadTlabOffset + threadLocalAllocBufferTopOffset;
     }
 
+    public int threadTlabPfTopOffset() {
+        return threadTlabOffset + threadLocalAllocBufferPfTopOffset;
+    }
+
     @HotSpotVMFlag(name = "TLABStats") @Stable public boolean tlabStats;
     @Stable public boolean inlineContiguousAllocationSupported;
 
@@ -1341,7 +1354,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;
@@ -1411,6 +1423,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;
@@ -1441,6 +1457,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;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Apr 28 11:18:15 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.*;
 
@@ -226,7 +226,7 @@
      * @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.
@@ -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);
 
@@ -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);
 
@@ -284,8 +284,6 @@
 
     Class<?> getJavaMirror(long metaspaceKlass);
 
-    void setNodeClass(Class<?> c, NodeClass nodeClass);
-
     long readUnsafeKlassPointer(Object o);
 
     void doNotInlineOrCompile(long metaspaceMethod);
@@ -297,7 +295,7 @@
      */
     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.
@@ -339,10 +337,11 @@
      * 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 method the method to look for, where {@code null} means that any frame is returned
+     * @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, HotSpotResolvedJavaMethod method);
+    HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, long[] methods, int initialSkip);
 
     /**
      * Materialized all virtual objects within the given stack frame and update the locals within
@@ -352,4 +351,6 @@
      *            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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,7 +24,6 @@
 package com.oracle.graal.hotspot.bridge;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -33,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));
     }
 
@@ -121,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);
@@ -139,27 +138,24 @@
     public native void reprofile(long metaspaceMethod);
 
     @Override
-    public native void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
+    public native void invalidateInstalledCode(InstalledCode hotspotInstalledCode);
 
     @Override
     public native Class<?> getJavaMirror(long metaspaceKlass);
 
     @Override
-    public native void setNodeClass(Class<?> c, NodeClass nodeClass);
-
-    @Override
     public native long readUnsafeKlassPointer(Object o);
 
     @Override
     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);
 
@@ -179,9 +175,11 @@
 
     public native boolean hasCompiledCodeForOSR(long metaspaceMethod, int entryBCI, int level);
 
-    public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethod method);
+    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	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +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.replacements.*;
-
-/**
- * Updates the {@code InstanceKlass::_graal_node_class} field when a {@link NodeClass} is created so
- * that the {@link HotSpotNodeClassSubstitutions} and {@link HotSpotNodeSubstitutions}
- * intrinsifications can read it.
- */
-class FastNodeClassRegistry extends NodeClass.Registry {
-
-    private final CompilerToVM vm;
-
-    public FastNodeClassRegistry(CompilerToVM vm) {
-        this.vm = vm;
-    }
-
-    @SuppressWarnings("unused")
-    static void initialize(CompilerToVM vm) {
-        new FastNodeClassRegistry(vm);
-    }
-
-    @Override
-    protected void registered(Class<? extends Node> key, NodeClass value) {
-        vm.setNodeClass(key, value);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Mon Apr 28 11:18:15 2014 +0200
@@ -38,11 +38,7 @@
 
     void shutdownCompiler() throws Exception;
 
-    /**
-     * @param hostedOnly specifies if the Graal compiler is only being used in hosted mode (i.e., it
-     *            will never compile itself)
-     */
-    void startCompiler(boolean bootstrapEnabled, boolean hostedOnly) throws Throwable;
+    void startCompiler(boolean bootstrapEnabled) throws Throwable;
 
     void bootstrap() throws Throwable;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Apr 28 11:18:15 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;
@@ -142,11 +142,7 @@
         this.runtime = runtime;
     }
 
-    public void startCompiler(boolean bootstrapEnabled, boolean hostedOnly) throws Throwable {
-
-        if (!hostedOnly) {
-            FastNodeClassRegistry.initialize(runtime.getCompilerToVM());
-        }
+    public void startCompiler(boolean bootstrapEnabled) throws Throwable {
 
         bootstrapRunning = bootstrapEnabled;
 
@@ -349,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Mon Apr 28 11:18:15 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.*;
 
@@ -99,7 +99,6 @@
 
     private static final boolean DUMP_STATIC = false;
 
-    public static String excludedClassPrefix = null;
     public static boolean enabled = false;
 
     public static final ConcurrentHashMap<String, Integer> indexes = new ConcurrentHashMap<>();
@@ -108,14 +107,23 @@
     public static final ArrayList<AtomicLong> staticCounters = new ArrayList<>();
 
     @SuppressFBWarnings(value = "AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION", justification = "concurrent abstraction calls are in synchronized block")
-    public static int getIndex(DynamicCounterNode counter) {
+    private static int getIndex(DynamicCounterNode counter) {
         if (!enabled) {
             throw new GraalInternalError("counter nodes shouldn't exist when counters are not enabled: " + counter.getGroup() + ", " + counter.getName());
         }
-        String name = counter.getName();
+        String name;
         String group = counter.getGroup();
-        name = counter.isWithContext() && counter.graph().method() != null ? name + " @ " + counter.graph().graphId() + ":" + MetaUtil.format("%h.%n", counter.graph().method()) + "#" + group : name +
-                        "#" + group;
+        if (counter.isWithContext()) {
+            StructuredGraph graph = counter.graph();
+            name = counter.getName() + " @ " + graph.graphId() + ":" + (graph.method() == null ? "" : MetaUtil.format("%h.%n", graph.method()));
+            if (graph.name != null) {
+                name += " (" + graph.name + ")";
+            }
+            name += "#" + group;
+
+        } else {
+            name = counter.getName() + "#" + group;
+        }
         Integer index = indexes.get(name);
         if (index == null) {
             synchronized (BenchmarkCounters.class) {
@@ -135,7 +143,7 @@
         return index;
     }
 
-    public static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) {
+    private static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) {
         if (!groups.isEmpty()) {
             out.println("====== dynamic counters (" + staticCounters.size() + " in total) ======");
             for (String group : new TreeSet<>(groups)) {
@@ -152,7 +160,7 @@
         }
     }
 
-    public static synchronized void clear(long[] counters) {
+    private static synchronized void clear(long[] counters) {
         delta = counters;
     }
 
@@ -228,7 +236,7 @@
         return (counter * 200 + 1) / sum / 2;
     }
 
-    public abstract static class CallbackOutputStream extends OutputStream {
+    private abstract static class CallbackOutputStream extends OutputStream {
 
         protected final PrintStream delegate;
         private final byte[][] patterns;
@@ -281,25 +289,30 @@
         final class BenchmarkCountersOutputStream extends CallbackOutputStream {
 
             private long startTime;
+            private boolean running;
             private boolean waitingForEnd;
 
             private BenchmarkCountersOutputStream(PrintStream delegate, String start, String end) {
-                super(delegate, new String[]{start, end, "\n"});
+                super(delegate, new String[]{"\n", end, start});
             }
 
             @Override
             protected void patternFound(int index) {
                 switch (index) {
-                    case 0:
+                    case 2:
                         startTime = System.nanoTime();
                         BenchmarkCounters.clear(compilerToVM.collectCounters());
+                        running = true;
                         break;
                     case 1:
-                        waitingForEnd = true;
+                        if (running) {
+                            waitingForEnd = true;
+                        }
                         break;
-                    case 2:
+                    case 0:
                         if (waitingForEnd) {
                             waitingForEnd = false;
+                            running = false;
                             BenchmarkCounters.dump(delegate, (System.nanoTime() - startTime) / 1000000000d, compilerToVM.collectCounters(), 100);
                         }
                         break;
@@ -321,7 +334,6 @@
                     throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: err|out");
                 }
             }
-            excludedClassPrefix = "Lcom/oracle/graal/";
             enabled = true;
         }
         if (Options.GenericDynamicCounters.getValue()) {
@@ -363,26 +375,24 @@
 
     public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) {
         StructuredGraph graph = counter.graph();
-        if (excludedClassPrefix == null || (counter.graph().method() != null && !counter.graph().method().getDeclaringClass().getName().startsWith(excludedClassPrefix))) {
 
-            ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false));
+        ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false));
 
-            int index = BenchmarkCounters.getIndex(counter);
-            if (index >= config.graalCountersSize) {
-                throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")");
-            }
-            ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, config.graalCountersThreadOffset, graph);
-            ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false));
-            ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
-            ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false));
-            IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement()));
-            WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE, false));
+        int index = BenchmarkCounters.getIndex(counter);
+        if (index >= config.graalCountersSize) {
+            throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")");
+        }
+        ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, wordKind, config.graalCountersThreadOffset, graph);
+        ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false));
+        ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
+        ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false));
+        IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement()));
+        WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE, false));
 
-            graph.addBeforeFixed(counter, thread);
-            graph.addBeforeFixed(counter, readArray);
-            graph.addBeforeFixed(counter, read);
-            graph.addBeforeFixed(counter, write);
-        }
+        graph.addBeforeFixed(counter, thread);
+        graph.addBeforeFixed(counter, readArray);
+        graph.addBeforeFixed(counter, read);
+        graph.addBeforeFixed(counter, write);
         graph.removeFixed(counter);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -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.*;
@@ -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) {
@@ -188,8 +192,10 @@
             if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
                 newObjectSnippets.lower((NewMultiArrayNode) n, tool);
             }
-        } else if (n instanceof LoadExceptionObjectNode) {
-            exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool);
+        } else if (n instanceof ExceptionObjectNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                lowerExceptionObjectNode((ExceptionObjectNode) n, tool);
+            }
         } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
             // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
             // zero and the MIN_VALUE / -1 cases.
@@ -219,7 +225,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);
             }
@@ -378,11 +384,27 @@
         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, getCompareAndSwapBarrier(cas), false));
+        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();
@@ -409,10 +431,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));
@@ -474,7 +496,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);
             }
         }
@@ -712,6 +734,19 @@
         }
     }
 
+    private void lowerExceptionObjectNode(ExceptionObjectNode n, LoweringTool tool) {
+        LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) n.predecessor()).getLocationIdentity();
+        BeginNode entry = n.graph().add(new KillingBeginNode(locationsKilledByInvoke));
+        LoadExceptionObjectNode loadException = n.graph().add(new LoadExceptionObjectNode(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Throwable.class))));
+
+        loadException.setStateAfter(n.stateAfter());
+        n.replaceAtUsages(InputType.Value, loadException);
+        n.graph().replaceFixedWithFixed(n, entry);
+        entry.graph().addAfterFixed(entry, loadException);
+
+        exceptionObjectSnippets.lower(loadException, registers, tool);
+    }
+
     public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) {
         StructuredGraph graph = commit.graph();
         for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
@@ -787,8 +822,8 @@
 
     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;
             }
@@ -816,7 +851,7 @@
 
         Stamp hubStamp;
         if (config.useCompressedClassPointers) {
-            hubStamp = StampFactory.forInteger(32, false);
+            hubStamp = StampFactory.forInteger(32);
         } else {
             hubStamp = StampFactory.forKind(wordKind);
         }
@@ -851,45 +886,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) {
@@ -976,7 +1019,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/HotSpotCodeCacheProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Mon Apr 28 11:18:15 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
@@ -256,7 +260,9 @@
 
     public Data createDataItem(Constant constant, int alignment) {
         if (constant instanceof HotSpotMetaspaceConstant) {
-            return new MetaspaceData(alignment, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), false);
+            // 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, HotSpotObjectConstant.asObject(constant), false);
         } else {
@@ -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;
@@ -280,4 +286,8 @@
     public String disassemble(ResolvedJavaMethod method) {
         return new BytecodeDisassembler().disassemble(method);
     }
+
+    public SpeculationLog createSpeculationLog() {
+        return new HotSpotSpeculationLog();
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Mon Apr 28 11:18:15 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.*;
 
 /**
@@ -501,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:
@@ -517,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:
@@ -534,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Mon Apr 28 11:18:15 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.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Mon Apr 28 11:18:15 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,6 +38,7 @@
 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.*;
@@ -64,7 +66,7 @@
         super(runtime, metaAccess, codeCache);
     }
 
-    private static void link(Stub stub) {
+    protected static void link(Stub stub) {
         stub.getLinkage().setCompiledStub(stub);
     }
 
@@ -101,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);
 
@@ -114,8 +115,18 @@
 
         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);
+
+        /*
+         * We cannot use LEAF_SP here because on some architectures we have to align the stack
+         * manually before calling into the VM. See {@link
+         * AMD64HotSpotEnterUnpackFramesStackFrameOp#emitCode}.
+         */
+        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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Mon Apr 28 11:18:15 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/HotSpotMetaAccessProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Mon Apr 28 11:18:15 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.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Mon Apr 28 11:18:15 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;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Apr 28 11:18:15 2014 +0200
@@ -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.*;
@@ -174,8 +173,6 @@
 
                 fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK")));
                 fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL")));
-
-                fields.add(metaAccess.lookupJavaField(NodeClass.class.getDeclaredField("registry")));
             } catch (SecurityException | NoSuchFieldException e) {
                 throw new GraalInternalError(e);
             }
@@ -202,8 +199,8 @@
         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);
                 }
@@ -213,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);
+            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;
@@ -250,7 +247,7 @@
      *         {@code object}'s class
      */
     public boolean isInObject(Object object) {
-        if (isStatic(modifiers)) {
+        if (isStatic()) {
             return false;
         }
         return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectType.fromClass(object.getClass()));
@@ -259,13 +256,13 @@
     @Override
     public Constant readValue(Constant receiver) {
         if (receiver == null) {
-            assert isStatic(modifiers);
+            assert isStatic();
             if (holder.isInitialized()) {
                 return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), HotSpotObjectConstant.forObject(holder.mirror()), offset);
             }
             return null;
         } else {
-            assert !isStatic(modifiers);
+            assert !isStatic();
             assert receiver.isNonNull() && isInObject(HotSpotObjectConstant.asObject(receiver));
             return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver, offset);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Apr 28 11:18:15 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,7 +56,6 @@
     private final HotSpotSignature signature;
     private HotSpotMethodData methodData;
     private byte[] code;
-    private SpeculationLog speculationLog;
 
     /**
      * Gets the holder of a HotSpot metaspace method native object.
@@ -162,6 +162,10 @@
         return HotSpotMetaspaceConstant.forMetaspaceObject(getHostWordKind(), metaspaceMethod, this);
     }
 
+    public long getMetaspaceMethod() {
+        return metaspaceMethod;
+    }
+
     @Override
     public Constant getEncoding() {
         return getMetaspaceMethodConstant();
@@ -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
@@ -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();
@@ -612,15 +613,40 @@
      * @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 HotSpotSpeculationLog();
+        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() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Mon Apr 28 11:18:15 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.*;
 
 /**
@@ -141,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());
 
@@ -157,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;
@@ -255,7 +253,7 @@
         if (isArray()) {
             return getComponentType().asExactType() != null ? this : null;
         }
-        return isFinal(getModifiers()) ? this : null;
+        return isFinal() ? this : null;
     }
 
     @Override
@@ -358,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;
         }
 
@@ -367,7 +365,7 @@
             return null;
         }
         HotSpotResolvedJavaMethod resolvedMethod = HotSpotResolvedJavaMethod.fromMetaspace(resolvedMetaspaceMethod);
-        if (isAbstract(resolvedMethod.getModifiers())) {
+        if (resolvedMethod.isAbstract()) {
             return null;
         }
         return resolvedMethod;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Mon Apr 28 11:18:15 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.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java	Mon Apr 28 11:18:15 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.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,9 +26,9 @@
 
 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 {
 
@@ -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) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Mon Apr 28 11:18:15 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.*;
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Mon Apr 28 11:18:15 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.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,18 +26,16 @@
 
 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.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.*;
 
 /**
  * Reserves a block of memory in the stack frame of a method. The block is reserved in the frame for
  * the entire execution of the associated method.
  */
-public final class AllocaNode extends FixedWithNextNode implements LIRGenResLowerable {
+public final class AllocaNode extends FixedWithNextNode implements LIRLowerable {
 
     /**
      * The number of slots in block.
@@ -58,8 +56,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) {
-        StackSlot array = res.getFrameMap().allocateStackSlots(slots, objects, null);
+    public void generate(NodeLIRBuilderTool gen) {
+        StackSlot array = gen.getLIRGeneratorTool().getResult().getFrameMap().allocateStackSlots(slots, objects, null);
         Value result = gen.getLIRGeneratorTool().emitAddress(array);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,12 +24,11 @@
 
 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.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -39,7 +38,7 @@
  * check on the object.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorEnter, MemoryCheckpoint.Single {
+public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single {
 
     private int lockDepth;
 
@@ -59,7 +58,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         assert lockDepth != -1;
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool();
         StackSlot slot = hsGen.getLockSlot(lockDepth);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,6 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -32,7 +30,7 @@
 /**
  * Converts a compile-time constant Java string into a C string installed with the generated code.
  */
-public final class CStringNode extends FloatingNode implements LIRGenLowerable {
+public final class CStringNode extends FloatingNode implements LIRLowerable {
 
     private final String string;
 
@@ -41,7 +39,7 @@
         this.string = string;
     }
 
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         gen.setResult(this, emitCString(gen, string));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Mon Apr 28 11:18:15 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,13 +86,17 @@
                 } else if (input instanceof IntegerStamp) {
                     // metaspace pointer
                     assert PrimitiveStamp.getBits(input) == 32;
-                    return StampFactory.forInteger(64, false);
+                    return StampFactory.forInteger(64);
                 }
                 break;
         }
         throw GraalInternalError.shouldNotReachHere();
     }
 
+    public ValueNode getInput() {
+        return input;
+    }
+
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (input instanceof CompressionNode) {
@@ -107,7 +113,7 @@
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool();
         boolean nonNull;
         if (input.stamp() instanceof ObjectStamp) {
-            nonNull = ObjectStamp.isObjectNonNull(input.stamp());
+            nonNull = StampTool.isObjectNonNull(input.stamp());
         } else {
             // metaspace pointers are never null
             nonNull = true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,8 +28,7 @@
 
 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.*;
@@ -38,7 +37,7 @@
  * Intrinsic for allocating an on-stack array of integers to hold the dimensions of a multianewarray
  * instruction.
  */
-public final class DimensionsNode extends FixedWithNextNode implements LIRGenResLowerable {
+public final class DimensionsNode extends FixedWithNextNode implements LIRLowerable {
 
     private final int rank;
 
@@ -48,12 +47,13 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) {
+    public void generate(NodeLIRBuilderTool gen) {
+        LIRGeneratorTool lirGen = gen.getLIRGeneratorTool();
         int size = rank * 4;
-        int wordSize = gen.getLIRGeneratorTool().target().wordSize;
+        int wordSize = lirGen.target().wordSize;
         int slots = roundUp(size, wordSize) / wordSize;
-        StackSlot array = res.getFrameMap().allocateStackSlots(slots, new BitSet(0), null);
-        Value result = gen.getLIRGeneratorTool().emitAddress(array);
+        StackSlot array = lirGen.getResult().getFrameMap().allocateStackSlots(slots, new BitSet(0), null);
+        Value result = lirGen.emitAddress(array);
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,13 +23,12 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -39,7 +38,7 @@
  * expected value or the compared against value instead of a boolean.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRGenLowerable, MemoryCheckpoint.Single {
+public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
@@ -79,7 +78,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         ((HotSpotNodeLIRBuilder) gen).visitDirectCompareAndSwap(this);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Mon Apr 28 11:18:15 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 {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotMatchableNodes.java	Mon Apr 28 11:18:15 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.hotspot.nodes;
+
+import com.oracle.graal.compiler.match.*;
+import com.oracle.graal.nodes.*;
+
+@MatchableNode(shortName = "Compression", value = CompressionNode.class, inputs = 1, adapter = HotSpotMatchableNodes.CompressionNodeAdapter.class)
+public class HotSpotMatchableNodes {
+    public static class CompressionNodeAdapter extends MatchNodeAdapter {
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((CompressionNode) node).getInput();
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadExceptionObjectNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable {
+
+    public LoadExceptionObjectNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,8 +26,6 @@
 
 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.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -35,16 +33,16 @@
 /**
  * Node that is used to maintain a stack based counter of how many locks are currently held.
  */
-public final class MonitorCounterNode extends FloatingNode implements LIRGenResLowerable {
+public final class MonitorCounterNode extends FloatingNode implements LIRLowerable {
 
     private MonitorCounterNode() {
         super(null);
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) {
+    public void generate(NodeLIRBuilderTool gen) {
         assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance";
-        StackSlot counter = res.getFrameMap().allocateStackSlots(1, new BitSet(0), null);
+        StackSlot counter = gen.getLIRGeneratorTool().getResult().getFrameMap().allocateStackSlots(1, new BitSet(0), null);
         Value result = gen.getLIRGeneratorTool().emitAddress(counter);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,19 +24,18 @@
 
 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.compiler.common.type.*;
 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.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
  * A call to the {@link NewArrayStub}.
  */
-public class NewArrayStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
+public class NewArrayStubCall extends DeoptimizingStubCall implements LIRLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -61,9 +60,9 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool 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.getLIRGeneratorTool().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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,14 +23,13 @@
 
 package com.oracle.graal.hotspot.nodes;
 
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
-public class PrefetchAllocateNode extends FixedWithNextNode implements LIRGenLowerable {
+public class PrefetchAllocateNode extends FixedWithNextNode implements LIRLowerable {
 
     @Input private ValueNode distance;
     @Input private ValueNode address;
@@ -42,7 +41,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         ((HotSpotNodeLIRBuilder) gen).emitPrefetchAllocate(address, distance);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,25 +24,23 @@
 
 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.target.*;
+import com.oracle.graal.compiler.common.type.*;
 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
  * supplied FrameState.
  */
-public class TailcallNode extends FixedWithNextNode implements LIRGenResLowerable {
+public class TailcallNode extends FixedWithNextNode implements LIRLowerable {
 
     @Input(InputType.State) private FrameState frameState;
     @Input private ValueNode target;
@@ -59,20 +57,21 @@
         this.frameState = frameState;
     }
 
-    public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) {
+    public void generate(NodeLIRBuilderTool gen) {
         HotSpotVMConfig config = runtime().getConfig();
+        LIRGeneratorTool lirGen = gen.getLIRGeneratorTool();
         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);
+        CallingConvention cc = lirGen.getResult().getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, lirGen.target(), false);
         List<ValueNode> parameters = new ArrayList<>();
         for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += HIRFrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) {
             parameters.add(frameState.localAt(slot));
         }
         Value[] args = gen.visitInvokeArguments(cc, parameters);
-        Value address = gen.getLIRGeneratorTool().emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0);
-        Value entry = gen.getLIRGeneratorTool().emitLoad(Kind.Long, address, null);
+        Value address = lirGen.emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0);
+        Value entry = lirGen.emitLoad(Kind.Long, address, null);
         HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen;
         hsgen.emitTailcall(args, entry);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,6 +27,7 @@
 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.*;
 
@@ -45,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);
                 }
             }
@@ -61,6 +62,13 @@
         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")
     private static boolean isInternedString(ConstantNode node) {
         if (!isObject(node)) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Mon Apr 28 11:18:15 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
      */
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Mon Apr 28 11:18:15 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/CallSiteSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -34,7 +34,7 @@
 public class CallSiteSubstitutions implements ReplacementsProvider {
 
     @Override
-    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) {
+    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) {
         replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class);
         replacements.registerSubstitutions(MutableCallSiteSubstitutions.class);
         replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,6 +31,7 @@
 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.*;
@@ -38,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.replacements.*;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java	Mon Apr 28 11:18:15 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.replacements.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.nodes.PiNode.*;
-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.replacements.*;
@@ -33,7 +31,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
-import com.oracle.graal.word.*;
 
 /**
  * Substitutions for improving the performance of {@link NodeClass#get}.
@@ -61,15 +58,12 @@
         }
     }
 
+    /**
+     * 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)
-    @MethodSubstitution(isStatic = true)
-    public static NodeClass get(Class<?> c) {
-        Word klass = loadWordFromObject(c, klassOffset());
-        NodeClass nc = piCastExact(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
-        if (nc != null) {
-            return nc;
-        }
-        return get(c);
-
-    }
+    public static native NodeClass get(Class<?> c);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -33,16 +33,15 @@
 public class HotSpotNodeSubstitutions {
 
     /**
-     * Partial substitution of {@link Node#getNodeClass()} that returns the value of the
-     * {@code InstanceKlass::_graal_node_class} field if it is non-null.
+     * 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 thisObj) {
-        Word klass = loadHub(thisObj);
-        NodeClass nc = piCastExact(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
-        if (nc != null) {
-            return nc;
-        }
-        return getNodeClass(thisObj);
+    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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Apr 28 11:18:15 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) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,7 @@
 
 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.nodes.spi.*;
 import com.oracle.graal.replacements.*;
@@ -32,7 +33,7 @@
 public class HotSpotSubstitutions implements ReplacementsProvider {
 
     @Override
-    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) {
+    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) {
         replacements.registerSubstitutions(ObjectSubstitutions.class);
         replacements.registerSubstitutions(SystemSubstitutions.class);
         replacements.registerSubstitutions(ThreadSubstitutions.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Apr 28 11:18:15 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,7 +41,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.options.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Apr 28 11:18:15 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.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.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
@@ -44,6 +44,12 @@
 
 /**
  * Snippet for loading the exception object at the start of an exception dispatcher.
+ * <p>
+ * The frame state upon entry to an exception handler is such that it is a
+ * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly the
+ * exception object (per the JVM spec) to rethrow. This means that the code generated for this node
+ * must not cause a deoptimization as the runtime/interpreter would not have a valid location to
+ * find the exception object to be rethrown.
  */
 public class LoadExceptionObjectSnippets implements Snippets {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Apr 28 11:18:15 2014 +0200
@@ -457,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 {
@@ -511,7 +511,7 @@
                         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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Apr 28 11:18:15 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,7 +47,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.options.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -105,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);
 
@@ -347,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) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java	Mon Apr 28 11:18:15 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.hotspot.meta.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Mon Apr 28 11:18:15 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/WriteBarrierSnippets.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Apr 28 11:18:15 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,7 +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.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,292 @@
+/*
+ * 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
+        // 2: deoptimizing frame
+        // 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.
+         *
+         * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository.
+         */
+        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()) + stackBias(), 0);
+        }
+
+        // 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;
+    }
+
+    /**
+     * Returns the stack bias for the host architecture.
+     *
+     * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository.
+     *
+     * @return stack bias
+     */
+    @Deprecated
+    @Fold
+    private static int stackBias() {
+        return config().stackBias;
+    }
+
+    @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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Mon Apr 28 11:18:15 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());
-
         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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Apr 28 11:18:15 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.nodes.DirectCompareAndSwapNode.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.stubs.StubUtil.*;
@@ -61,15 +60,9 @@
     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());
-
         Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER);
         args.add("hub", null);
-        args.addConst("intArrayHub", intArrayHub);
+        args.addConst("intArrayHub", intArrayType.klass());
         args.addConst("threadRegister", providers.getRegisters().getThreadRegister());
         return args;
     }
@@ -231,7 +224,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Mon Apr 28 11:18:15 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.meta.*;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Apr 28 11:18:15 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.hsail/src/com/oracle/graal/hsail/HSAIL.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java	Mon Apr 28 11:18:15 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/src/com/oracle/graal/java/AbstractBytecodeParser.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Apr 28 11:18:15 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,12 +32,11 @@
 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.*;
 
@@ -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:
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -69,6 +69,12 @@
     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;
         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Mon Apr 28 11:18:15 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,6 +82,12 @@
         public boolean isLoopHeader;
         public int loopId;
 
+        /**
+         * XXX to be removed - currently only used by baseline compiler
+         */
+        public Loop<BciBlock> loop;
+        public boolean isLoopEnd;
+
         public FixedWithNextNode firstInstruction;
         public AbstractFrameStateBuilder<?, ?> entryState;
 
@@ -144,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() {
@@ -159,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) {
@@ -716,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/GraphBuilderPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,10 +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.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.*;
@@ -36,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;
@@ -44,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;
@@ -217,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);
                     }
@@ -282,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;
@@ -407,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();
@@ -417,7 +416,7 @@
                  * unwind immediately.
                  */
                 if (bci != currentBlock.endBci || dispatchBlock == null) {
-                    dispatchBlock = unwindBlock(bci);
+                    dispatchBlock = unwindBlock();
                 }
 
                 HIRFrameStateBuilder dispatchState = frameState.copy();
@@ -634,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));
@@ -721,7 +720,7 @@
                      * https://wikis.oracle.com/display/HotSpotInternals/Method+handles
                      * +and+invokedynamic
                      */
-                    boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers());
+                    boolean hasReceiver = !((ResolvedJavaMethod) target).isStatic();
                     Constant appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL);
                     if (appendix != null) {
                         frameState.apush(ConstantNode.forConstant(appendix, metaAccess, currentGraph));
@@ -814,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");
                 }
@@ -1077,17 +1076,17 @@
              * Returns a block begin node with the specified state. If the specified probability is
              * 0, the block deoptimizes immediately.
              */
-            private AbstractBeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder 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);
@@ -1153,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);
@@ -1186,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);
@@ -1197,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();
@@ -1299,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,18 +23,16 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.graph.iterators.NodePredicates.*;
-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.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, HIRFrameStateBuilder> {
@@ -55,7 +53,7 @@
 
         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);
@@ -259,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) {
@@ -328,6 +326,7 @@
         } finally {
             lockedObjects = lockedObjects.length == 1 ? EMPTY_ARRAY : Arrays.copyOf(lockedObjects, lockedObjects.length - 1);
             monitorIds = monitorIds.length == 1 ? EMPTY_MONITOR_ARRAY : Arrays.copyOf(monitorIds, monitorIds.length - 1);
+            assert lockedObjects.length == monitorIds.length;
         }
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java	Mon Apr 28 11:18:15 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.*;
@@ -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/except/Catch_NPE_07.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NPE_07.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,9 @@
 
 package com.oracle.graal.jtt.except;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -61,12 +62,12 @@
         }
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.except;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -49,17 +50,17 @@
         }
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 3);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.except;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -56,17 +57,17 @@
         }
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.except;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Throw_InNested extends JTTTest {
 
@@ -48,12 +49,12 @@
         return i;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.except;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Throw_Synchronized01 extends JTTTest {
 
@@ -38,12 +39,12 @@
         throw new Exception();
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.except;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Throw_Synchronized02 extends JTTTest {
 
@@ -36,12 +37,12 @@
         throw new Exception();
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.except;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Throw_Synchronized03 extends JTTTest {
 
@@ -41,12 +42,12 @@
         throw new Exception();
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.hotpath;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -37,27 +38,27 @@
         return sum;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 80);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,9 @@
 // Checkstyle: stop
 package com.oracle.graal.jtt.hotpath;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -55,12 +56,12 @@
         return (int) (b + c + s + i + l + f + d);
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 40);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1000);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 package com.oracle.graal.jtt.hotpath;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -104,12 +105,12 @@
         }
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 40);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 80);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,8 +25,9 @@
 
 import java.util.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -106,7 +107,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,9 @@
 // Checkstyle: stop
 package com.oracle.graal.jtt.hotpath;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -48,7 +49,7 @@
         return sum;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 15);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java	Mon Apr 28 11:18:15 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/Test6196102.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6196102.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.hotspot;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /**
  * @bug 6196102
@@ -46,7 +47,7 @@
         return "ok";
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.hotspot;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 //@formatter:off
 
@@ -50,7 +51,7 @@
         return 95;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java	Mon Apr 28 11:18:15 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/EnumMap02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/EnumMap02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.util.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -45,17 +46,17 @@
         C
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.io.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -58,7 +59,7 @@
         out.println(test(10000));
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 10000);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,10 +24,11 @@
 
 import java.lang.reflect.*;
 
+import org.junit.*;
+
 import sun.misc.*;
 
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -55,7 +56,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.net.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -43,22 +44,22 @@
         return null;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Class_Literal01 extends JTTTest {
 
@@ -45,27 +46,27 @@
         return null;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Class_asSubclass01 extends JTTTest {
 
@@ -53,27 +54,27 @@
         return i;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Class_cast01 extends JTTTest {
 
@@ -57,27 +58,27 @@
         return i;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Class_forName01 extends JTTTest {
 
@@ -45,27 +46,27 @@
         return null;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Class_forName02 extends JTTTest {
 
@@ -51,27 +52,27 @@
         return null;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.net.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -56,32 +57,32 @@
         return null;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -48,32 +49,32 @@
         return null;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.net.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -41,17 +42,17 @@
         return null;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -81,27 +82,27 @@
 
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Int_less02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Int_less02.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/JDK_ClassLoaders02.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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/lang/Object_getClass01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Object_getClass01 extends JTTTest {
 
@@ -49,27 +50,27 @@
         return null;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Object_toString01 extends JTTTest {
 
@@ -47,17 +48,17 @@
         return string;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -33,17 +34,17 @@
         return ("id" + i).intern() == ("id" + i).intern();
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -33,17 +34,17 @@
         return ("id" + i).intern().equals("id" + i);
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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/loop/LoopParseLong.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.loop;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class LoopParseLong extends JTTTest {
 
@@ -98,7 +99,7 @@
         return negative ? result : -result;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("testShortened", "7", 10);
         runTest("testShortened", "-100", 10);
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.loop;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -58,7 +59,7 @@
         return "" + ('a' + count);
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -33,7 +34,7 @@
         return p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java	Mon Apr 28 11:18:15 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/micro/Matrix01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/Matrix01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -155,32 +156,32 @@
         ((Matrix[]) array)[val % array.length] = new Matrix(number);
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -57,7 +58,7 @@
         return Integer.valueOf(foo(new String[]{"asdf"}));
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -58,7 +59,7 @@
         Object c = b;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.util.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -117,22 +118,22 @@
         return c2 ? 1 : 0;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 10);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 20);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 40);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.io.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -44,7 +45,7 @@
         return (String) arg;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", (Object) null);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.optimize;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  * Tests value numbering of instanceof operations.
@@ -76,17 +77,17 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -37,22 +38,22 @@
         return Class_getField01.class.getField(input).getName();
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", "test");
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", "field");
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", "field2");
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", "field3");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -42,27 +43,27 @@
         public String field4;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", "test");
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", "field");
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", "field2");
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", "field3");
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", "field4");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -39,17 +40,17 @@
         field = args[0];
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", "test");
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", "main");
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", "xx");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -52,37 +53,37 @@
         field = args[0];
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Class_newInstance03 extends JTTTest {
 
@@ -45,27 +46,27 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -59,47 +60,47 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @LongTest
+    @Test
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @LongTest
+    @Test
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -61,47 +62,47 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @LongTest
+    @Test
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @LongTest
+    @Test
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.lang.reflect.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -87,47 +88,47 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @LongTest
+    @Test
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @LongTest
+    @Test
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -61,47 +62,47 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @LongTest
+    @Test
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @LongTest
+    @Test
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -59,47 +60,47 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @LongTest
+    @Test
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @LongTest
+    @Test
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -67,47 +68,47 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @LongTest
+    @Test
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @LongTest
+    @Test
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -69,47 +70,47 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @LongTest
+    @Test
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @LongTest
+    @Test
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -69,47 +70,47 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @LongTest
+    @Test
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @LongTest
+    @Test
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @LongTest
+    @Test
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.lang.reflect.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -56,27 +57,27 @@
         return arg.length;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.lang.reflect.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -44,12 +45,12 @@
         field = args[0];
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", "test1");
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", "test2");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
 
 import java.lang.reflect.*;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -48,12 +49,12 @@
         field = args[0];
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", "test1");
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", "test2");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -51,22 +52,22 @@
     public void method3(int arg1, Object arg2) {
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -51,22 +52,22 @@
     public void method3() {
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Monitor_contended01 extends JTTTest implements Runnable {
 
@@ -71,7 +72,7 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Monitor_notowner01 extends JTTTest {
 
@@ -62,7 +63,7 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter02.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Object_wait01 extends JTTTest implements Runnable {
 
@@ -57,22 +58,22 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run2() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test(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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Object_wait02 extends JTTTest implements Runnable {
 
@@ -57,17 +58,17 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test(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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Object_wait03 extends JTTTest implements Runnable {
 
@@ -63,17 +64,17 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test(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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Object_wait04 extends JTTTest implements Runnable {
 
@@ -67,32 +68,32 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java	Mon Apr 28 11:18:15 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/ThreadLocal03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/ThreadLocal03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -59,22 +60,22 @@
         }
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Thread_getState02 extends JTTTest {
 
@@ -33,7 +34,7 @@
         return new Thread().getState() == Thread.State.NEW;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,8 +26,9 @@
 
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 //Test all, mainly monitors
 public class Thread_isInterrupted02 extends JTTTest {
@@ -85,12 +86,12 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 0, 0);
     }
 
-    @LongTest
+    @Test(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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -68,7 +69,7 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -66,7 +67,7 @@
 
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 /*
  */
@@ -66,7 +67,7 @@
         }
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Thread_join01 extends JTTTest implements Runnable {
 
@@ -43,7 +44,7 @@
         cont = false;
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,8 +27,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Thread_join02 extends JTTTest implements Runnable {
 
@@ -50,7 +51,7 @@
         cont = false;
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,8 +27,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Thread_join03 extends JTTTest implements Runnable {
 
@@ -47,7 +48,7 @@
         cont = false;
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Thread_new01 extends JTTTest {
 
@@ -45,27 +46,27 @@
         return false;
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public class Thread_new02 extends JTTTest implements Runnable {
 
@@ -51,27 +52,27 @@
         // do nothing.
     }
 
-    @LongTest
+    @Test
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @LongTest
+    @Test
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @LongTest
+    @Test
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @LongTest
+    @Test
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @LongTest
+    @Test
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,9 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import org.junit.*;
+
 import com.oracle.graal.jtt.*;
-import com.oracle.graal.test.*;
 
 public final class Thread_sleep01 extends JTTTest {
 
@@ -35,17 +36,17 @@
         return System.currentTimeMillis() - before >= i;
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run0() throws Throwable {
         runTest("test", 10);
     }
 
-    @LongTest
+    @Test(timeout = 20000)
     public void run1() throws Throwable {
         runTest("test", 20);
     }
 
-    @LongTest
+    @Test(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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_yield01.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Mon Apr 28 11:18:15 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.*;
@@ -39,8 +39,8 @@
 
     // @formatter:off
 
-    IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
-    LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, IROL, IROR,
+    LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, LROL, LROR,
     FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
     DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
     INEG, LNEG, INOT, LNOT,
@@ -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();
         }
@@ -473,6 +491,14 @@
                     assert asIntReg(src).equals(AMD64.rcx);
                     masm.shrl(asIntReg(dst));
                     break;
+                case IROL:
+                    assert asIntReg(src).equals(AMD64.rcx);
+                    masm.roll(asIntReg(dst));
+                    break;
+                case IROR:
+                    assert asIntReg(src).equals(AMD64.rcx);
+                    masm.roll(asIntReg(dst));
+                    break;
 
                 case LADD:
                     masm.addq(asLongReg(dst), asLongReg(src));
@@ -504,6 +530,14 @@
                     assert asIntReg(src).equals(AMD64.rcx);
                     masm.shrq(asLongReg(dst));
                     break;
+                case LROL:
+                    assert asIntReg(src).equals(AMD64.rcx);
+                    masm.rolq(asLongReg(dst));
+                    break;
+                case LROR:
+                    assert asIntReg(src).equals(AMD64.rcx);
+                    masm.rorq(asLongReg(dst));
+                    break;
 
                 case FADD:
                     masm.addss(asFloatReg(dst), asFloatReg(src));
@@ -568,6 +602,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;
@@ -674,6 +711,12 @@
                 case IUSHR:
                     masm.shrl(asIntReg(dst), crb.asIntConst(src) & 31);
                     break;
+                case IROL:
+                    masm.roll(asIntReg(dst), crb.asIntConst(src) & 31);
+                    break;
+                case IROR:
+                    masm.rorl(asIntReg(dst), crb.asIntConst(src) & 31);
+                    break;
 
                 case LADD:
                     masm.addq(asLongReg(dst), crb.asIntConst(src));
@@ -702,6 +745,12 @@
                 case LUSHR:
                     masm.shrq(asLongReg(dst), crb.asIntConst(src) & 63);
                     break;
+                case LROL:
+                    masm.rolq(asLongReg(dst), crb.asIntConst(src) & 31);
+                    break;
+                case LROR:
+                    masm.rorq(asLongReg(dst), crb.asIntConst(src) & 31);
+                    break;
 
                 case FADD:
                     masm.addss(asFloatReg(dst), (AMD64Address) crb.asFloatConstRef(src));
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Mon Apr 28 11:18:15 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.*;
@@ -132,6 +132,9 @@
                     default:
                         throw GraalInternalError.shouldNotReachHere();
                 }
+
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
             }
         }
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Mon Apr 28 11:18:15 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 {
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Apr 28 11:18:15 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;
@@ -432,6 +432,74 @@
         }
     }
 
+    @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();
+            }
+        }
+    }
+
     public static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
         move(result.getKind(), crb, masm, result, input);
     }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILBitManipulationOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,10 +26,10 @@
 
 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.
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Mon Apr 28 11:18:15 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.
@@ -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));
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Mon Apr 28 11:18:15 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
@@ -440,6 +447,65 @@
         }
     }
 
+    @Opcode("ATOMIC_READ_AND_ADD")
+    public static class AtomicReadAndAddOp extends HSAILLIRInstruction {
+
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Use({COMPOSITE}) protected HSAILAddressValue address;
+        @Use({REG, CONST}) protected Value delta;
+
+        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) {
+            switch (accessKind) {
+                case Int:
+                case Long:
+                    masm.emitAtomicAdd(result, address.toAddress(), delta);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Opcode("ATOMIC_READ_AND_WRITE")
+    public static class AtomicReadAndWriteOp extends HSAILLIRInstruction {
+
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Use({COMPOSITE}) protected HSAILAddressValue address;
+        @Use({REG, CONST}) protected Value newValue;
+
+        public AtomicReadAndWriteOp(Kind accessKind, AllocatableValue result, HSAILAddressValue address, Value newValue) {
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.newValue = newValue;
+        }
+
+        public HSAILAddressValue getAddress() {
+            return address;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+            masm.emitAtomicExch(accessKind, result, address.toAddress(), newValue);
+        }
+    }
+
     public static class NullCheckOp extends HSAILLIRInstruction {
 
         @Use protected Value input;
@@ -482,4 +548,5 @@
             throw GraalInternalError.shouldNotReachHere();
         }
     }
+
 }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXTestOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Apr 28 11:18:15 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
@@ -68,7 +68,7 @@
     FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
     DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
     INEG, LNEG, FNEG, DNEG, INOT, LNOT,
-    I2L, L2I, I2B, I2C, I2S,
+    L2I, B2I, S2I, B2L, S2L, I2L,
     F2D, D2F,
     I2F, I2D, F2I, D2I,
     L2F, L2D, F2L, D2L,
@@ -572,11 +572,11 @@
                 case L2I:
                     new Signx(asLongReg(src), asIntReg(dst)).emit(masm);
                     break;
-                case I2B:
+                case B2I:
                     new Sll(asIntReg(src), 24, asIntReg(dst)).emit(masm);
                     new Srl(asIntReg(dst), 24, asIntReg(dst)).emit(masm);
                     break;
-                case I2C:
+                case S2I:
                     new Sll(asIntReg(src), 16, asIntReg(dst)).emit(masm);
                     new Srl(asIntReg(dst), 16, asIntReg(dst)).emit(masm);
                     break;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Apr 28 11:18:15 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 {
 
@@ -270,13 +270,16 @@
     @Opcode("CMOVE")
     public static class CondMoveOp extends SPARCLIRInstruction {
 
+        private final Kind kind;
+
         @Def({REG, HINT}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Use({REG, STACK, CONST}) protected Value falseValue;
 
         private final ConditionFlag condition;
 
-        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+        public CondMoveOp(Kind kind, Variable result, Condition condition, Variable trueValue, Value falseValue) {
+            this.kind = kind;
             this.result = result;
             this.condition = intCond(condition);
             this.trueValue = trueValue;
@@ -285,20 +288,28 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            cmove(crb, masm, result, false, condition, false, trueValue, falseValue);
+            // check that we don't overwrite an input operand before it is used.
+            assert !result.equals(trueValue);
+
+            SPARCMove.move(crb, masm, result, falseValue);
+            cmove(crb, masm, kind, result, condition, trueValue);
         }
     }
 
     @Opcode("CMOVE")
     public static class FloatCondMoveOp extends SPARCLIRInstruction {
 
+        private final Kind kind;
+
         @Def({REG}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Alive({REG}) protected Value falseValue;
+
         private final ConditionFlag condition;
         private final boolean unorderedIsTrue;
 
-        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+        public FloatCondMoveOp(Kind kind, Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+            this.kind = kind;
             this.result = result;
             this.condition = floatCond(condition);
             this.unorderedIsTrue = unorderedIsTrue;
@@ -308,18 +319,12 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
-        }
-    }
+            // check that we don't overwrite an input operand before it is used.
+            assert !result.equals(trueValue);
 
-    private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, boolean isFloat, ConditionFlag condition, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
-        // check that we don't overwrite an input operand before it is used.
-        assert !result.equals(trueValue);
+            SPARCMove.move(crb, masm, result, falseValue);
+            cmove(crb, masm, kind, result, condition, trueValue);
 
-        SPARCMove.move(crb, masm, result, falseValue);
-        cmove(crb, masm, result, condition, trueValue);
-
-        if (isFloat) {
             if (unorderedIsTrue && !trueOnUnordered(condition)) {
                 // cmove(crb, masm, result, ConditionFlag.Parity, trueValue);
                 throw GraalInternalError.unimplemented();
@@ -330,18 +335,20 @@
         }
     }
 
-    private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, ConditionFlag cond, Value other) {
+    private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Kind kind, Value result, ConditionFlag cond, Value other) {
         if (!isRegister(other)) {
             SPARCMove.move(crb, masm, result, other);
-            throw new InternalError("result should be scratch");
+            throw GraalInternalError.shouldNotReachHere("result should be scratch");
         }
         assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move";
-        switch (other.getKind()) {
+        switch (kind) {
             case Int:
-                // XXX CC depends on compare
                 new Movcc(cond, CC.Icc, asRegister(other), asRegister(result)).emit(masm);
                 break;
             case Long:
+            case Object:
+                new Movcc(cond, CC.Xcc, asRegister(other), asRegister(result)).emit(masm);
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Mon Apr 28 11:18:15 2014 +0200
@@ -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 + (target.stackAlignment - 1);
-        return (x / target.stackAlignment) * target.stackAlignment;
+        return NumUtil.roundUp(size, target.stackAlignment);
     }
 
     @Override
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Apr 28 11:18:15 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,33 +23,15 @@
 package com.oracle.graal.lir.sparc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Add;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsh;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lduh;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Membar;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Rdpc;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stb;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Sth;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cas;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Casx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Clr;
-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;
@@ -154,32 +136,33 @@
 
         @Override
         public void emitMemAccess(SPARCMacroAssembler masm) {
-            SPARCAddress addr = address.toAddress();
+            final SPARCAddress addr = address.toAddress();
+            final Register dst = asRegister(result);
             switch (kind) {
                 case Boolean:
                 case Byte:
-                    new Ldsb(addr, asRegister(result)).emit(masm);
+                    new Ldsb(addr, dst).emit(masm);
                     break;
                 case Short:
-                    new Ldsh(addr, asRegister(result)).emit(masm);
+                    new Ldsh(addr, dst).emit(masm);
                     break;
                 case Char:
-                    new Lduh(addr, asRegister(result)).emit(masm);
+                    new Lduh(addr, dst).emit(masm);
                     break;
                 case Int:
-                    new Ldsw(addr, asRegister(result)).emit(masm);
+                    new Ldsw(addr, dst).emit(masm);
                     break;
                 case Long:
-                    new Ldx(addr, asRegister(result)).emit(masm);
+                    new Ldx(addr, dst).emit(masm);
                     break;
                 case Float:
-                    new Ldf(addr, asRegister(result)).emit(masm);
+                    new Ldf(addr, dst).emit(masm);
                     break;
                 case Double:
-                    new Lddf(addr, asRegister(result)).emit(masm);
+                    new Lddf(addr, dst).emit(masm);
                     break;
                 case Object:
-                    new Ldx(addr, asRegister(result)).emit(masm);
+                    new Ldx(addr, dst).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -208,6 +191,26 @@
         }
     }
 
+    public static class LoadDataAddressOp extends SPARCLIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        private final byte[] data;
+
+        public LoadDataAddressOp(AllocatableValue result, byte[] data) {
+            this.result = result;
+            this.data = data;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            RawData rawData = new RawData(data, 16);
+            SPARCAddress addr = (SPARCAddress) crb.recordDataReferenceInCode(rawData);
+            assert addr == masm.getPlaceholder();
+            final boolean forceRelocatable = true;
+            new Setx(0, asRegister(result), forceRelocatable).emit(masm);
+        }
+    }
+
     public static class MembarOp extends SPARCLIRInstruction {
 
         private final int barriers;
@@ -395,19 +398,25 @@
     }
 
     private static void reg2reg(SPARCAssembler masm, Value result, Value input) {
-        if (asRegister(input).equals(asRegister(result))) {
+        final Register src = asRegister(input);
+        final Register dst = asRegister(result);
+        if (src.equals(dst)) {
             return;
         }
         switch (input.getKind()) {
             case Int:
             case Long:
             case Object:
-                new Mov(asRegister(input), asRegister(result)).emit(masm);
+                new Mov(src, dst).emit(masm);
                 break;
             case Float:
+                new Fmovs(src, dst).emit(masm);
+                break;
             case Double:
+                new Fmovd(src, dst).emit(masm);
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -423,7 +432,11 @@
                 new Stx(src, dst).emit(masm);
                 break;
             case Float:
+                new Stf(src, dst).emit(masm);
+                break;
             case Double:
+                new Stdf(src, dst).emit(masm);
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -461,7 +474,7 @@
                     }
                 }
                 break;
-            case Long: {
+            case Long:
                 if (crb.codeCache.needsDataPatch(input)) {
                     crb.recordInlineDataInCode(input);
                     new Setx(input.asLong(), asRegister(result), true).emit(masm);
@@ -473,8 +486,10 @@
                     }
                 }
                 break;
-            }
-            case Object: {
+            case Float:
+                new Ldf((SPARCAddress) crb.asFloatConstRef(input), asFloatReg(result)).emit(masm);
+                break;
+            case Object:
                 if (input.isNull()) {
                     new Clr(asRegister(result)).emit(masm);
                 } else if (crb.target.inlineObjects) {
@@ -488,7 +503,6 @@
                     throw GraalInternalError.shouldNotReachHere("the patched offset might be too big for the load");
                 }
                 break;
-            }
             default:
                 throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,133 @@
+/*
+ * 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.lir.sparc;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Saves registers to stack slots.
+ */
+@Opcode("SAVE_REGISTER")
+public class SPARCSaveRegistersOp extends SPARCLIRInstruction implements SaveRegistersOp {
+
+    /**
+     * The registers (potentially) saved by this operation.
+     */
+    protected final Register[] savedRegisters;
+
+    /**
+     * The slots to which the registers are saved.
+     */
+    @Def(STACK) protected final StackSlot[] slots;
+
+    /**
+     * Specifies if {@link #remove(Set)} should have an effect.
+     */
+    protected final boolean supportsRemove;
+
+    /**
+     *
+     * @param savedRegisters the registers saved by this operation which may be subject to
+     *            {@linkplain #remove(Set) pruning}
+     * @param slots the slots to which the registers are saved
+     * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned}
+     */
+    public SPARCSaveRegistersOp(Register[] savedRegisters, StackSlot[] slots, boolean supportsRemove) {
+        this.savedRegisters = savedRegisters;
+        this.slots = slots;
+        this.supportsRemove = supportsRemove;
+    }
+
+    private static void saveRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, StackSlot result, Register register) {
+        RegisterValue input = register.asValue(result.getKind());
+        SPARCMove.move(crb, masm, result, input);
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                saveRegister(crb, masm, slots[i], savedRegisters[i]);
+            }
+        }
+    }
+
+    public StackSlot[] getSlots() {
+        return slots;
+    }
+
+    public boolean supportsRemove() {
+        return supportsRemove;
+    }
+
+    public int remove(Set<Register> doNotSave) {
+        if (!supportsRemove) {
+            throw new UnsupportedOperationException();
+        }
+        return prune(doNotSave, savedRegisters);
+    }
+
+    static int prune(Set<Register> toRemove, Register[] registers) {
+        int pruned = 0;
+        for (int i = 0; i < registers.length; i++) {
+            if (registers[i] != null) {
+                if (toRemove.contains(registers[i])) {
+                    registers[i] = null;
+                    pruned++;
+                }
+            }
+        }
+        return pruned;
+    }
+
+    public RegisterSaveLayout getMap(FrameMap frameMap) {
+        int total = 0;
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                total++;
+            }
+        }
+        Register[] keys = new Register[total];
+        int[] values = new int[total];
+        if (total != 0) {
+            int mapIndex = 0;
+            for (int i = 0; i < savedRegisters.length; i++) {
+                if (savedRegisters[i] != null) {
+                    keys[mapIndex] = savedRegisters[i];
+                    values[mapIndex] = frameMap.indexForStackSlot(slots[i]);
+                    mapIndex++;
+                }
+            }
+            assert mapIndex == total;
+        }
+        return new RegisterSaveLayout(keys, values);
+    }
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Mon Apr 28 11:18:15 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,18 +88,12 @@
         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 = {};
-
     public CompilationResult.Mark recordMark(Object id) {
-        return compilationResult.recordMark(asm.position(), id, NO_REFS);
-    }
-
-    public CompilationResult.Mark recordMark(Object id, CompilationResult.Mark... references) {
-        return compilationResult.recordMark(asm.position(), id, references);
+        return compilationResult.recordMark(asm.position(), id);
     }
 
     public void blockComment(String s) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,594 @@
+/*
+ * 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 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;
+
+    private AbstractBlock<?> currentBlock;
+
+    /**
+     * 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;
+    }
+
+    /**
+     * 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 (Options.PrintIRWithLIR.getValue() && !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 (Options.PrintIRWithLIR.getValue()) {
+            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 (Options.TraceLIRGeneratorLevel.getValue() >= 1) {
+            TTY.println("BEGIN Generating LIR for block B" + block.getId());
+        }
+    }
+
+    public final void doBlockEnd(AbstractBlock<?> block) {
+
+        if (Options.TraceLIRGeneratorLevel.getValue() >= 1) {
+            TTY.println("END Generating LIR for block B" + block.getId());
+        }
+
+        currentBlock = null;
+
+        if (Options.PrintIRWithLIR.getValue()) {
+            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	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,199 @@
+/*
+ * 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 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.calc.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.spi.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.LIRGenerator.*;
+
+public interface LIRGeneratorTool extends ArithmeticLIRGenerator {
+
+    CodeGenProviders getProviders();
+
+    TargetDescription target();
+
+    MetaAccessProvider getMetaAccess();
+
+    CodeCacheProvider getCodeCache();
+
+    ForeignCallsProvider getForeignCalls();
+
+    AbstractBlock<?> getCurrentBlock();
+
+    LIRGenerationResult getResult();
+
+    boolean hasBlockEnd(AbstractBlock<?> block);
+
+    void doBlockStart(AbstractBlock<?> block);
+
+    void doBlockEnd(AbstractBlock<?> block);
+
+    Map<Constant, LoadConstant> getConstantLoads();
+
+    void setConstantLoads(Map<Constant, LoadConstant> constantLoads);
+
+    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);
+
+    Variable 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);
+
+    Variable newVariable(PlatformKind kind);
+
+    Variable 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);
+
+    AllocatableValue asAllocatable(Value value);
+
+    Variable load(Value value);
+
+    Value loadNonConst(Value value);
+
+    /**
+     * Returns true if the redundant move elimination optimization should be done after register
+     * allocation.
+     */
+    boolean canEliminateRedundantMoves();
+
+    /**
+     * Determines if only oop maps are required for the code generated from the LIR.
+     */
+    boolean needOnlyOopMaps();
+
+    /**
+     * 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}
+     */
+    AllocatableValue resultOperandFor(Kind kind);
+
+    void append(LIRInstruction op);
+
+    void emitJump(LabelRef label);
+
+    void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
+                    double trueDestinationProbability);
+
+    void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
+
+    void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
+
+    Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
+
+    Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
+
+    void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value);
+
+    void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget);
+
+    CallingConvention getCallingConvention();
+
+    void emitBitCount(Variable result, Value operand);
+
+    void emitBitScanForward(Variable result, Value operand);
+
+    void emitBitScanReverse(Variable result, Value operand);
+
+    void emitByteSwap(Variable result, Value operand);
+
+    void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
+
+}
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Mon Apr 28 11:18:15 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 != exit).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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/ObjectStampJoinTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Mon Apr 28 11:18:15 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/BinaryOpLogicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable, Canonicalizable {
+
+    @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 BinaryOpLogicNode(ValueNode x, ValueNode y) {
+        assert x != null && y != null && x.getKind() == y.getKind();
+        this.x = x;
+        this.y = y;
+    }
+
+    public abstract TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY);
+
+    @Override
+    public boolean verify() {
+        assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
+        return super.verify();
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        switch (evaluate(tool.getConstantReflection(), x(), y())) {
+            case FALSE:
+                return LogicConstantNode.contradiction(graph());
+            case TRUE:
+                return LogicConstantNode.tautology(graph());
+        }
+        return this;
+    }
+
+    @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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Mon Apr 28 11:18:15 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.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Extension})
 public abstract class CallTargetNode extends ValueNode implements LIRLowerable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Apr 28 11:18:15 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.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard})
 public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable, Lowerable, GuardingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Mon Apr 28 11:18:15 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);
@@ -266,19 +268,18 @@
         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);
     }
 
     /**
@@ -287,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);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -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
@@ -44,4 +44,9 @@
     public FixedWithNextNode(Stamp stamp) {
         super(stamp);
     }
+
+    @Override
+    public FixedWithNextNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Apr 28 11:18:15 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;
 
     /**
@@ -124,8 +95,8 @@
         this.virtualObjectMappings = new NodeInputList<>(this, virtualObjectMappings);
         this.rethrowException = rethrowException;
         this.duringCall = duringCall;
-        assert !rethrowException || stackSize == 1 : "must have exception on top of the stack";
-        assert values.size() - localsSize - stackSize == monitorIds.size();
+        assert !this.rethrowException || this.stackSize == 1 : "must have exception on top of the stack";
+        assert this.locksSize() == this.monitorIds.size();
     }
 
     /**
@@ -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) {
@@ -248,6 +220,19 @@
      * correctly in slot encoding: a long or double will be followed by a null slot.
      */
     public FrameState duplicateModified(int newBci, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) {
+        return duplicateModified(newBci, method, newRethrowException, popKind, pushedValues);
+    }
+
+    /**
+     * Creates a copy of this frame state with one stack element of type popKind popped from the
+     * stack and the values in pushedValues pushed on the stack. The pushedValues will be formatted
+     * correctly in slot encoding: a long or double will be followed by a null slot.
+     */
+    public FrameState duplicateModified(Kind popKind, ValueNode... pushedValues) {
+        return duplicateModified(bci, method, rethrowException, popKind, pushedValues);
+    }
+
+    private FrameState duplicateModified(int newBci, ResolvedJavaMethod newMethod, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) {
         ArrayList<ValueNode> copy = new ArrayList<>(values.subList(0, localsSize + stackSize));
         if (popKind != Kind.Void) {
             if (stackAt(stackSize() - 1) == null) {
@@ -266,7 +251,7 @@
         int newStackSize = copy.size() - localsSize;
         copy.addAll(values.subList(localsSize + stackSize, values.size()));
 
-        FrameState other = graph().add(new FrameState(method, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings));
+        FrameState other = graph().add(new FrameState(newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings));
         other.setOuterFrameState(outerFrameState());
         return other;
     }
@@ -395,13 +380,26 @@
                 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;
     }
 
     @Override
     public boolean verify() {
-        assertTrue(values.size() - localsSize - stackSize == monitorIds.size(), "mismatch in number of locks");
+        assertTrue(locksSize() == monitorIds.size(), "mismatch in number of locks");
         for (ValueNode value : values) {
             assertTrue(value == null || !value.isDeleted(), "frame state must not contain deleted nodes");
             assertTrue(value == null || value instanceof VirtualObjectNode || (value.getKind() != Kind.Void), "unexpected value: %s", value);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Mon Apr 28 11:18:15 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
@@ -107,7 +107,8 @@
         } else if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
             if (c.getValue() != negated) {
-                return graph().start();
+                this.replaceAtUsages(null);
+                return null;
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Apr 28 11:18:15 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() == null) {
             if (stamp().equals(object().stamp())) {
                 return object();
             } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Apr 28 11:18:15 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.*;
@@ -50,6 +51,18 @@
         return condition;
     }
 
+    public boolean isNegated() {
+        return negated;
+    }
+
+    public DeoptimizationReason getReason() {
+        return reason;
+    }
+
+    public DeoptimizationAction getAction() {
+        return action;
+    }
+
     /**
      * Constructor for {@link #guardingNonNull(Object)} node intrinsic.
      */
@@ -87,7 +100,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Mon Apr 28 11:18:15 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 {
 
@@ -43,6 +43,6 @@
 
     @Override
     public String targetName() {
-        return "Indirect#" + ((JavaMethod) target()).getName();
+        return MetaUtil.format("Indirect#%h.%n", target());
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 28 11:18:15 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.*;
 
 /**
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -36,8 +36,8 @@
 
     private static final double EXCEPTION_PROBA = 1e-5;
 
-    @Successor private AbstractBeginNode next;
-    @Successor private DispatchBeginNode exceptionEdge;
+    @Successor private BeginNode next;
+    @Successor private BeginNode exceptionEdge;
     @Input(InputType.Extension) private CallTargetNode callTarget;
     @Input(InputType.State) private FrameState stateDuring;
     @Input(InputType.State) private FrameState stateAfter;
@@ -47,7 +47,7 @@
     private boolean useForInlining;
     private double exceptionProbability;
 
-    public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci) {
+    public InvokeWithExceptionNode(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) {
         super(callTarget.returnStamp());
         this.exceptionEdge = exceptionEdge;
         this.bci = bci;
@@ -57,20 +57,20 @@
         this.exceptionProbability = EXCEPTION_PROBA;
     }
 
-    public DispatchBeginNode exceptionEdge() {
+    public BeginNode exceptionEdge() {
         return exceptionEdge;
     }
 
-    public void setExceptionEdge(DispatchBeginNode x) {
+    public void setExceptionEdge(BeginNode x) {
         updatePredecessor(exceptionEdge, x);
         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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Mon Apr 28 11:18:15 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.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Extension})
 public abstract class MemoryMapNode extends FloatingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Apr 28 11:18:15 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(VirtualState.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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Apr 28 11:18:15 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());
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Mon Apr 28 11:18:15 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.*;
 
 public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Mon Apr 28 11:18:15 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) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,57 @@
+/*
+ * 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.api.meta.ProfilingInfo.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable {
+
+    @Input private ValueNode object;
+
+    public ValueNode object() {
+        return object;
+    }
+
+    protected void setX(ValueNode object) {
+        updateUsages(this.object, object);
+        this.object = object;
+    }
+
+    public UnaryOpLogicNode(ValueNode object) {
+        assert object != null;
+        this.object = object;
+    }
+
+    public abstract TriState evaluate(ValueNode forObject);
+
+    @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/UnwindNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Mon Apr 28 11:18:15 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/VirtualState.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Mon Apr 28 11:18:15 2014 +0200
@@ -45,6 +45,10 @@
 
     public abstract void applyToNonVirtual(NodeClosure<? super ValueNode> closure);
 
+    /**
+     * Performs a <b>pre-order</b> iteration over all elements reachable from this state that are a
+     * subclass of {@link VirtualState}.
+     */
     public abstract void applyToVirtual(VirtualClosure closure);
 
     public abstract boolean isPartOfThisState(VirtualState state);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Apr 28 11:18:15 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.*;
@@ -88,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+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 +36,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 BinaryOpLogicNode {
 
     /**
      * 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,24 +86,23 @@
         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);
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (x().isConstant() && y().isConstant()) {
+            return TriState.get(condition().foldCondition(x().asConstant(), y().asConstant(), constantReflection, unorderedIsTrue()));
+        }
+        return TriState.UNKNOWN;
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant() && tool.getMetaAccess() != null) {
-            return LogicConstantNode.forBoolean(condition().foldCondition(x().asConstant(), y().asConstant(), tool.getConstantReflection(), unorderedIsTrue()), graph());
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
         }
         if (x().isConstant()) {
             if (y() instanceof ConditionalNode) {
@@ -193,14 +176,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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Mon Apr 28 11:18:15 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
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,16 +22,20 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+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.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
 public final class FloatEqualsNode extends CompareNode {
 
     /**
      * Constructs a new floating point equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -50,4 +54,18 @@
     public boolean unorderedIsTrue() {
         return false;
     }
+
+    @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (forX.stamp() instanceof FloatStamp && forY.stamp() instanceof FloatStamp) {
+            FloatStamp xStamp = (FloatStamp) forX.stamp();
+            FloatStamp yStamp = (FloatStamp) forY.stamp();
+            if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) {
+                return TriState.TRUE;
+            } else if (xStamp.alwaysDistinct(yStamp)) {
+                return TriState.FALSE;
+            }
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,13 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
+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.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 = "<")
 public final class FloatLessThanNode extends CompareNode {
@@ -34,7 +37,7 @@
 
     /**
      * Constructs a new floating point comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      * @param unorderedIsTrue whether a comparison that is undecided (involving NaNs, etc.) leads to
@@ -58,10 +61,10 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y() && !unorderedIsTrue()) {
-            return LogicConstantNode.contradiction(graph());
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && !unorderedIsTrue()) {
+            return TriState.FALSE;
         }
-        return super.canonical(tool);
+        return super.evaluate(constantReflection, forX, forY);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Mon Apr 28 11:18:15 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,13 +22,18 @@
  */
 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 {
 
     public FloatingNode(Stamp stamp) {
         super(stamp);
     }
+
+    @Override
+    public FloatingNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,17 +23,20 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+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 = "|<|")
 public final class IntegerBelowThanNode extends CompareNode {
 
     /**
      * Constructs a new unsigned integer comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -54,28 +57,33 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.contradiction(graph());
-        } else {
-            if (x().isConstant() && x().asConstant().asLong() == 0) {
-                // 0 |<| y is the same as 0 != y
-                return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y())));
-            }
-
-            if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-                IntegerStamp xStamp = (IntegerStamp) x().stamp();
-                IntegerStamp yStamp = (IntegerStamp) y().stamp();
-                if (yStamp.isPositive()) {
-                    if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
-                        return LogicConstantNode.tautology(graph());
-                    } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
-                        return LogicConstantNode.contradiction(graph());
-                    }
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.FALSE;
+        } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
+            if (yStamp.isPositive()) {
+                if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
+                    return TriState.TRUE;
+                } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
+                    return TriState.FALSE;
                 }
             }
         }
+        return super.evaluate(constantReflection, forX, forY);
+    }
 
-        return super.canonical(tool);
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
+        }
+        if (x().isConstant() && x().asConstant().asLong() == 0) {
+            // 0 |<| y is the same as 0 != y
+            return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y())));
+        }
+        return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,12 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+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 = "==")
@@ -34,7 +36,7 @@
 
     /**
      * Constructs a new integer equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -70,24 +72,28 @@
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.TRUE;
+        } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
+            return TriState.FALSE;
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (GraphUtil.unproxify(x()) == GraphUtil.unproxify(y())) {
-            return LogicConstantNode.tautology(graph());
-        } else if (x().stamp().alwaysDistinct(y().stamp())) {
-            return LogicConstantNode.contradiction(graph());
-        }
-
-        ValueNode result = canonicalizeSymmetric(x(), y());
-        if (result != null) {
+        Node result = super.canonical(tool);
+        if (result != this) {
             return result;
         }
 
-        result = canonicalizeSymmetric(y(), x());
-        if (result != null) {
+        result = canonicalizeSymmetric(x(), y());
+        if (result != this) {
             return result;
         }
 
-        return super.canonical(tool);
+        return canonicalizeSymmetric(y(), x());
     }
 
     private ValueNode canonicalizeSymmetric(ValueNode x, ValueNode y) {
@@ -132,6 +138,6 @@
                 }
             }
         }
-        return null;
+        return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,17 +23,20 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+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 = "<")
 public final class IntegerLessThanNode extends CompareNode {
 
     /**
      * Constructs a new integer comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -70,22 +73,32 @@
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.FALSE;
+        } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
+            if (xStamp.upperBound() < yStamp.lowerBound()) {
+                return TriState.TRUE;
+            } else if (xStamp.lowerBound() >= yStamp.upperBound()) {
+                return TriState.FALSE;
+            }
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.contradiction(graph());
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
         }
         if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-            IntegerStamp xStamp = (IntegerStamp) x().stamp();
-            IntegerStamp yStamp = (IntegerStamp) y().stamp();
-            if (xStamp.upperBound() < yStamp.lowerBound()) {
-                return LogicConstantNode.tautology(graph());
-            } else if (xStamp.lowerBound() >= yStamp.upperBound()) {
-                return LogicConstantNode.contradiction(graph());
-            }
-            if (IntegerStamp.sameSign(xStamp, yStamp)) {
+            if (IntegerStamp.sameSign((IntegerStamp) x().stamp(), (IntegerStamp) y().stamp())) {
                 return graph().unique(new IntegerBelowThanNode(x(), y()));
             }
         }
-        return super.canonical(tool);
+        return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,64 +22,42 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
+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.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 BinaryOpLogicNode {
 
     /**
      * 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
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            return LogicConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph());
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            return TriState.get((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0);
         }
         if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-            IntegerStamp xStamp = (IntegerStamp) x().stamp();
-            IntegerStamp yStamp = (IntegerStamp) y().stamp();
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
             if ((xStamp.upMask() & yStamp.upMask()) == 0) {
-                return LogicConstantNode.tautology(graph());
+                return TriState.TRUE;
+            } else if ((xStamp.downMask() & yStamp.downMask()) != 0) {
+                return TriState.FALSE;
             }
         }
-        return this;
-    }
-
-    @Override
-    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        return false;
+        return TriState.UNKNOWN;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.nodes.calc;
 
 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.*;
@@ -32,21 +34,15 @@
 /**
  * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
  */
-public final class IsNullNode extends LogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable {
-
-    @Input private ValueNode object;
-
-    public ValueNode object() {
-        return object;
-    }
+public final class IsNullNode extends UnaryOpLogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable {
 
     /**
      * Constructs a new IsNullNode instruction.
-     * 
+     *
      * @param object the instruction producing the object to check against null
      */
     public IsNullNode(ValueNode object) {
-        this.object = object;
+        super(object);
     }
 
     @Override
@@ -63,20 +59,31 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        Constant constant = object().asConstant();
-        if (constant != null) {
-            assert constant.getKind() == Kind.Object;
-            return LogicConstantNode.forBoolean(constant.isNull(), graph());
-        }
-        if (ObjectStamp.isObjectNonNull(object.stamp())) {
-            return LogicConstantNode.contradiction(graph());
+        switch (evaluate(object())) {
+            case FALSE:
+                return LogicConstantNode.contradiction(graph());
+            case TRUE:
+                return LogicConstantNode.tautology(graph());
         }
         return this;
     }
 
     @Override
+    public TriState evaluate(ValueNode forObject) {
+        Constant constant = forObject.asConstant();
+        if (constant != null) {
+            assert constant.getKind() == Kind.Object;
+            return TriState.get(constant.isNull());
+        }
+        if (StampTool.isObjectNonNull(forObject.stamp())) {
+            return TriState.FALSE;
+        }
+        return TriState.UNKNOWN;
+    }
+
+    @Override
     public void virtualize(VirtualizerTool tool) {
-        if (tool.getObjectState(object) != null) {
+        if (tool.getObjectState(object()) != null) {
             tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,18 +23,21 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+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.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
 public final class ObjectEqualsNode extends CompareNode implements Virtualizable {
 
     /**
      * Constructs a new object equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -55,21 +58,28 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.tautology(graph());
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.TRUE;
+        } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
+            return TriState.FALSE;
+        } else {
+            return super.evaluate(constantReflection, forX, forY);
         }
+    }
 
-        if (ObjectStamp.isObjectAlwaysNull(x())) {
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
+        }
+        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())) {
-            return LogicConstantNode.contradiction(graph());
-        }
-
-        return super.canonical(tool);
+        return this;
     }
 
     private void virtualizeNonVirtualComparison(State state, ValueNode other, VirtualizerTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Mon Apr 28 11:18:15 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.*;
@@ -98,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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,24 +24,25 @@
 
 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.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;
     }
 
@@ -66,15 +67,16 @@
     }
 
     public boolean isExceptionEntry() {
-        return getBeginNode() instanceof ExceptionObjectNode;
+        Node predecessor = getBeginNode().predecessor();
+        return predecessor != null && predecessor instanceof InvokeWithExceptionNode && getBeginNode() == ((InvokeWithExceptionNode) predecessor).exceptionEdge();
     }
 
     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 +124,7 @@
             } else {
                 cur = ((FixedWithNextNode) cur).next();
             }
-            assert !(cur instanceof AbstractBeginNode);
+            assert !(cur instanceof BeginNode);
             return result;
         }
 
@@ -167,10 +169,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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,15 +22,15 @@
  */
 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
  * by adding an increment to the compiled code. This should of course only be used for
  * debugging/testing purposes.
- * 
+ *
  * A unique counter will be created for each unique name passed to the constructor. Depending on the
  * value of withContext, the name of the root method is added to the counter's name.
  */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Mon Apr 28 11:18:15 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
@@ -37,8 +38,8 @@
 @NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}")
 public final class AddLocationNode extends LocationNode implements Canonicalizable {
 
-    @Input private ValueNode x;
-    @Input private ValueNode y;
+    @Input(InputType.Association) private ValueNode x;
+    @Input(InputType.Association) private ValueNode y;
 
     protected LocationNode getX() {
         return (LocationNode) x;
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +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.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A node that represents an exception thrown implicitly by a Java bytecode. It can be lowered to
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Mon Apr 28 11:18:15 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/FixedAccessNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Mon Apr 28 11:18:15 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/GuardedNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GuardedNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * A node that may be guarded by a {@linkplain GuardingNode guarding node}.
  */
-public interface GuardedNode {
+public interface GuardedNode extends NodeInterface {
 
     GuardingNode getGuard();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Mon Apr 28 11:18:15 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/MemoryCheckpoint.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,7 +31,7 @@
  * represented by location identities (i.e. change a value at one or more locations that belong to
  * these location identities).
  */
-public interface MemoryCheckpoint extends MemoryNode {
+public interface MemoryCheckpoint extends MemoryNode, NodeInterface {
 
     FixedNode asNode();
 
@@ -40,7 +40,7 @@
         /**
          * This method is used to determine which memory location is killed by this node. Returning
          * the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory locations.
-         * 
+         *
          * @return the identity of the location killed by this node.
          */
         LocationIdentity getLocationIdentity();
@@ -53,7 +53,7 @@
          * This method is used to determine which set of memory locations is killed by this node.
          * Returning the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory
          * locations.
-         * 
+         *
          * @return the identities of all locations killed by this node.
          */
         LocationIdentity[] getLocationIdentities();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * This interface marks nodes that are part of the memory graph.
  */
-public interface MemoryNode {
+public interface MemoryNode extends NodeInterface {
 
     ValueNode asNode();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 28 11:18:15 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());
     }
@@ -140,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/StoreHubNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Mon Apr 28 11:18:15 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 {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Mon Apr 28 11:18:15 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,15 +79,15 @@
                 }
             }
         }
-        // Temporarily disable this as it appears to break truffle.
-        // ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object());
-        // if (receiverType != null && receiverType.isArray()) {
-        // LocationIdentity identity =
-        // NamedLocationIdentity.getArrayLocation(receiverType.getComponentType().getKind());
-        // // Try to build a better location node
-        // ValueNode location = offset();
-        // return cloneAsArrayAccess(location, identity);
-        // }
+        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;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Apr 28 11:18:15 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
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Apr 28 11:18:15 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
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Mon Apr 28 11:18:15 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, InputType.Guard})
-public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, GuardingNode {
+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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Mon Apr 28 11:18:15 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,18 +58,30 @@
     /**
      * 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()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -73,7 +73,7 @@
     public Node canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        if (ObjectStamp.isObjectAlwaysNull(object())) {
+        if (StampTool.isObjectAlwaysNull(object())) {
             return object();
         }
         if (hub.isConstant()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Apr 28 11:18:15 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
@@ -45,6 +45,19 @@
 
     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;
@@ -70,20 +83,9 @@
         return valueKind;
     }
 
-    public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind) {
-        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;
-    }
-
     @Override
     public LocationIdentity getLocationIdentity() {
-        return LocationIdentity.ANY_LOCATION;
+        return locationIdentity;
     }
 
     @Override
@@ -94,19 +96,19 @@
     // 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,
-                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
+                    @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,
-                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
+                    @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,
-                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
+                    @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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Mon Apr 28 11:18:15 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
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Mon Apr 28 11:18:15 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 {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,21 +22,18 @@
  */
 package com.oracle.graal.nodes.java;
 
-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.*;
-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
  * throw instruction or implicit exception).
  */
+@NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint.Single {
 
     public ExceptionObjectNode(MetaAccessProvider metaAccess) {
@@ -49,56 +46,13 @@
     }
 
     @Override
-    public void simplify(SimplifierTool tool) {
-        //
-    }
-
-    private boolean isLowered() {
-        return (stamp() == StampFactory.forVoid());
-    }
-
-    /**
-     * The frame state upon entry to an exception handler is such that it is a
-     * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly
-     * the exception object (per the JVM spec) to rethrow. This means that the code creating this
-     * state (i.e. the {@link LoadExceptionObjectNode}) cannot cause a deoptimization as the
-     * runtime/interpreter would not have a valid location for the exception object to be rethrown.
-     */
-    @Override
     public void lower(LoweringTool tool) {
-        if (isLowered()) {
-            return;
-        }
-        LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp()));
-        loadException.setStateAfter(stateAfter());
-        List<GuardedNode> guardedNodes = new ArrayList<>();
-        for (Node usage : usages().snapshot()) {
-            if (usage instanceof GuardedNode) {
-                // can't replace the guard with LoadExceptionObjectNode as it is not a GuardingNode
-                // so temporarily change it to remove the GuardedNode from usages
-                GuardedNode guardedNode = (GuardedNode) usage;
-                guardedNode.setGuard(graph().add(new BeginNode()));
-                guardedNodes.add(guardedNode);
-            }
-        }
-        replaceAtUsages(loadException);
-        for (GuardedNode guardedNode : guardedNodes) {
-            BeginNode dummyGuard = (BeginNode) guardedNode.getGuard();
-            guardedNode.setGuard(this);
-            graph().removeFixed(dummyGuard);
-        }
-        graph().addAfterFixed(this, loadException);
-        setStateAfter(null);
-        setStamp(StampFactory.forVoid());
-        loadException.lower(tool);
+        tool.getLowerer().lower(this, tool);
     }
 
     @Override
     public boolean verify() {
-        if (isLowered()) {
-            return true;
-        }
-        assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state");
+        assertTrue(stateAfter() != null, "an exception handler needs a frame state");
         return super.verify();
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Mon Apr 28 11:18:15 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
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,31 +23,31 @@
 package com.oracle.graal.nodes.java;
 
 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.*;
 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.
  */
-public final class InstanceOfNode extends LogicNode implements Canonicalizable, Lowerable, Virtualizable {
+public final class InstanceOfNode extends UnaryOpLogicNode implements Canonicalizable, Lowerable, Virtualizable {
 
-    @Input private ValueNode object;
     private final ResolvedJavaType type;
     private JavaTypeProfile profile;
 
     /**
      * Constructs a new InstanceOfNode.
-     * 
+     *
      * @param type the target type of the instanceof check
      * @param object the object being tested by the instanceof
      */
     public InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
+        super(object);
         this.type = type;
-        this.object = object;
         this.profile = profile;
         assert type != null;
     }
@@ -59,13 +59,39 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        Stamp stamp = object().stamp();
+        switch (evaluate(object())) {
+            case FALSE:
+                return LogicConstantNode.contradiction(graph());
+            case TRUE:
+                return LogicConstantNode.tautology(graph());
+            case UNKNOWN:
+                Stamp stamp = object().stamp();
+                if (stamp instanceof ObjectStamp) {
+                    ObjectStamp objectStamp = (ObjectStamp) stamp;
+                    ResolvedJavaType stampType = objectStamp.type();
+                    if (stampType != null && type().isAssignableFrom(stampType)) {
+                        if (!objectStamp.nonNull()) {
+                            // the instanceof matches if the object is non-null, so return true
+                            // depending on the null-ness.
+                            IsNullNode isNull = graph().unique(new IsNullNode(object()));
+                            return graph().unique(new LogicNegationNode(isNull));
+                        }
+                    }
+                }
+                return this;
+        }
+        return this;
+    }
+
+    @Override
+    public TriState evaluate(ValueNode forObject) {
+        Stamp stamp = forObject.stamp();
         if (!(stamp instanceof ObjectStamp)) {
-            return this;
+            return TriState.UNKNOWN;
         }
         ObjectStamp objectStamp = (ObjectStamp) stamp;
         if (objectStamp.alwaysNull()) {
-            return LogicConstantNode.contradiction(graph());
+            return TriState.FALSE;
         }
 
         ResolvedJavaType stampType = objectStamp.type();
@@ -74,34 +100,25 @@
             if (subType) {
                 if (objectStamp.nonNull()) {
                     // the instanceOf matches, so return true
-                    return LogicConstantNode.tautology(graph());
-                } else {
-                    // the instanceof matches if the object is non-null, so return true depending on
-                    // the null-ness.
-                    IsNullNode isNull = graph().unique(new IsNullNode(object()));
-                    return graph().unique(new LogicNegationNode(isNull));
+                    return TriState.TRUE;
                 }
             } else {
                 if (objectStamp.isExactType()) {
                     // since this type check failed for an exact type we know that it can never
                     // succeed at run time. we also don't care about null values, since they will
                     // also make the check fail.
-                    return LogicConstantNode.contradiction(graph());
+                    return TriState.FALSE;
                 } else {
                     boolean superType = stampType.isAssignableFrom(type());
                     if (!superType && !stampType.isInterface() && !type().isInterface()) {
-                        return LogicConstantNode.contradiction(graph());
+                        return TriState.FALSE;
                     }
                     // since the subtype comparison was only performed on a declared type we don't
                     // really know if it might be true at run time...
                 }
             }
         }
-        return this;
-    }
-
-    public ValueNode object() {
-        return object;
+        return TriState.UNKNOWN;
     }
 
     /**
@@ -121,7 +138,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        State state = tool.getObjectState(object);
+        State state = tool.getObjectState(object());
         if (state != null) {
             tool.replaceWithValue(LogicConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph()));
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.java;
-
-import com.oracle.graal.api.code.*;
-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
- * caller. The node is only produced when lowering an {@link ExceptionObjectNode}.
- * <p>
- * The frame state upon entry to an exception handler is such that it is a
- * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly the
- * exception object (per the JVM spec) to rethrow. This means that the code generated for this node
- * must not cause a deoptimization as the runtime/interpreter would not have a valid location to
- * find the exception object to be rethrown.
- */
-public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable {
-
-    public LoadExceptionObjectNode(Stamp stamp) {
-        super(stamp);
-    }
-
-    @Override
-    public void lower(LoweringTool tool) {
-        tool.getLowerer().lower(this, tool);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Mon Apr 28 11:18:15 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}.
@@ -80,7 +80,7 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         assert getNewValue().stamp().isCompatible(getExpectedValue().stamp());
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        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);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +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);
-
-    Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue);
-
-    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	Fri Apr 25 16:21:07 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/Lowerable.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.nodes.spi;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * Interface implemented by nodes that can replace themselves with lower level nodes during a phase
  * that transforms a graph to replace higher level nodes with lower level nodes.
  */
-public interface Lowerable {
+public interface Lowerable extends NodeInterface {
 
     /**
      * Expand this node into lower level nodes expressing the same semantics. If the introduced
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,12 +26,19 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
+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.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 
 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);
@@ -59,9 +66,19 @@
 
     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);
 
     MemoryArithmeticLIRLowerer getMemoryLowerer();
+
+    Variable newVariable(Kind kind);
+
+    void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
+
+    void emitBitCount(Variable result, Value operand);
+
+    void emitBitScanForward(Variable result, Value operand);
+
+    void doBlock(Block block, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,15 @@
 package com.oracle.graal.nodes.spi;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * Interface for nodes which have {@link FrameState} nodes as input.
  */
-public interface NodeWithState {
+public interface NodeWithState extends NodeInterface {
 
-    Node asNode();
+    default NodeIterable<FrameState> states() {
+        return asNode().inputs().filter(FrameState.class);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,11 +24,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 
 /**
  * Interface for service providers that register replacements with the compiler.
  */
 public interface ReplacementsProvider {
 
-    void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, Replacements replacements, TargetDescription target);
+    void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Mon Apr 28 11:18:15 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 Java 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Mon Apr 28 11:18:15 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();
@@ -327,6 +331,14 @@
         return v;
     }
 
+    public static boolean tryKillUnused(Node node) {
+        if (node.isAlive() && isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) {
+            killWithUnusedFloatingInputs(node);
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Exhaustive search for {@link GraphUtil#originalValue(ValueNode)} when a simple search fails.
      * This can happen in the presence of complicated phi/proxy/phi constructs.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/NodeIterators.java	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java	Mon Apr 28 11:18:15 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
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Mon Apr 28 11:18:15 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.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.Extension})
 public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Apr 28 11:18:15 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/OptionProcessor.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Mon Apr 28 11:18:15 2014 +0200
@@ -40,8 +40,10 @@
  *
  * <pre>
  * ServiceLoader&lt;Options&gt; sl = ServiceLoader.loadInstalled(Options.class);
- * for (OptionDescriptor desc : sl) {
- *     // use desc
+ * for (Options opts : sl) {
+ *     for (OptionDescriptor desc : sl) {
+ *         // use desc
+ *     }
  * }
  * </pre>
  */
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -178,7 +178,7 @@
                 }
                 StructuredGraph graph = (StructuredGraph) node.graph();
                 Mark mark = graph.getMark();
-                if (!tryKillUnused(node)) {
+                if (!GraphUtil.tryKillUnused(node)) {
                     if (!tryCanonicalize(node, nodeClass)) {
                         if (node instanceof ValueNode) {
                             ValueNode valueNode = (ValueNode) node;
@@ -200,14 +200,6 @@
             }
         }
 
-        private static boolean tryKillUnused(Node node) {
-            if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) {
-                GraphUtil.killWithUnusedFloatingInputs(node);
-                return true;
-            }
-            return false;
-        }
-
         public static boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) {
             if (nodeClass.valueNumberable() && !nodeClass.isLeafNode()) {
                 Node newNode = node.graph().findDuplicate(node);
@@ -383,7 +375,7 @@
 
             @Override
             public void removeIfUnused(Node node) {
-                tryKillUnused(node);
+                GraphUtil.tryKillUnused(node);
             }
 
             @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Apr 28 11:18:15 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) {
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Apr 28 11:18:15 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");
@@ -1317,8 +1316,6 @@
         assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal();
         assert !invokeNode.graph().isAfterFloatingReadPhase() : "inline isn't handled correctly after floating reads phase";
 
-        Kind returnKind = invokeNode.getKind();
-
         FrameState stateAfter = invoke.stateAfter();
         assert stateAfter == null || stateAfter.isAlive();
         if (receiverNullCheck && !((MethodCallTargetNode) invoke.callTarget()).isStatic()) {
@@ -1347,7 +1344,7 @@
             }
         }
 
-        final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode);
+        final BeginNode prevBegin = BeginNode.prevBegin(invokeNode);
         DuplicationReplacement localReplacement = new DuplicationReplacement() {
 
             public Node replacement(Node node) {
@@ -1386,7 +1383,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,52 +1393,14 @@
         } 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);
             }
         }
 
         if (stateAfter != null) {
-            FrameState outerFrameState = null;
+            processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge);
             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) {
-                        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;
-                            frameState.replaceAndDelete(stateAtExceptionEdge);
-                        } else {
-                            assert stateAtExceptionEdge == null;
-                        }
-                    } else {
-                        // only handle the outermost frame states
-                        if (frameState.outerFrameState() == null) {
-                            assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method());
-                            if (outerFrameState == null) {
-                                outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invokeNode.getKind());
-                                outerFrameState.setDuringCall(true);
-                            }
-                            frameState.setOuterFrameState(outerFrameState);
-                        }
-                    }
-                }
-            }
             if (callerLockDepth != 0) {
                 for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.class)) {
                     MonitorIdNode monitor = (MonitorIdNode) duplicates.get(original);
@@ -1479,6 +1438,93 @@
         return duplicates;
     }
 
+    protected static void processFrameStates(Invoke invoke, StructuredGraph inlineGraph, Map<Node, Node> duplicates, FrameState stateAtExceptionEdge) {
+        FrameState stateAtReturn = invoke.stateAfter();
+        FrameState outerFrameState = null;
+        Kind invokeReturnKind = invoke.asNode().getKind();
+        for (FrameState original : inlineGraph.getNodes(FrameState.class)) {
+            FrameState frameState = (FrameState) duplicates.get(original);
+            if (frameState != null && frameState.isAlive()) {
+                if (frameState.bci == BytecodeFrame.AFTER_BCI) {
+                    /*
+                     * pop return kind from invoke's stateAfter and replace with this frameState's
+                     * return value (top of stack)
+                     */
+                    FrameState stateAfterReturn = stateAtReturn;
+                    if (invokeReturnKind != Kind.Void && frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0)) {
+                        stateAfterReturn = stateAtReturn.duplicateModified(invokeReturnKind, frameState.stackAt(0));
+                    }
+                    frameState.replaceAndDelete(stateAfterReturn);
+                } else if (stateAtExceptionEdge != null && isStateAfterException(frameState)) {
+                    /*
+                     * pop exception object from invoke's stateAfter and replace with this
+                     * frameState's exception object (top of stack)
+                     */
+                    FrameState stateAfterException = stateAtExceptionEdge;
+                    if (frameState.stackSize() > 0 && stateAtExceptionEdge.stackAt(0) != frameState.stackAt(0)) {
+                        stateAfterException = stateAtExceptionEdge.duplicateModified(Kind.Object, frameState.stackAt(0));
+                    }
+                    frameState.replaceAndDelete(stateAfterException);
+                } else if (frameState.bci == BytecodeFrame.UNWIND_BCI || frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
+                    handleMissingAfterExceptionFrameState(frameState);
+                } else {
+                    // only handle the outermost frame states
+                    if (frameState.outerFrameState() == null) {
+                        assert frameState.bci != BytecodeFrame.BEFORE_BCI : frameState;
+                        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 = stateAtReturn.duplicateModified(invoke.bci(), stateAtReturn.rethrowException(), invokeReturnKind);
+                            outerFrameState.setDuringCall(true);
+                        }
+                        frameState.setOuterFrameState(outerFrameState);
+                    }
+                }
+            }
+        }
+    }
+
+    private static boolean isStateAfterException(FrameState frameState) {
+        return frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI || (frameState.bci == BytecodeFrame.UNWIND_BCI && !frameState.method().isSynchronized());
+    }
+
+    protected static void handleMissingAfterExceptionFrameState(FrameState nonReplaceableFrameState) {
+        Graph graph = nonReplaceableFrameState.graph();
+        NodeWorkList workList = graph.createNodeWorkList();
+        workList.add(nonReplaceableFrameState);
+        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 {
+                        FixedNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+                        if (fixedStateSplit instanceof BeginNode) {
+                            deoptimizeNode = BeginNode.begin(deoptimizeNode);
+                        }
+                        fixedStateSplit.replaceAtPredecessor(deoptimizeNode);
+                        GraphUtil.killCFG(fixedStateSplit);
+                    }
+                }
+            }
+        }
+    }
+
     public static ValueNode mergeReturns(MergeNode merge, List<? extends ReturnNode> returnNodes) {
         PhiNode returnValuePhi = null;
 
@@ -1504,7 +1550,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 +1564,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 +1612,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/IterativeConditionalEliminationPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -62,7 +62,7 @@
             canonicalizer.applyIncremental(graph, context, listener.getChangedNodes());
             listener.getChangedNodes().clear();
             if (++count > MAX_ITERATIONS) {
-                throw new BailoutException("Number of iterations in conditional elimination phase exceeds " + MAX_ITERATIONS);
+                throw new BailoutException("Number of iterations in ConditionalEliminationPhase phase exceeds " + MAX_ITERATIONS);
             }
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Mon Apr 28 11:18:15 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,19 +44,22 @@
  * 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 {
 
     private static final String GROUP_NAME = "~profiled weight";
     private static final String GROUP_NAME_WITHOUT = "~profiled weight (invoke-free sections)";
+    private static final String GROUP_NAME_INVOKES = "~profiled invokes";
 
     private static final boolean WITH_SECTION_HEADER = false;
+    private static boolean WITH_INVOKE_FREE_SECTIONS = false;
+    private static boolean WITH_INVOKES = true;
 
     @Override
     protected void run(StructuredGraph graph) {
@@ -65,23 +69,38 @@
         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);
+        // don't put the counter increase directly after the start (problems with OSR)
+        FixedWithNextNode current = graph.start();
+        while (current.next() instanceof FixedWithNextNode) {
+            current = (FixedWithNextNode) current.next();
+        }
+        addSectionCounters(current, Arrays.asList(cfg.getBlocks()), cfg.getLoops(), schedule, probabilities);
+
+        if (WITH_INVOKES) {
+            for (Node node : graph.getNodes()) {
+                if (node instanceof Invoke) {
+                    Invoke invoke = (Invoke) node;
+                    DynamicCounterNode.addCounterBefore(GROUP_NAME_INVOKES, invoke.callTarget().targetName(), 1, true, invoke.asNode());
+
+                }
+            }
+        }
     }
 
-    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);
         DynamicCounterNode.addCounterBefore(GROUP_NAME, sectionHead(start), (long) weight, true, start.next());
-        if (!hasInvoke(blocks)) {
+        if (WITH_INVOKE_FREE_SECTIONS && !hasInvoke(blocks)) {
             DynamicCounterNode.addCounterBefore(GROUP_NAME_WITHOUT, sectionHead(start), (long) weight, true, start.next());
         }
     }
@@ -108,7 +127,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Apr 28 11:18:15 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();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Mon Apr 28 11:18:15 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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,233 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.code.Assumptions;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.debug.DebugMetric;
+import com.oracle.graal.graph.Node;
+import com.oracle.graal.graph.spi.CanonicalizerTool;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.compiler.common.type.ObjectStamp;
+import com.oracle.graal.phases.graph.PostOrderNodeIterator;
+import com.oracle.graal.phases.tiers.PhaseContext;
+
+import java.util.ArrayList;
+
+/**
+ * <p>
+ * For readability purposes the code realizing control-flow-sensitive reductions is chopped into
+ * several classes in an inheritance hierarchy, this class being their common ancestor. That way,
+ * many dependencies can be ruled out immediately (e.g., private members of a class aren't needed by
+ * other classes). The whole thing is reminiscent of trait-based patterns, minus their
+ * disadvantages.
+ * </p>
+ *
+ *
+ * <p>
+ * This class makes available little more than a few fields and a few utility methods used
+ * throughout the remaining components making up control-flow sensitive reductions.
+ * </p>
+ * */
+public abstract class BaseReduction extends PostOrderNodeIterator<State> {
+
+    protected static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved");
+    protected static final DebugMetric metricGuardingPiNodeRemoved = Debug.metric("GuardingPiNodeRemoved");
+    protected static final DebugMetric metricFixedGuardNodeRemoved = Debug.metric("FixedGuardNodeRemoved");
+    protected static final DebugMetric metricMethodResolved = Debug.metric("MethodResolved");
+
+    /**
+     * <p>
+     * Upon visiting a {@link com.oracle.graal.nodes.FixedNode FixedNode} in
+     * {@link #node(com.oracle.graal.nodes.FixedNode)}, an impossible path may be detected. We'd
+     * like to insert an unconditional deoptimizing node as a hint for Dead Code Elimination to kill
+     * that branch. However that can't be made on the go (a
+     * {@link com.oracle.graal.nodes.ControlSinkNode} can't have successors). Thus their insertion
+     * is postponed till the end of a round of
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction}.
+     * </p>
+     *
+     * @see State#impossiblePath()
+     * @see com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#finished()
+     * */
+    public static class PostponedDeopt {
+
+        private final boolean goesBeforeFixed;
+        private final FixedWithNextNode fixed;
+        private final DeoptimizationReason deoptReason;
+
+        public PostponedDeopt(boolean goesBeforeFixed, FixedWithNextNode fixed, DeoptimizationReason deoptReason) {
+            this.goesBeforeFixed = goesBeforeFixed;
+            this.fixed = fixed;
+            this.deoptReason = deoptReason;
+        }
+
+        public void doRewrite(LogicNode falseConstant) {
+            StructuredGraph graph = fixed.graph();
+            // have to insert a FixedNode other than a ControlSinkNode
+            FixedGuardNode buckStopsHere = graph.add(new FixedGuardNode(falseConstant, deoptReason, DeoptimizationAction.None));
+            if (goesBeforeFixed) {
+                fixed.replaceAtPredecessor(buckStopsHere);
+            } else {
+                graph.addAfterFixed(fixed, buckStopsHere);
+            }
+        }
+
+    }
+
+    protected static class PostponedDeopts extends ArrayList<PostponedDeopt> {
+
+        private static final long serialVersionUID = 7188324432387121238L;
+
+        /**
+         * Enqueue adding a {@link com.oracle.graal.nodes.DeoptimizeNode} right before the fixed
+         * argument, will be done once we're done traversing the graph.
+         *
+         * @see #finished()
+         * */
+        void addDeoptBefore(FixedWithNextNode fixed, DeoptimizationReason deoptReason) {
+            add(new PostponedDeopt(true, fixed, deoptReason));
+        }
+
+        /**
+         * Enqueue adding a {@link com.oracle.graal.nodes.DeoptimizeNode} right after the fixed
+         * argument, will be done once we're done traversing the graph.
+         *
+         * @see #finished()
+         * */
+        void addDeoptAfter(FixedWithNextNode fixed, DeoptimizationReason deoptReason) {
+            add(new PostponedDeopt(false, fixed, deoptReason));
+        }
+
+    }
+
+    /**
+     * <p>
+     * One of the promises of
+     * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)}
+     * is that a "maximally reduced" node is returned. That is achieved in part by leveraging
+     * {@link com.oracle.graal.graph.Node#canonical(com.oracle.graal.graph.spi.CanonicalizerTool)}.
+     * Doing so, in turn, requires this subclass of
+     * {@link com.oracle.graal.graph.spi.CanonicalizerTool}.
+     * </p>
+     * */
+    public final class Tool implements CanonicalizerTool {
+
+        private final PhaseContext context;
+
+        public Tool(PhaseContext context) {
+            this.context = context;
+        }
+
+        @Override
+        public Assumptions assumptions() {
+            return context.getAssumptions();
+        }
+
+        @Override
+        public MetaAccessProvider getMetaAccess() {
+            return context.getMetaAccess();
+        }
+
+        @Override
+        public ConstantReflectionProvider getConstantReflection() {
+            return context.getConstantReflection();
+        }
+
+        /**
+         * Postpone
+         * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)}
+         * until {@link FlowSensitiveReduction#finished()} for the reasons covered there.
+         * */
+        @Override
+        public void removeIfUnused(Node node) {
+            // GraphUtil.tryKillUnused(node);
+        }
+
+        @Override
+        public boolean canonicalizeReads() {
+            return false;
+        }
+    } // end of class FlowSensitiveReduction.Tool
+
+    protected final LogicConstantNode trueConstant;
+    protected final LogicConstantNode falseConstant;
+    protected final ConstantNode nullConstant;
+
+    protected final CanonicalizerTool tool;
+    protected final StructuredGraph graph;
+
+    protected EquationalReasoner reasoner;
+
+    protected final PostponedDeopts postponedDeopts = new PostponedDeopts();
+
+    protected BaseReduction(FixedNode start, State initialState, PhaseContext context) {
+        super(start, initialState);
+        graph = start.graph();
+        trueConstant = LogicConstantNode.tautology(graph);
+        falseConstant = LogicConstantNode.contradiction(graph);
+        nullConstant = ConstantNode.defaultForKind(Kind.Object, graph); // ConstantNode.forObject(null,
+                                                                        // metaAccess, graph);
+        tool = new Tool(context);
+        reasoner = new EquationalReasoner(graph, tool, trueConstant, falseConstant, nullConstant);
+    }
+
+    /**
+     * <p>
+     * Test whether the output's stamp is an upcast of that of the input. For example, upon
+     * replacing a CheckCastNode in
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode, com.oracle.graal.nodes.ValueNode)}
+     * we don't want to be left with an upcast, as it loses precision.
+     * </p>
+     *
+     * <p>
+     * As usual with object stamps, they can be compared along different dimensions (alwaysNull,
+     * etc.) It's enough for one such dimension to show precision loss for the end result to be
+     * reported as such.
+     * </p>
+     *
+     * */
+    protected static boolean precisionLoss(ValueNode input, ValueNode output) {
+        ObjectStamp inputStamp = (ObjectStamp) input.stamp();
+        ObjectStamp outputStamp = (ObjectStamp) output.stamp();
+        if (FlowUtil.isMorePrecise(inputStamp.type(), outputStamp.type())) {
+            return true;
+        }
+        if (lessThan(outputStamp.alwaysNull(), inputStamp.alwaysNull())) {
+            return true;
+        }
+        if (lessThan(outputStamp.nonNull(), inputStamp.nonNull())) {
+            return true;
+        }
+        if (lessThan(outputStamp.isExactType(), inputStamp.isExactType())) {
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean lessThan(boolean a, boolean b) {
+        return a == false && b == true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,87 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.ResolvedJavaType;
+import com.oracle.graal.nodes.LogicNode;
+import com.oracle.graal.nodes.ShortCircuitOrNode;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.calc.IsNullNode;
+import com.oracle.graal.nodes.java.InstanceOfNode;
+
+/**
+ * @see #extract(com.oracle.graal.nodes.LogicNode)
+ * */
+class CastCheckExtractor {
+
+    public final ResolvedJavaType type;
+    public final ValueNode subject;
+
+    CastCheckExtractor(ResolvedJavaType type, ValueNode subject) {
+        this.type = type;
+        this.subject = subject;
+    }
+
+    static CastCheckExtractor extractCastCheckInfo(LogicNode x, LogicNode y) {
+        if (x instanceof IsNullNode) {
+            IsNullNode isNull = (IsNullNode) x;
+            ValueNode subject = isNull.object();
+            if (isInstanceOfCheckOn(y, subject)) {
+                InstanceOfNode iOf = (InstanceOfNode) y;
+                return new CastCheckExtractor(iOf.type(), subject);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * This method detects whether the argument realizes the CheckCast pattern. If so, distills and
+     * returns the essentials of such check, otherwise returns null.
+     * */
+    static CastCheckExtractor extract(LogicNode cond) {
+        if (!(cond instanceof ShortCircuitOrNode)) {
+            return null;
+        }
+        ShortCircuitOrNode orNode = (ShortCircuitOrNode) cond;
+        if (orNode.isXNegated() || orNode.isYNegated()) {
+            return null;
+        }
+        CastCheckExtractor result = extractCastCheckInfo(orNode.getX(), orNode.getY());
+        if (result != null) {
+            return result;
+        }
+        result = extractCastCheckInfo(orNode.getY(), orNode.getX());
+        return result;
+    }
+
+    /**
+     * Porcelain method.
+     * */
+    public static boolean isInstanceOfCheckOn(LogicNode cond, ValueNode subject) {
+        if (!(cond instanceof InstanceOfNode)) {
+            return false;
+        }
+        InstanceOfNode io = (InstanceOfNode) cond;
+        return io.object() == subject;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,337 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.IsNullNode;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.compiler.common.type.ObjectStamp;
+import com.oracle.graal.compiler.common.type.StampFactory;
+import com.oracle.graal.nodes.type.StampTool;
+import com.oracle.graal.phases.tiers.PhaseContext;
+
+import static com.oracle.graal.api.meta.DeoptimizationAction.InvalidateReprofile;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
+
+/**
+ * <p>
+ * This class implements control-flow sensitive reductions for
+ * {@link com.oracle.graal.nodes.java.CheckCastNode}.
+ * </p>
+ *
+ * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
+ * */
+public abstract class CheckCastReduction extends GuardingPiReduction {
+
+    public CheckCastReduction(FixedNode start, State initialState, PhaseContext context) {
+        super(start, initialState, context);
+    }
+
+    /**
+     * <p>
+     * This phase is able to refine the types of reference-values at use sites provided a
+     * {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} is available witnessing
+     * that fact.
+     * </p>
+     *
+     * <p>
+     * This method turns non-redundant {@link com.oracle.graal.nodes.java.CheckCastNode}s into
+     * {@link com.oracle.graal.nodes.GuardingPiNode}s. Once such lowering has been performed (during
+     * run N of this phase) follow-up runs attempt to further simplify the resulting node, see
+     * {@link EquationalReasoner#downcastedGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode, Witness)}
+     * and {@link #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}
+     * </p>
+     *
+     * <p>
+     * Precondition: the inputs (ie, object) hasn't been deverbosified yet.
+     * </p>
+     * */
+    protected final void visitCheckCastNode(CheckCastNode checkCast) {
+
+        /*
+         * checkCast.object() hasn't been deverbosified yet.
+         */
+
+        if (!FlowUtil.hasLegalObjectStamp(checkCast)) {
+            // This situation is exercised by test Class_cast01
+            return;
+        }
+
+        final ValueNode subject = checkCast.object();
+        final ResolvedJavaType toType = checkCast.type();
+        ObjectStamp subjectStamp = (ObjectStamp) subject.stamp();
+        ResolvedJavaType subjectType = subjectStamp.type();
+
+        // --------- checkCast deemed redundant by subject-stamp alone ---------
+        // --------- in particular due to stamp informing always null ----------
+        boolean isRedundantPerStamp = StampTool.isObjectAlwaysNull(subject) || (subjectType != null && toType.isAssignableFrom(subjectType));
+        if (isRedundantPerStamp) {
+            metricCheckCastRemoved.increment();
+            checkCast.replaceAtUsages(subject);
+            graph.removeFixed(checkCast);
+            return;
+        }
+
+        assert !StampTool.isObjectAlwaysNull(subject) : "Null as per stamp subjects should have been handled above";
+
+        // --------- checkCast deemed unsatisfiable by subject-stamp alone ---------
+        if (state.knownNotToConform(subject, toType)) {
+            postponedDeopts.addDeoptBefore(checkCast, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException);
+            state.impossiblePath();
+            // let FixedGuardNode(false).simplify() prune the dead-code control-path
+            return;
+        }
+
+        /*
+         * Remark: subject may be TypeProxyNode, GuardedValueNode, ProxyNode, GuardingPiNode, among
+         * others.
+         */
+
+        PiNode untrivialNull = reasoner.untrivialNull(subject);
+        if (untrivialNull != null) {
+            metricCheckCastRemoved.increment();
+            checkCast.replaceAtUsages(untrivialNull);
+            graph.removeFixed(checkCast);
+            return;
+        }
+
+        Witness w = state.typeInfo(subject);
+
+        if (w == null) {
+            /*
+             * If there's no witness, attempting `downcasted(subject)` is futile.
+             */
+            visitCheckCastNodeLackingWitness(checkCast);
+            return;
+        }
+
+        visitCheckCastNodeWithWitness(checkCast);
+
+    }
+
+    /**
+     * Given that no witness is available for the {@link com.oracle.graal.nodes.java.CheckCastNode}
+     * 's subject there's no point in downcasting such subject, ie no
+     * {@link com.oracle.graal.nodes.PiNode} can be fabricated for the subject.
+     *
+     * @see #lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode,
+     *      com.oracle.graal.nodes.ValueNode)
+     *
+     * */
+    private void visitCheckCastNodeLackingWitness(CheckCastNode checkCast) {
+        final ValueNode subject = checkCast.object();
+        final ResolvedJavaType toType = checkCast.type();
+        if (toType.isInterface()) {
+            return;
+        }
+        assert reasoner.downcasted(subject) == subject;
+        lowerCheckCastAnchorFriendlyWay(checkCast, subject);
+    }
+
+    /**
+     * Porcelain method.
+     *
+     * <p>
+     * Rather than tracking the CheckCastNode via {@link com.oracle.graal.phases.common.cfs.State
+     * State} (doing so woud add a special case because a
+     * {@link com.oracle.graal.nodes.java.CheckCastNode} isn't a
+     * {@link com.oracle.graal.nodes.extended.GuardingNode}) this method creates an anchor by
+     * lowering the CheckCastNode into a FixedGuardNode. Not the same way as done by
+     * {@link com.oracle.graal.nodes.java.CheckCastNode#lower(com.oracle.graal.nodes.spi.LoweringTool)}
+     * which lowers into a {@link com.oracle.graal.nodes.GuardingPiNode} (which is not a
+     * {@link com.oracle.graal.nodes.extended.GuardingNode}).
+     * </p>
+     *
+     * <p>
+     * With that, state tracking can proceed as usual.
+     * </p>
+     *
+     * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
+     *
+     * */
+    public void lowerCheckCastAnchorFriendlyWay(CheckCastNode checkCast, ValueNode subject) {
+        ValueNode originalCheckCastObject = checkCast.object();
+
+        ObjectStamp subjectStamp = (ObjectStamp) subject.stamp();
+        final ResolvedJavaType toType = checkCast.type();
+        ObjectStamp resultStamp = (ObjectStamp) StampFactory.declared(toType);
+        JavaTypeProfile profile = checkCast.profile();
+
+        assert FlowUtil.isLegalObjectStamp(subjectStamp);
+        assert subjectStamp.type() == null || !toType.isAssignableFrom(subjectStamp.type()) : "No need to lower in an anchor-friendly way in the first place";
+
+        /*
+         * Depending on what is known about the subject:
+         * 
+         * (a) definitely-non-null
+         * 
+         * (b) null-not-seen-in-profiling
+         * 
+         * (c) runtime-null-check-needed
+         * 
+         * the condition (of the cast-guard to be emitted) and the stamp (of the PiNode to be
+         * emitted) are going to be different. Each of the three branches below deals with one of
+         * the cases above.
+         */
+        LogicNode condition;
+        if (subjectStamp.nonNull()) {
+            /*
+             * (1 of 3) definitely-non-null
+             */
+            // addWithoutUnique for the same reason as in CheckCastNode.lower()
+            condition = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile));
+            reasoner.added.add(condition);
+            resultStamp = FlowUtil.asNonNullStamp(resultStamp);
+            // TODO fix in CheckCastNode.lower()
+        } else {
+            if (profile != null && profile.getNullSeen() == ProfilingInfo.TriState.FALSE) {
+                /*
+                 * (2 of 3) null-not-seen-in-profiling
+                 */
+                IsNullNode isNN = graph.unique(new IsNullNode(subject));
+                reasoner.added.add(isNN);
+                FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true));
+                graph.addBeforeFixed(checkCast, nullCheck);
+                // not calling wrapInPiNode() because we don't want to rememberSubstitution()
+                PiNode nonNullGuarded = graph.unique(new PiNode(subject, FlowUtil.asNonNullStamp(subjectStamp), nullCheck));
+                reasoner.added.add(nonNullGuarded);
+                // addWithoutUnique for the same reason as in CheckCastNode.lower()
+                condition = graph.addWithoutUnique(new InstanceOfNode(toType, nonNullGuarded, profile));
+                reasoner.added.add(condition);
+                resultStamp = FlowUtil.asNonNullStamp(resultStamp);
+            } else {
+                /*
+                 * (3 of 3) runtime-null-check-needed
+                 */
+                // addWithoutUnique for the same reason as in CheckCastNode.lower()
+                InstanceOfNode typeTest = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile));
+                reasoner.added.add(typeTest);
+                LogicNode nullTest = graph.unique(new IsNullNode(subject));
+                reasoner.added.add(nullTest);
+                // TODO (ds) replace with probability of null-seen when available
+                final double shortCircuitProbability = NOT_FREQUENT_PROBABILITY;
+                condition = LogicNode.or(nullTest, typeTest, shortCircuitProbability);
+                reasoner.added.add(condition);
+            }
+        }
+
+        /*
+         * Add a cast-guard (checking only what needs to be checked) and a PiNode (to be used in
+         * place of the CheckCastNode).
+         */
+        FixedGuardNode castGuard = graph.add(new FixedGuardNode(condition, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException, InvalidateReprofile));
+        graph.addBeforeFixed(checkCast, castGuard);
+
+        assert FlowUtil.isLegalObjectStamp(resultStamp);
+        Witness w = state.typeInfo(subject);
+        assert !isTypeOfWitnessBetter(w, resultStamp);
+
+        if (!FlowUtil.lacksUsages(checkCast)) {
+            // not calling wrapInPiNode() because we don't want to rememberSubstitution()
+            PiNode checkedObject = graph.unique(new PiNode(subject, resultStamp, castGuard));
+            reasoner.added.add(checkedObject);
+            assert !precisionLoss(originalCheckCastObject, checkedObject);
+            assert !precisionLoss(subject, checkedObject);
+            checkCast.replaceAtUsages(checkedObject);
+        }
+
+        graph.removeFixed(checkCast);
+
+        if (resultStamp.nonNull()) {
+            state.trackIO(subject, toType, castGuard);
+        } else {
+            state.trackCC(subject, toType, castGuard);
+        }
+    }
+
+    /**
+     * Porcelain method.
+     * */
+    public static boolean isTypeOfWitnessBetter(Witness w, ObjectStamp stamp) {
+        if (w == null) {
+            return false;
+        }
+        return FlowUtil.isMorePrecise(w.type(), stamp.type());
+    }
+
+    /**
+     *
+     * Please note in this method "subject" refers to the downcasted input to the checkCast.
+     *
+     * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
+     * */
+    private void visitCheckCastNodeWithWitness(CheckCastNode checkCast) {
+
+        final ResolvedJavaType toType = checkCast.type();
+
+        ValueNode subject;
+        if (checkCast.object() instanceof CheckCastNode) {
+            subject = reasoner.downcasted(checkCast);
+            if (subject == checkCast) {
+                subject = reasoner.downcasted(checkCast.object());
+            }
+        } else {
+            subject = reasoner.downcasted(checkCast.object());
+        }
+
+        ObjectStamp subjectStamp = (ObjectStamp) subject.stamp();
+        ResolvedJavaType subjectType = subjectStamp.type();
+
+        // TODO move this check to downcasted()
+        assert !precisionLoss(checkCast.object(), subject);
+
+        /*
+         * At this point, two sources of (partial) information: the witness and the stamp of
+         * subject. The latter might be more precise than the witness (eg, subject might be
+         * GuardedValueNode)
+         */
+
+        // --------- checkCast made redundant by downcasting its input ---------
+        if (subjectType != null && toType.isAssignableFrom(subjectType)) {
+            checkCast.replaceAtUsages(subject);
+            graph.removeFixed(checkCast);
+            return;
+        }
+
+        /*
+         * At this point, `downcasted()` might or might not have delivered a more precise value. If
+         * more precise, it wasn't precise enough to conform to `toType`. Even so, for the
+         * `toType.isInterface()` case (dealt with below) we'll replace the checkCast's input with
+         * that value (its class-stamp being more precise than the original).
+         */
+
+        if (toType.isInterface()) {
+            boolean wasDowncasted = (subject != checkCast.object());
+            if (wasDowncasted) {
+                FlowUtil.replaceInPlace(checkCast, checkCast.object(), subject);
+            }
+            return;
+        }
+
+        lowerCheckCastAnchorFriendlyWay(checkCast, subject);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,946 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.ResolvedJavaType;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.debug.DebugMetric;
+import com.oracle.graal.graph.Node;
+import com.oracle.graal.graph.NodeBitMap;
+import com.oracle.graal.graph.spi.CanonicalizerTool;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.FloatingNode;
+import com.oracle.graal.nodes.calc.IsNullNode;
+import com.oracle.graal.nodes.calc.ObjectEqualsNode;
+import com.oracle.graal.nodes.extended.GuardedNode;
+import com.oracle.graal.nodes.extended.GuardingNode;
+import com.oracle.graal.nodes.java.CheckCastNode;
+import com.oracle.graal.nodes.java.InstanceOfNode;
+import com.oracle.graal.nodes.spi.ValueProxy;
+import com.oracle.graal.compiler.common.type.IllegalStamp;
+import com.oracle.graal.compiler.common.type.ObjectStamp;
+import com.oracle.graal.compiler.common.type.StampFactory;
+import com.oracle.graal.nodes.type.StampTool;
+import com.oracle.graal.nodes.util.GraphUtil;
+
+import java.util.IdentityHashMap;
+import java.util.Set;
+
+/**
+ * <p>
+ * This class implements a simple partial evaluator that recursively reduces a given
+ * {@link com.oracle.graal.nodes.calc.FloatingNode} into a simpler one based on the current state.
+ * Such evaluator comes handy when visiting a {@link com.oracle.graal.nodes.FixedNode} N, just
+ * before updating the state for N. At the pre-state, an {@link EquationalReasoner
+ * EquationalReasoner} can be used to reduce N's inputs (actually only those inputs of Value and
+ * Condition {@link com.oracle.graal.graph.InputType InputType}). For an explanation of where it's
+ * warranted to replace "old input" with "reduced input", see the inline comments in method
+ * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node n) deverbosify(Node n)}
+ * </p>
+ *
+ * <p>
+ * The name {@link EquationalReasoner EquationalReasoner} was chosen because it conveys what it
+ * does.
+ * </p>
+ */
+public final class EquationalReasoner {
+
+    private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved");
+    private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved");
+    private static final DebugMetric metricObjectEqualsRemoved = Debug.metric("ObjectEqualsRemoved");
+    private static final DebugMetric metricEquationalReasoning = Debug.metric("EquationalReasoning");
+    private static final DebugMetric metricDowncasting = Debug.metric("Downcasting");
+
+    private final StructuredGraph graph;
+    private final CanonicalizerTool tool;
+    private final LogicConstantNode trueConstant;
+    private final LogicConstantNode falseConstant;
+    private final ConstantNode nullConstant;
+
+    private State state;
+    private NodeBitMap visited;
+
+    /**
+     * The reduction of a {@link com.oracle.graal.nodes.calc.FloatingNode} performed by
+     * {@link EquationalReasoner EquationalReasoner} may result in a FloatingNode being added to the
+     * graph. Those nodes aren't tracked in the {@link EquationalReasoner#visited visited}
+     * {@link com.oracle.graal.graph.NodeBitMap NodeBitMap} but in this set instead (those nodes are
+     * added after the {@link com.oracle.graal.graph.NodeBitMap} was obtained).
+     */
+    final Set<ValueNode> added = java.util.Collections.newSetFromMap(new IdentityHashMap<ValueNode, Boolean>());
+
+    /**
+     * The reduction of a FloatingNode performed by {@link EquationalReasoner EquationalReasoner}
+     * may result in a FloatingNode being added to the graph. Those nodes are tracked in this map,
+     * to avoid recomputing them.
+     *
+     * The substitutions tracked in this field become invalid as described in
+     * {@link #updateState(com.oracle.graal.phases.common.cfs.State) updateState(State)}
+     */
+    private final IdentityHashMap<ValueNode, ValueNode> substs = new IdentityHashMap<>();
+
+    public EquationalReasoner(StructuredGraph graph, CanonicalizerTool tool, LogicConstantNode trueConstant, LogicConstantNode falseConstant, ConstantNode nullConstant) {
+        this.graph = graph;
+        this.tool = tool;
+        this.trueConstant = trueConstant;
+        this.falseConstant = falseConstant;
+        this.nullConstant = nullConstant;
+    }
+
+    /**
+     * {@link #added} grows during a run of
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase
+     * FlowSensitiveReductionPhase}, and doesn't survive across runs.
+     * */
+    public void forceState(State s) {
+        state = s;
+        substs.clear();
+        added.clear();
+        visited = null;
+        versionNrAsofLastForce = s.versionNr;
+    }
+
+    /**
+     * <p>
+     * Gaining more precise type information about an SSA value doesn't "invalidate" as such any of
+     * the substitutions tracked in {@link EquationalReasoner#substs substs}, at least not in the
+     * sense of making the value tracked by one such entry "wrong". However, clearing the
+     * {@link EquationalReasoner#substs substs} is still justified because next time they are
+     * computed, the newly computed reduction could (in principle) be more effective (due to the
+     * more precise type information).
+     * </p>
+     *
+     * <p>
+     * Between clearings of cached substitutions, it is expected they get applied a number of times
+     * to justify the bookkeeping cost.
+     * </p>
+     *
+     */
+    public void updateState(State s) {
+        assert s != null;
+        if (state == null || state != s || state.versionNr != versionNrAsofLastForce) {
+            forceState(s);
+        }
+    }
+
+    private int versionNrAsofLastForce = 0;
+
+    /**
+     * Reduce the argument based on the state at the program point where the argument is consumed.
+     * For most FixedNodes, that's how their inputs can be reduced. Two exceptions:
+     * <ul>
+     * <li>
+     * the condition of a {@link com.oracle.graal.nodes.GuardingPiNode}, see
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}
+     * </li>
+     * <li>
+     * the condition of a {@link com.oracle.graal.nodes.FixedGuardNode}, see
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)}
+     * </li>
+     *
+     * </ul>
+     *
+     *
+     * <p>
+     * Part of the reduction work is delegated to baseCase-style reducers, whose contract explicitly
+     * requires them not to deverbosify the argument's inputs --- the decision is made based on the
+     * argument only (thus "base case"). Returning the unmodified argument is how a baseCase-style
+     * tells this method to fall to the default case (for a floating node only: walk into the
+     * argument's inputs, canonicalize followed by
+     * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)
+     * rememberSubstitution()} if any input changed).
+     * </p>
+     *
+     * <p>
+     * This method must behave as a function (idempotent query method), ie refrain from mutating the
+     * state other than updating caches:
+     * <ul>
+     * <li>{@link EquationalReasoner#added EquationalReasoner#added},</li>
+     * <li>{@link EquationalReasoner#visited EquationalReasoner#visited} and</li>
+     * <li>the cache updated via
+     * {@link EquationalReasoner#rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)
+     * EquationalReasoner#rememberSubstitution(ValueNode, FloatingNode)}.</li>
+     * </ul>
+     * </p>
+     *
+     * <p>
+     * In turn, baseCase-style reducers are even more constrained: besides behaving as functions,
+     * their contract prevents them from updating any caches (basically because they already grab
+     * the answer from caches, if the answer isn't there they should just return their unmodified
+     * argument).
+     * </p>
+     *
+     * <p>
+     * This method returns:
+     * <ul>
+     * <li>
+     * the original argument, in case no reduction possible.</li>
+     * <li>
+     * a {@link com.oracle.graal.nodes.ValueNode ValueNode} different from the argument, in case the
+     * conditions for a reduction were met. The node being returned might be already in the graph.
+     * In any case it's canonicalized already, the caller need not perform that again.</li>
+     * <li>
+     * the unmodified argument, in case no reduction was made. Otherwise, a maximally reduced
+     * {@link com.oracle.graal.nodes.ValueNode}.</li>
+     * </ul>
+     * </p>
+     *
+     * @see com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode)
+     *
+     * @see com.oracle.graal.phases.common.cfs.BaseReduction.Tool
+     *
+     */
+    public Node deverbosify(final Node n) {
+
+        // --------------------------------------------------------------------
+        // cases that don't initiate any call-chain that may enter this method
+        // --------------------------------------------------------------------
+
+        if (n == null) {
+            return null;
+        }
+        assert !(n instanceof GuardNode) : "This phase not yet ready to run during MidTier";
+        if (!(n instanceof ValueNode)) {
+            return n;
+        }
+        ValueNode v = (ValueNode) n;
+        if (v.stamp() instanceof IllegalStamp) {
+            return v;
+        }
+        if (FlowUtil.isLiteralNode(v)) {
+            return v;
+        }
+        ValueNode result = substs.get(v);
+        if (result != null) {
+            // picked cached substitution
+            return result;
+        }
+        if ((visited != null && visited.contains(n)) || added.contains(v)) {
+            return v;
+        }
+
+        // --------------------------------------------------------------------
+        // stack overflow prevention via added, visited
+        // --------------------------------------------------------------------
+
+        if (visited == null) {
+            visited = graph.createNodeBitMap();
+        }
+        visited.mark(n);
+
+        /*
+         * Past this point, if we ever want `n` to be deverbosified, it must be looked-up by one of
+         * the cases above. One sure way to achieve that is with `rememberSubstitution(old, new)`
+         */
+        if (v instanceof ValueProxy) {
+            return downcasted(v);
+        }
+
+        if (n instanceof FloatingNode) {
+            /*
+             * `deverbosifyFloatingNode()` will drill down over floating inputs, when that not
+             * possible anymore it resorts to calling `downcasted()`. Thus it's ok to take the
+             * `deverbosifyFloatingNode()` route first, as no downcasting opportunity will be
+             * missed.
+             */
+            return deverbosifyFloatingNode((FloatingNode) n);
+        }
+
+        if (FlowUtil.hasLegalObjectStamp(v)) {
+            return downcasted(v);
+        }
+
+        return n;
+    }
+
+    /**
+     * This method:
+     *
+     * <ul>
+     * <li>
+     * Recurses only over floating inputs to attempt reductions, leave anything else as is.</li>
+     * <li>
+     * Performs copy-on-write aka lazy-DAG-copying as described in source comments, in-line.</li>
+     * <li>
+     * Usage: must be called only from {@link #deverbosify(com.oracle.graal.graph.Node)
+     * deverbosify(Node)}.</li>
+     * </ul>
+     * */
+    public Node deverbosifyFloatingNode(final FloatingNode n) {
+
+        assert n != null : "Should have been caught in deverbosify()";
+        assert !(n instanceof ValueProxy) : "Should have been caught in deverbosify()";
+        assert !FlowUtil.isLiteralNode(n) : "Should have been caught in deverbosify()";
+
+        if (n instanceof PhiNode) {
+            /*
+             * Each input to a PhiNode should be deverbosified with the state applicable to the path
+             * providing such input, as done in visitAbstractEndNode()
+             */
+            return n;
+        }
+
+        final FloatingNode f = baseCaseFloating(n);
+        if (f != n) {
+            return f;
+        }
+
+        FloatingNode changed = null;
+        for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(f)) {
+            /*
+             * Although deverbosify() is invoked below, it's only for floating inputs. That way, the
+             * state can't be used to make invalid conclusions.
+             */
+            Node j = (i instanceof FloatingNode) ? deverbosify(i) : i;
+            if (i != j) {
+                assert j != f;
+                if (changed == null) {
+                    changed = (FloatingNode) f.copyWithInputs();
+                    added.add(changed);
+                    // copyWithInputs() implies graph.unique(changed)
+                    assert changed.isAlive();
+                    assert FlowUtil.lacksUsages(changed);
+                }
+                /*
+                 * Note: we don't trade i for j at each usage of i (doing so would change meaning)
+                 * but only at those usages consumed by `changed`. In turn, `changed` won't replace
+                 * `n` at arbitrary usages, but only where such substitution is valid as per the
+                 * state holding there. In practice, this means the buck stops at the "root"
+                 * FixedNode on whose inputs deverbosify() is invoked for the first time, via
+                 * deverbosifyInputsInPlace().
+                 */
+                FlowUtil.replaceInPlace(changed, i, j);
+            }
+        }
+        if (changed == null) {
+            assert visited.contains(f) || added.contains(f);
+            if (FlowUtil.hasLegalObjectStamp(f)) {
+                /*
+                 * No input has changed doesn't imply there's no witness to refine the
+                 * floating-object value.
+                 */
+                ValueNode d = downcasted(f);
+                return d;
+            } else {
+                return f;
+            }
+        }
+        FlowUtil.inferStampAndCheck(changed);
+        added.add(changed);
+        ValueNode canon = (ValueNode) changed.canonical(tool);
+        // might be already in `added`, no problem adding it again.
+        added.add(canon);
+        rememberSubstitution(f, canon);
+        return canon;
+    }
+
+    /**
+     * In case of doubt (on whether a reduction actually triggered) it's always ok to invoke "
+     * <code>rememberSubstitution(f, downcasted(f))</code>": this method records a map entry only if
+     * pre-image and image differ.
+     *
+     * @return the image of the substitution (ie, the second argument) unmodified.
+     * */
+    private <M extends ValueNode> M rememberSubstitution(ValueNode from, M to) {
+        assert from != null && to != null;
+        if (from == to) {
+            return to;
+        }
+        // we don't track literals because they map to themselves
+        if (FlowUtil.isLiteralNode(from)) {
+            assert from == to;
+            return to;
+        }
+        /*
+         * It's ok for different keys (which were not unique in the graph after all) to map to the
+         * same value. However any given key can't map to different values.
+         */
+        ValueNode image = substs.get(from);
+        if (image != null) {
+            assert image == to;
+            return to;
+        }
+        substs.put(from, to);
+        return to;
+    }
+
+    /**
+     * The contract for this baseCase-style method is covered in
+     * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)
+     * EquationalReasoner#deverbosify()}
+     *
+     * @return a {@link com.oracle.graal.nodes.calc.FloatingNode} different from the argument, in
+     *         case a reduction was made. The node being returned might be already in the graph. In
+     *         any case it's canonicalized already, the caller need not perform that again. In case
+     *         no reduction was made, this method returns the unmodified argument.
+     */
+    private FloatingNode baseCaseFloating(final FloatingNode f) {
+        if (f instanceof LogicNode) {
+            FloatingNode result = baseCaseLogicNode((LogicNode) f);
+            return rememberSubstitution(f, result);
+        }
+        return f;
+    }
+
+    /**
+     * <p>
+     * Reduce the argument based on the state at the program point for it (ie, based on
+     * "valid facts" only, without relying on any floating-guard-assumption).
+     * </p>
+     *
+     * <p>
+     * The inputs of the argument aren't traversed into, for that
+     * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)
+     * EquationalReasoner#deverbosify()} should be used instead.
+     * </p>
+     * <p>
+     * This method must behave as a function (idempotent query method): it should refrain from
+     * changing the state, as well as from updating caches (other than DebugMetric-s).
+     * </p>
+     *
+     * @return a {@link com.oracle.graal.nodes.LogicNode} different from the argument, in case a
+     *         reduction was made. The node being returned might be already in the graph. In any
+     *         case it's canonicalized already, the caller need not perform that again. In case no
+     *         reduction was made, this method returns the unmodified argument.
+     *
+     */
+    public FloatingNode baseCaseLogicNode(LogicNode condition) {
+        assert condition != null;
+        if (condition instanceof LogicConstantNode) {
+            return condition;
+        } else if (state.trueFacts.containsKey(condition)) {
+            metricEquationalReasoning.increment();
+            return trueConstant;
+        } else if (state.falseFacts.containsKey(condition)) {
+            metricEquationalReasoning.increment();
+            return falseConstant;
+        } else {
+            if (condition instanceof InstanceOfNode) {
+                return baseCaseInstanceOfNode((InstanceOfNode) condition);
+            } else if (condition instanceof IsNullNode) {
+                return baseCaseIsNullNode((IsNullNode) condition);
+            } else if (condition instanceof ObjectEqualsNode) {
+                return baseCaseObjectEqualsNode((ObjectEqualsNode) condition);
+            }
+        }
+        return condition;
+    }
+
+    /**
+     * Actually the same result delivered by this method could be obtained by just letting
+     * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)
+     * EquationalReasoner#deverbosify()} handle the argument in the default case for floating nodes
+     * (ie, deverbosify inputs followed by canonicalize). However it's done here for metrics
+     * purposes.
+     *
+     * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made;
+     *         otherwise the unmodified argument.
+     *
+     */
+    private LogicNode baseCaseInstanceOfNode(InstanceOfNode instanceOf) {
+        ValueNode scrutinee = GraphUtil.unproxify(instanceOf.object());
+        if (!FlowUtil.hasLegalObjectStamp(scrutinee)) {
+            return instanceOf;
+        }
+        if (state.isNull(scrutinee)) {
+            metricInstanceOfRemoved.increment();
+            return falseConstant;
+        } else if (state.isNonNull(scrutinee) && state.knownToConform(scrutinee, instanceOf.type())) {
+            metricInstanceOfRemoved.increment();
+            return trueConstant;
+        }
+        return instanceOf;
+    }
+
+    /**
+     * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was
+     *         performed; otherwise the unmodified argument.
+     *
+     */
+    private FloatingNode baseCaseIsNullNode(IsNullNode isNull) {
+        ValueNode object = isNull.object();
+        if (!FlowUtil.hasLegalObjectStamp(object)) {
+            return isNull;
+        }
+        ValueNode scrutinee = GraphUtil.unproxify(isNull.object());
+        GuardingNode evidence = untrivialNullAnchor(scrutinee);
+        if (evidence != null) {
+            metricNullCheckRemoved.increment();
+            return trueConstant;
+        } else if (state.isNonNull(scrutinee)) {
+            metricNullCheckRemoved.increment();
+            return falseConstant;
+        }
+        return isNull;
+    }
+
+    /**
+     * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made;
+     *         otherwise the unmodified argument.
+     */
+    private LogicNode baseCaseObjectEqualsNode(ObjectEqualsNode equals) {
+        if (!FlowUtil.hasLegalObjectStamp(equals.x()) || !FlowUtil.hasLegalObjectStamp(equals.y())) {
+            return equals;
+        }
+        ValueNode x = GraphUtil.unproxify(equals.x());
+        ValueNode y = GraphUtil.unproxify(equals.y());
+        if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) {
+            metricObjectEqualsRemoved.increment();
+            return falseConstant;
+        } else if (state.isNull(x) && state.isNull(y)) {
+            metricObjectEqualsRemoved.increment();
+            return trueConstant;
+        }
+        return equals;
+    }
+
+    /**
+     * It's always ok to use "<code>downcasted(object)</code>" instead of " <code>object</code>"
+     * because this method re-wraps the argument in a {@link com.oracle.graal.nodes.PiNode} only if
+     * the new stamp is strictly more refined than the original.
+     *
+     * <p>
+     * This method does not
+     * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)}
+     * .
+     * </p>
+     *
+     * @return One of:
+     *         <ul>
+     *         <li>a {@link com.oracle.graal.nodes.PiNode} with more precise stamp than the input if
+     *         the state warrants such downcasting</li>
+     *         <li>a {@link com.oracle.graal.nodes.java.CheckCastNode CheckCastNode} for the same
+     *         scrutinee in question</li>
+     *         <li>the unmodified argument otherwise.</li>
+     *         </ul>
+     */
+    ValueNode downcasted(final ValueNode object) {
+
+        // -------------------------------------------------
+        // actions based only on the stamp of the input node
+        // -------------------------------------------------
+
+        if (!FlowUtil.hasLegalObjectStamp(object)) {
+            return object;
+        }
+        if (FlowUtil.isLiteralNode(object)) {
+            return object;
+        }
+        if (StampTool.isObjectAlwaysNull(object.stamp())) {
+            return untrivialNull(object);
+        }
+
+        // ------------------------------------------
+        // actions based on the stamp and the witness
+        // ------------------------------------------
+
+        ValueNode scrutinee = GraphUtil.unproxify(object);
+
+        PiNode untrivialNull = untrivialNull(scrutinee);
+        if (untrivialNull != null) {
+            return untrivialNull;
+        }
+
+        Witness w = state.typeInfo(scrutinee);
+        if (w == null) {
+            // no additional hints being tracked for the scrutinee
+            return object;
+        }
+
+        assert !w.clueless();
+
+        ObjectStamp inputStamp = (ObjectStamp) object.stamp();
+        ObjectStamp witnessStamp = w.asStamp();
+        if (inputStamp.equals(witnessStamp) || !FlowUtil.isMorePrecise(witnessStamp, inputStamp)) {
+            // the witness offers no additional precision over current one
+            fixupTypeProfileStamp(object);
+            return object;
+        }
+
+        assert !FlowUtil.isMorePrecise(inputStamp.type(), w.type());
+
+        ValueNode result;
+        if (object instanceof ValueProxy) {
+            result = downcastedValueProxy((ValueProxy) object, w);
+        } else {
+            result = downcastedUtil(object, w);
+        }
+
+        return result;
+    }
+
+    /**
+     * TODO TypeProfileProxyNode.inferStamp doesn't infer non-null from non-null payload
+     *
+     * <p>
+     * And there's a bunch of asserts in
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} that assert no
+     * type-precision gets lost. Thus the need to fix-up on our own, as done here.
+     * </p>
+     * */
+    private static void fixupTypeProfileStamp(ValueNode object) {
+        if (!(object instanceof TypeProfileProxyNode)) {
+            return;
+        }
+        TypeProfileProxyNode profile = (TypeProfileProxyNode) object;
+        ObjectStamp outgoinStamp = (ObjectStamp) profile.stamp();
+        ObjectStamp payloadStamp = (ObjectStamp) profile.getObject().stamp();
+        if (payloadStamp.nonNull() && !outgoinStamp.nonNull()) {
+            profile.setStamp(FlowUtil.asNonNullStamp(outgoinStamp));
+        }
+    }
+
+    /**
+     * <p>
+     * Porcelain method.
+     * </p>
+     *
+     * <p>
+     * Utility to create, add to the graph,
+     * {@link EquationalReasoner#rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)}
+     * , and return a {@link com.oracle.graal.nodes.PiNode} that narrows into the given stamp,
+     * anchoring the payload.
+     * </p>
+     *
+     * <p>
+     * The resulting node might not have been in the graph already.
+     * </p>
+     * */
+    private PiNode wrapInPiNode(ValueNode payload, GuardingNode anchor, ObjectStamp newStamp, boolean remember) {
+        try (Debug.Scope s = Debug.scope("Downcast", payload)) {
+            assert payload != anchor : payload.graph().toString();
+            metricDowncasting.increment();
+            PiNode result = graph.unique(new PiNode(payload, newStamp, anchor.asNode()));
+            // we've possibly got a new node in the graph --- bookkeeping is in order.
+            added.add(result);
+            if (remember) {
+                rememberSubstitution(payload, result);
+            }
+            Debug.log("Downcasting from %s to %s", payload, result);
+            return result;
+        } catch (Throwable e) {
+            throw Debug.handle(e);
+        }
+    }
+
+    /**
+     * <p>
+     * If the argument is known null due to its stamp, there's no need to have an anchor for that
+     * fact and this method returns null.
+     * </p>
+     *
+     * <p>
+     * Otherwise, if an anchor is found it is returned, null otherwise.
+     * </p>
+     */
+    public GuardingNode untrivialNullAnchor(ValueNode object) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        if (StampTool.isObjectAlwaysNull(object)) {
+            return null;
+        }
+        return state.knownNull.get(GraphUtil.unproxify(object));
+    }
+
+    /**
+     *
+     * This method returns:
+     * <ul>
+     * <li><b>null</b>, if the argument is known null due to its stamp. Otherwise,</li>
+     * <li><b>a PiNode</b> wrapping the null constant and an anchor offering evidence as to why the
+     * argument is known null, if such anchor is available. Otherwise,</li>
+     * <li><b>null</b></li>
+     * </ul>
+     * <p>
+     * This method does not
+     * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)}
+     * .
+     * </p>
+     */
+    public PiNode untrivialNull(ValueNode object) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        GuardingNode anchor = untrivialNullAnchor(object);
+        if (anchor == null) {
+            return null;
+        }
+        if (object instanceof GuardedNode && StampTool.isObjectAlwaysNull(object.stamp())) {
+            return (PiNode) object;
+        }
+        // notice nullConstant is wrapped, not object
+        PiNode result = wrapInPiNode(nullConstant, anchor, (ObjectStamp) StampFactory.alwaysNull(), false);
+        return result;
+    }
+
+    // @formatter:off
+    /**
+     * <p>ValueProxys can be classified along two dimensions,
+     * in addition to the fixed-floating dichotomy.</p>
+     *
+     * <p>
+     *     First, we might be interested in separating those ValueProxys
+     *     that are entitled to change (usually narrow) their stamp from those that aren't.
+     *     In the first category are:
+     *       PiNode, PiArrayNode, GuardingPiNode,
+     *       CheckCastNode, UnsafeCastNode, and
+     *       GuardedValueNode.
+     * </p>
+     *
+     * <p>
+     *     A note on stamp-narrowing ValueProxys:
+     *     our state abstraction tracks only the type refinements induced by CheckCastNode and GuardingPiNode
+     *     (which are fixed nodes, unlike the other stamp-narrowing ValueProxys;
+     *     the reason being that the state abstraction can be updated only at fixed nodes).
+     *     As a result, the witness for a (PiNode, PiArrayNode, UnsafeCastNode, or GuardedValueNode)
+     *     may be less precise than the proxy's stamp. We don't want to lose such precision,
+     *     thus <code>downcasted(proxy) == proxy</code> in such cases.
+     * </p>
+     *
+     * <p>
+     *     The second classification focuses on
+     *     the additional information that travels with the proxy
+     *     (in addition to its "payload", ie getOriginalValue(), and any narrowing-stamp).
+     *     Such additional information boils down to:
+     *
+     *   (a) type profile (TypeProfileProxyNode)
+     *   (b) type profile (CheckCastNode)
+     *   (c) anchor (GuardedValueNode)
+     *   (d) anchor (PiNode)
+     *   (e) anchor and array length (PiArrayNode)
+     *   (f) optional anchor (UnsafeCastNode)
+     *   (g) deopt-condition (GuardingPiNode)
+     *   (h) LocationIdentity (MemoryProxyNOde)
+     *   (i) control-flow dependency (FixedValueAnchorNode)
+     *   (j) proxyPoint (ProxyNode -- think loops)
+     *</p>
+     */
+    // @formatter:on
+    private ValueNode downcastedValueProxy(ValueProxy proxy, Witness w) {
+        assert FlowUtil.hasLegalObjectStamp((ValueNode) proxy);
+        assert FlowUtil.hasLegalObjectStamp((proxy).getOriginalNode());
+        assert GraphUtil.unproxify((ValueNode) proxy) == GraphUtil.unproxify(proxy.getOriginalNode());
+
+        assert GraphUtil.unproxify((ValueNode) proxy) == GraphUtil.unproxify((proxy).getOriginalNode());
+
+        if (proxy instanceof PiNode) {
+            return downcastedPiNodeOrPiArrayNode((PiNode) proxy, w);
+        } else if (proxy instanceof GuardingPiNode) {
+            return downcastedGuardingPiNode((GuardingPiNode) proxy, w);
+        } else if (proxy instanceof TypeProfileProxyNode) {
+            return downcastedTypeProfileProxyNode((TypeProfileProxyNode) proxy);
+        } else if (proxy instanceof CheckCastNode) {
+            return downcastedCheckCastNode((CheckCastNode) proxy, w);
+        } else if (proxy instanceof ProxyNode || proxy instanceof GuardedValueNode) {
+            // TODO scaladacapo return downcastedUtil((ValueNode) proxy, w);
+            return (ValueNode) proxy;
+        }
+
+        assert false : "TODO case not yet handled";
+
+        // TODO complete the missing implementation for the cases not yet handled
+
+        return ((ValueNode) proxy);
+    }
+
+    /**
+     * <p>
+     * Why would we want to downcast a GuardingPiNode? Is it even possible? Like, for example, a
+     * GuardingPiNode originating in the lowering of a CheckCastNode (carried out by
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
+     * visitCheckCastNode()}).
+     * </p>
+     *
+     * <p>
+     * It's both possible and desirable. Example: <code>
+     *         Number n = (Number) o;
+     *         if (n instanceof Integer) {
+     *            return n.intValue();
+     *         }
+     *     </code>
+     *
+     * The receiver of intValue() is a usage of a previous checkCast, for which the current witness
+     * provides a more refined type (and an anchor). In this case, the advantage of downcasting a
+     * GuardingPiNode is clear: devirtualizing the `intValue()` callsite.
+     * </p>
+     *
+     * @see #downcastedValueProxy
+     * */
+    public ValueNode downcastedGuardingPiNode(GuardingPiNode envelope, Witness w) {
+        assert envelope != w.guard().asNode() : "The stamp of " + envelope + " would lead to downcasting with that very same GuardingPiNode as guard.";
+        return downcastedUtil(envelope, w);
+    }
+
+    /**
+     * <p>
+     * This method accepts both {@link com.oracle.graal.nodes.PiNode} and
+     * {@link com.oracle.graal.nodes.PiArrayNode} argument.
+     * </p>
+     *
+     * <p>
+     * In case a witness reveals a strictly more precise type than the
+     * {@link com.oracle.graal.nodes.PiNode}'s stamp, this method wraps the argument in a new
+     * {@link com.oracle.graal.nodes.PiNode} with updated stamp, and returns it.
+     * </p>
+     *
+     * <p>
+     * A {@link com.oracle.graal.nodes.PiArrayNode} argument ends up wrapped in a
+     * {@link com.oracle.graal.nodes.PiNode}. Thus, the
+     * {@link com.oracle.graal.nodes.PiArrayNode#length} information doesn't get lost.
+     * </p>
+     *
+     * <p>
+     * Note: {@link com.oracle.graal.nodes.PiNode}'s semantics allow un-packing its payload as soon
+     * as it type conforms to that of the {@link com.oracle.graal.nodes.PiNode} (that's what
+     * {@link com.oracle.graal.nodes.PiNode#canonical(com.oracle.graal.graph.spi.CanonicalizerTool)
+     * PiNode.canonical()} does). Not clear the benefits of duplicating that logic here.
+     * </p>
+     *
+     * @see #downcastedValueProxy
+     * */
+    private ValueNode downcastedPiNodeOrPiArrayNode(PiNode envelope, Witness w) {
+        return downcastedUtil(envelope, w);
+    }
+
+    /**
+     * <p>
+     * In a case the payload of the {@link com.oracle.graal.nodes.TypeProfileProxyNode} can be
+     * downcasted, this method returns a copy-on-write version with the downcasted payload.
+     * </p>
+     *
+     * <p>
+     * Otherwise returns the unmodified argument.
+     * </p>
+     *
+     * @see #downcastedValueProxy
+     * */
+    private ValueNode downcastedTypeProfileProxyNode(TypeProfileProxyNode envelope) {
+        ValueNode payload = envelope.getOriginalNode();
+        ValueNode d = downcasted(payload);
+        if (payload != d) {
+            TypeProfileProxyNode changed = (TypeProfileProxyNode) envelope.copyWithInputs();
+            added.add(changed);
+            // copyWithInputs() implies graph.unique(changed)
+            FlowUtil.replaceInPlace(changed, payload, d);
+            FlowUtil.inferStampAndCheck(changed);
+            fixupTypeProfileStamp(changed);
+            /*
+             * It's not prudent to (1) obtain the canonical() of the (changed) TypeProfileProxyNode
+             * to (2) replace its usages; because we're potentially walking a DAG (after all,
+             * TypeProfileProxyNode is a floating-node). Those steps, which admittedly are needed,
+             * are better performed upon replacing in-place the inputs of a FixedNode, or during
+             * Canonicalize.
+             */
+            return changed;
+        }
+        fixupTypeProfileStamp(envelope);
+        return envelope;
+    }
+
+    /**
+     * <p>
+     * Re-wrap the checkCast in a type-refining {@link com.oracle.graal.nodes.PiNode PiNode} only if
+     * the downcasted scrutinee does not conform to the checkCast's target-type.
+     * </p>
+     * */
+    private ValueNode downcastedCheckCastNode(CheckCastNode checkCast, Witness w) {
+
+        final ResolvedJavaType toType = checkCast.type();
+
+        if (checkCast.object() instanceof CheckCastNode) {
+            ValueNode innerMost = checkCast;
+            while (innerMost instanceof CheckCastNode) {
+                innerMost = ((CheckCastNode) innerMost).object();
+            }
+            ValueNode deepest = downcasted(innerMost);
+            ResolvedJavaType deepestType = ((ObjectStamp) deepest.stamp()).type();
+            if ((deepestType != null && deepestType.equals(toType)) || FlowUtil.isMorePrecise(deepestType, toType)) {
+                assert !w.knowsBetterThan(deepest);
+                return deepest;
+            }
+        }
+
+        ValueNode subject = downcasted(checkCast.object());
+        ObjectStamp subjectStamp = (ObjectStamp) subject.stamp();
+        ResolvedJavaType subjectType = subjectStamp.type();
+
+        if (subjectType != null && toType.isAssignableFrom(subjectType)) {
+            assert !w.knowsBetterThan(subject);
+            return subject;
+        }
+
+        return downcastedUtil(checkCast, w);
+    }
+
+    /**
+     * <p>
+     * Porcelain method.
+     * </p>
+     *
+     * <p>
+     * This method wraps the argument in a new {@link com.oracle.graal.nodes.PiNode PiNode} (created
+     * to hold an updated stamp) provided the argument's stamp can be strictly refined, and returns
+     * it.
+     * </p>
+     * */
+    private ValueNode downcastedUtil(ValueNode subject, Witness w) {
+
+        ObjectStamp originalStamp = (ObjectStamp) subject.stamp();
+        ObjectStamp outgoingStamp = originalStamp;
+
+        if (w.isNonNull() && !outgoingStamp.nonNull()) {
+            outgoingStamp = FlowUtil.asNonNullStamp(outgoingStamp);
+        }
+        if (FlowUtil.isMorePrecise(w.type(), outgoingStamp.type())) {
+            outgoingStamp = FlowUtil.asRefinedStamp(outgoingStamp, w.type());
+        }
+
+        if (outgoingStamp != originalStamp) {
+            assert FlowUtil.isMorePrecise(outgoingStamp, originalStamp);
+
+            boolean isWitnessGuardAnAliasForScrutinee = false;
+            if (w.guard() instanceof GuardingPiNode || w.guard() instanceof PiNode) {
+                /*
+                 * The guard offered by the witness canonicalizes into its subject (a possibly
+                 * type-refined scrutinee) provided its subject conforms as per stamp.
+                 */
+                if (w.guard().asNode().stamp().equals(outgoingStamp)) {
+                    isWitnessGuardAnAliasForScrutinee = true;
+                }
+            }
+
+            ValueNode result;
+            if (isWitnessGuardAnAliasForScrutinee) {
+                result = w.guard().asNode();
+                assert !w.knowsBetterThan(result);
+                return result; // TODO this works. explain why.
+            } else {
+                result = wrapInPiNode(subject, w.guard(), outgoingStamp, true);
+                assert !w.knowsBetterThan(result);
+                return result;
+            }
+
+        } else {
+            assert !w.knowsBetterThan(subject);
+            return subject;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,218 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.IsNullNode;
+import com.oracle.graal.nodes.extended.GuardingNode;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.tiers.PhaseContext;
+
+/**
+ * <p>
+ * This class implements control-flow sensitive reductions for
+ * {@link com.oracle.graal.nodes.FixedGuardNode}.
+ * </p>
+ * 
+ * @see #visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)
+ * */
+public abstract class FixedGuardReduction extends CheckCastReduction {
+
+    public FixedGuardReduction(FixedNode start, State initialState, PhaseContext context) {
+        super(start, initialState, context);
+    }
+
+    /**
+     * In case the condition is constant,
+     * {@link com.oracle.graal.nodes.FixedGuardNode#simplify(com.oracle.graal.graph.spi.SimplifierTool)
+     * FixedGuardNode#simplify(SimplifierTool)} will eventually remove the
+     * {@link com.oracle.graal.nodes.FixedGuardNode} ("always succeeds") or kill the code that
+     * should be killed ("always fails").
+     * 
+     * <p>
+     * The only thing we do here is tracking as true fact (from this program point onwards) the
+     * condition of the {@link com.oracle.graal.nodes.FixedGuardNode FixedGuardNode}.
+     * </p>
+     * 
+     * <p>
+     * Precondition: the condition hasn't been deverbosified yet.
+     * </p>
+     */
+    protected final void visitFixedGuardNode(FixedGuardNode f) {
+
+        /*
+         * A FixedGuardNode with LogicConstantNode condition is left untouched.
+         */
+
+        if (f.condition() instanceof LogicConstantNode) {
+            if (FlowUtil.alwaysFails(f.isNegated(), f.condition())) {
+                state.impossiblePath();
+                // let FixedGuardNode(false).simplify() prune the dead-code control-path
+                return;
+            }
+            assert FlowUtil.alwaysSucceeds(f.isNegated(), f.condition());
+            return;
+        }
+
+        /*
+         * Attempt to eliminate the current FixedGuardNode by using another GuardingNode already in
+         * scope and with equivalent condition.
+         */
+
+        GuardingNode existingGuard = f.isNegated() ? state.falseFacts.get(f.condition()) : state.trueFacts.get(f.condition());
+        if (existingGuard != null) {
+            // assert existingGuard instanceof FixedGuardNode;
+            metricFixedGuardNodeRemoved.increment();
+            f.replaceAtUsages(existingGuard.asNode());
+            graph.removeFixed(f);
+            return;
+        }
+
+        final LogicNode cond = f.condition();
+        final boolean isTrue = !f.isNegated();
+
+        /*
+         * FixedGuardNode requires handling similar to that of GuardingPiNode, (ie the condition
+         * can't simply be deverbosified in place). A replacement anchor is needed, ie an anchor
+         * that amounts to the same combination of (negated, condition) for the FixedGuardNode at
+         * hand.
+         */
+
+        // TODO what about isDependencyTainted
+
+        if (cond instanceof IsNullNode) {
+            final IsNullNode isNullNode = (IsNullNode) cond;
+            if (isTrue) {
+                // grab an anchor attesting nullness
+                final GuardingNode replacement = reasoner.untrivialNullAnchor(isNullNode.object());
+                if (replacement != null) {
+                    removeFixedGuardNode(f, replacement);
+                    return;
+                }
+                if (state.isNonNull(isNullNode.object())) {
+                    markFixedGuardNodeAlwaysFails(f);
+                    return;
+                }
+                // can't produce evidence, fall-through to addFact
+            } else {
+                // grab an anchor attesting non-nullness
+                final Witness w = state.typeInfo(isNullNode.object());
+                if (w != null && w.isNonNull()) {
+                    removeFixedGuardNode(f, w.guard());
+                    return;
+                }
+                if (state.isNull(isNullNode.object())) {
+                    markFixedGuardNodeAlwaysFails(f);
+                    return;
+                }
+                // can't produce evidence, fall-through to addFact
+            }
+        } else if (cond instanceof InstanceOfNode) {
+            final InstanceOfNode iOf = (InstanceOfNode) cond;
+            final Witness w = state.typeInfo(iOf.object());
+            if (isTrue) {
+                // grab an anchor attesting instanceof
+                if (w != null) {
+                    if (w.isNonNull() && w.type() != null) {
+                        if (iOf.type().isAssignableFrom(w.type())) {
+                            removeFixedGuardNode(f, w.guard());
+                            return;
+                        }
+                        if (State.knownNotToConform(w.type(), iOf.type())) {
+                            markFixedGuardNodeAlwaysFails(f);
+                            return;
+                        }
+                    }
+                }
+                if (state.isNull(iOf.object())) {
+                    markFixedGuardNodeAlwaysFails(f);
+                    return;
+                }
+                // can't produce evidence, fall-through to addFact
+            } else {
+                // grab an anchor attesting not-instanceof
+                // (1 of 2) attempt determining nullness
+                final GuardingNode nullGuard = reasoner.untrivialNullAnchor(iOf.object());
+                if (nullGuard != null) {
+                    removeFixedGuardNode(f, nullGuard);
+                    return;
+                }
+                // (2 of 2) attempt determining known-not-to-conform
+                if (w != null && !w.cluelessAboutType()) {
+                    if (State.knownNotToConform(w.type(), iOf.type())) {
+                        removeFixedGuardNode(f, w.guard());
+                        return;
+                    }
+                }
+                // can't produce evidence, fall-through to addFact
+            }
+        } else if (isTrue && cond instanceof ShortCircuitOrNode) {
+            CastCheckExtractor cce = CastCheckExtractor.extract(cond);
+            if (cce != null && !State.isDependencyTainted(cce.subject, f)) {
+                // grab an anchor attesting check-cast
+                Witness w = state.typeInfo(cce.subject);
+                if (w != null && w.type() != null) {
+                    if (cce.type.isAssignableFrom(w.type())) {
+                        removeFixedGuardNode(f, w.guard());
+                        return;
+                    }
+                    if (State.knownNotToConform(w.type(), cce.type)) {
+                        markFixedGuardNodeAlwaysFails(f);
+                        return;
+                    }
+                }
+            }
+            // can't produce evidence, fall-through to addFact
+        }
+
+        state.addFact(isTrue, cond, f);
+    }
+
+    /**
+     * Porcelain method.
+     * */
+    private void markFixedGuardNodeAlwaysFails(FixedGuardNode f) {
+        metricFixedGuardNodeRemoved.increment();
+        state.impossiblePath();
+        f.setCondition(f.isNegated() ? trueConstant : falseConstant);
+        // `f.condition()` if unused will be removed in finished()
+    }
+
+    /**
+     * Porcelain method.
+     * 
+     * <p>
+     * The `replacement` guard must be such that it implies the `old` guard.
+     * </p>
+     * */
+    private void removeFixedGuardNode(FixedGuardNode old, GuardingNode replacement) {
+        if (replacement == null) {
+            return;
+        }
+        metricFixedGuardNodeRemoved.increment();
+        old.replaceAtUsages(replacement.asNode());
+        graph.removeFixed(old);
+        // `old.condition()` if unused will be removed in finished()
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,545 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Node;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.FloatingNode;
+import com.oracle.graal.nodes.extended.LoadHubNode;
+import com.oracle.graal.nodes.extended.NullCheckNode;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.compiler.common.type.IllegalStamp;
+import com.oracle.graal.nodes.type.StampTool;
+import com.oracle.graal.nodes.util.GraphUtil;
+import com.oracle.graal.phases.common.DeadCodeEliminationPhase;
+import com.oracle.graal.phases.tiers.PhaseContext;
+
+import java.lang.reflect.Modifier;
+
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+
+/**
+ * <p>
+ * All control-flow-sensitive reductions follow the common pattern of
+ * <ul>
+ * <li>Recognizing properties of interest (ie, LogicNode-s) at control-flow splits, as well as upon
+ * check-casts and fixed-guards.</li>
+ * <li>Using the information thus tracked to simplify
+ * <ul>
+ * <li>side-effects free expressions, via
+ * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)}
+ * </li>
+ * <li>control-flow, eg. by eliminating redundant fixed-guards and check-casts, ie which are known
+ * always to hold.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see com.oracle.graal.phases.common.cfs.CheckCastReduction
+ * @see com.oracle.graal.phases.common.cfs.GuardingPiReduction
+ * @see com.oracle.graal.phases.common.cfs.FixedGuardReduction
+ *
+ * */
+public class FlowSensitiveReduction extends FixedGuardReduction {
+
+    public FlowSensitiveReduction(FixedNode start, State initialState, PhaseContext context) {
+        super(start, initialState, context);
+    }
+
+    /**
+     * <p>
+     * This method performs two kinds of cleanup:
+     * <ol>
+     * <li>
+     * marking as unreachable certain code-paths, as described in
+     * {@link com.oracle.graal.phases.common.cfs.BaseReduction.PostponedDeopt}</li>
+     * <li>
+     * Removing nodes not in use that were added during this phase, as described next.</li>
+     * </ol>
+     * </p>
+     *
+     *
+     * <p>
+     * Methods like
+     * {@link com.oracle.graal.phases.common.cfs.FlowUtil#replaceInPlace(com.oracle.graal.graph.Node, com.oracle.graal.graph.Node, com.oracle.graal.graph.Node)}
+     * may result in old inputs becoming disconnected from the graph. It's not advisable to
+     * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} at
+     * that moment, because one of the inputs that might get killed is one of {@link #nullConstant},
+     * {@link #falseConstant}, or {@link #trueConstant}; which thus could get killed too early,
+     * before another invocation of
+     * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)}
+     * needs them. To recap,
+     * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} also
+     * recursively visits the inputs of the its argument.
+     * </p>
+     *
+     * <p>
+     * This method goes over all of the nodes that deverbosification might have added, which are
+     * either:
+     * <ul>
+     * <li>
+     * {@link com.oracle.graal.nodes.calc.FloatingNode}, added by
+     * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosifyFloatingNode(com.oracle.graal.nodes.calc.FloatingNode)}
+     * ; or</li>
+     * <li>
+     * {@link com.oracle.graal.nodes.java.MethodCallTargetNode}, added by
+     * {@link #deverbosifyInputsCopyOnWrite(com.oracle.graal.nodes.java.MethodCallTargetNode)}</li>
+     * </ul>
+     *
+     * Checking if they aren't in use, proceeding to remove them in that case.
+     * </p>
+     *
+     * */
+    @Override
+    public void finished() {
+        if (!postponedDeopts.isEmpty()) {
+            for (PostponedDeopt postponed : postponedDeopts) {
+                postponed.doRewrite(falseConstant);
+            }
+            new DeadCodeEliminationPhase().apply(graph);
+        }
+        for (MethodCallTargetNode mcn : graph.getNodes().filter(MethodCallTargetNode.class)) {
+            if (mcn.isAlive() && FlowUtil.lacksUsages(mcn)) {
+                mcn.safeDelete();
+            }
+        }
+        for (Node n : graph.getNodes().filter(FloatingNode.class)) {
+            GraphUtil.tryKillUnused(n);
+        }
+        assert !isAliveWithoutUsages(trueConstant);
+        assert !isAliveWithoutUsages(falseConstant);
+        assert !isAliveWithoutUsages(nullConstant);
+    }
+
+    private static boolean isAliveWithoutUsages(FloatingNode node) {
+        return node.isAlive() && node.usages().isEmpty();
+    }
+
+    private void registerControlSplit(Node pred, BeginNode begin) {
+        assert pred != null && begin != null;
+        assert !state.isUnreachable;
+
+        if (begin instanceof LoopExitNode) {
+            state.clear();
+        }
+
+        if (pred instanceof IfNode) {
+            registerIfNode((IfNode) pred, begin);
+        } else if (pred instanceof TypeSwitchNode) {
+            registerTypeSwitchNode((TypeSwitchNode) pred, begin);
+        }
+    }
+
+    private void registerIfNode(IfNode ifNode, BeginNode begin) {
+        final boolean isThenBranch = (begin == ifNode.trueSuccessor());
+
+        if (ifNode.condition() instanceof LogicConstantNode) {
+            final LogicConstantNode constCond = (LogicConstantNode) ifNode.condition();
+            if (isThenBranch != constCond.getValue()) {
+                state.impossiblePath();
+                // let IfNode(constant) prune the dead-code control-path
+            }
+        }
+
+        if (state.isUnreachable) {
+            if (!(ifNode.condition() instanceof LogicConstantNode)) {
+                // if condition constant, no need to add a Deopt node
+                postponedDeopts.addDeoptAfter(begin, UnreachedCode);
+            }
+        } else {
+            state.addFact(isThenBranch, ifNode.condition(), begin);
+        }
+    }
+
+    /**
+     * TODO When tracking integer-stamps, the state at each successor of a TypeSwitchNode should
+     * track an integer-stamp for the LoadHubNode (meet over the constants leading to that
+     * successor). However, are LoadHubNode-s shared frequently enough?
+     * */
+    private void registerTypeSwitchNode(TypeSwitchNode typeSwitch, BeginNode begin) {
+        if (typeSwitch.value() instanceof LoadHubNode) {
+            LoadHubNode loadHub = (LoadHubNode) typeSwitch.value();
+            ResolvedJavaType type = null;
+            for (int i = 0; i < typeSwitch.keyCount(); i++) {
+                if (typeSwitch.keySuccessor(i) == begin) {
+                    if (type == null) {
+                        type = typeSwitch.typeAt(i);
+                    } else {
+                        type = FlowUtil.widen(type, typeSwitch.typeAt(i));
+                    }
+                }
+            }
+            if (type == null) {
+                // `begin` denotes the default case of the TypeSwitchNode
+                return;
+            }
+            // preferable would be trackExact, but not there yet
+            state.addNullness(false, loadHub.object(), begin);
+            if (state.knownNotToConform(loadHub.object(), type)) {
+                postponedDeopts.addDeoptAfter(begin, UnreachedCode);
+                state.impossiblePath();
+                return;
+            }
+            if (type.isInterface()) {
+                state.trackNN(loadHub.object(), begin);
+            } else {
+                state.trackIO(loadHub.object(), type, begin);
+            }
+        }
+    }
+
+    /**
+     *
+     * <p>
+     * Reduce input nodes based on the state at the program point for the argument (ie, based on
+     * "valid facts" only, without relying on any floating-guard-assumption).
+     * </p>
+     *
+     * <p>
+     * For each (direct or indirect) child, a copy-on-write version is made in case any of its
+     * children changed, with the copy accommodating the updated children. If the parent was shared,
+     * copy-on-write prevents the updates from becoming visible to anyone but the invoker of this
+     * method.
+     * </p>
+     *
+     * <p>
+     * <b> Please note the parent node is mutated upon any descendant changing. No copy-on-write is
+     * performed for the parent node itself. </b>
+     * </p>
+     *
+     * <p>
+     * In more detail, for each direct {@link com.oracle.graal.nodes.ValueNode} input of the node at
+     * hand,
+     *
+     * <ol>
+     * <li>
+     * Obtain a lazy-copied version (via spanning tree) of the DAG rooted at the input-usage in
+     * question. Lazy-copying is done by walking a spanning tree of the original DAG, stopping at
+     * non-FloatingNodes but transitively walking FloatingNodes and their inputs. Upon arriving at a
+     * (floating) node N, the state's facts are checked to determine whether a constant C can be
+     * used instead in the resulting lazy-copied DAG. A NodeBitMap is used to realize the spanning
+     * tree.</li>
+     *
+     * <li>
+     * Provided one or more N-to-C node replacements took place, the resulting lazy-copied DAG has a
+     * parent different from the original (ie different object identity) which indicates the
+     * (copied, updated) DAG should replace the original via replaceFirstInput(), and inferStamp()
+     * should be invoked to reflect the updated inputs.</li>
+     *
+     * </ol>
+     * </p>
+     *
+     * @return whether any reduction was performed on the inputs of the arguments.
+     * */
+    public boolean deverbosifyInputsInPlace(ValueNode parent) {
+        boolean changed = false;
+        for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) {
+            assert !(i instanceof GuardNode) : "ConditionalElim shouldn't run in MidTier";
+            ValueNode j = (ValueNode) reasoner.deverbosify(i);
+            if (i != j) {
+                changed = true;
+                FlowUtil.replaceInPlace(parent, i, j);
+            }
+        }
+        if (changed) {
+            FlowUtil.inferStampAndCheck(parent);
+        }
+        return changed;
+    }
+
+    /**
+     * Similar to {@link #deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode)}, except that
+     * not the parent but a fresh clone is updated upon any of its children changing.
+     *
+     * @return the original parent if no updated took place, a copy-on-write version of it
+     *         otherwise.
+     *
+     * */
+    private MethodCallTargetNode deverbosifyInputsCopyOnWrite(MethodCallTargetNode parent) {
+        MethodCallTargetNode changed = null;
+        for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) {
+            Node j = reasoner.deverbosify(i);
+            if (i != j) {
+                assert j != parent;
+                if (changed == null) {
+                    changed = (MethodCallTargetNode) parent.copyWithInputs();
+                    reasoner.added.add(changed);
+                    // copyWithInputs() implies graph.unique(changed)
+                    assert changed.isAlive();
+                    assert FlowUtil.lacksUsages(changed);
+                }
+                FlowUtil.replaceInPlace(changed, i, j);
+            }
+        }
+        if (changed == null) {
+            return parent;
+        }
+        FlowUtil.inferStampAndCheck(changed);
+        /*
+         * No need to rememberSubstitution() because not called from deverbosify(). In detail, it's
+         * only deverbosify() that skips visited nodes (thus we'd better have recorded any
+         * substitutions we want for them). Not this case.
+         */
+        return changed;
+    }
+
+    /**
+     * Precondition: This method assumes that either:
+     *
+     * <ul>
+     * <li>the state has already stabilized (ie no more pending iterations in the "iterative"
+     * dataflow algorithm); or</li>
+     * <li>any rewritings made based on the state in its current form are conservative enough to be
+     * safe.</li>
+     * </ul>
+     *
+     * <p>
+     * The overarching goal is to perform just enough rewriting to trigger other phases (
+     * {@link com.oracle.graal.graph.spi.SimplifierTool SimplifierTool},
+     * {@link com.oracle.graal.phases.common.DeadCodeEliminationPhase DeadCodeEliminationPhase},
+     * etc) to perform the bulk of rewriting, thus lowering the maintenance burden.
+     * </p>
+     *
+     */
+    @Override
+    protected void node(FixedNode node) {
+
+        assert node.isAlive();
+
+        /*-------------------------------------------------------------------------------------
+         * Step 1: Unreachable paths are still visited (PostOrderNodeIterator requires all ends
+         * of a merge to have been visited), but time is saved by neither updating the state nor
+         * rewriting anything while on an an unreachable path.
+         *-------------------------------------------------------------------------------------
+         */
+        if (state.isUnreachable) {
+            return;
+        }
+
+        /*-------------------------------------------------------------------------------------
+         * Step 2: For an AbstractBeginNode, determine whether this path is reachable, register
+         * any associated guards.
+         *-------------------------------------------------------------------------------------
+         */
+        if (node instanceof BeginNode) {
+            BeginNode begin = (BeginNode) node;
+            Node pred = node.predecessor();
+
+            if (pred != null) {
+                registerControlSplit(pred, begin);
+            }
+            return;
+        }
+
+        /*-------------------------------------------------------------------------------------
+         * Step 3: Check whether EquationalReasoner caches should be cleared upon state updates.
+         *-------------------------------------------------------------------------------------
+         */
+        reasoner.updateState(state);
+
+        /*-------------------------------------------------------------------------------------
+         * Step 4: Whatever special-case handling makes sense for the FixedNode at hand before
+         * its inputs are reduced.
+         *-------------------------------------------------------------------------------------
+         */
+
+        if (node instanceof AbstractEndNode) {
+            visitAbstractEndNode((AbstractEndNode) node);
+            return;
+        } else if (node instanceof Invoke) {
+            visitInvoke((Invoke) node);
+            return;
+        } else if (node instanceof CheckCastNode) {
+            // it's important not to call deverbosification for visitCheckCastNode()
+            visitCheckCastNode((CheckCastNode) node);
+            return;
+        } else if (node instanceof GuardingPiNode) {
+            visitGuardingPiNode((GuardingPiNode) node);
+            return;
+        } else if (node instanceof NullCheckNode) {
+            visitNullCheckNode((NullCheckNode) node);
+            return;
+        } else if (node instanceof FixedGuardNode) {
+            visitFixedGuardNode((FixedGuardNode) node);
+            return;
+        } else if (node instanceof ConditionAnchorNode) {
+            // ConditionAnchorNode shouldn't occur during HighTier
+            return;
+        }
+
+        /*-------------------------------------------------------------------------------------
+         * Step 5: After special-case handling, we do our best for those FixedNode-s
+         * where the effort to reduce their inputs might pay off.
+         *
+         * Why is this useful? For example, by the time the AbstractBeginNode for an If-branch
+         * is visited (in general a ControlSplitNode), the If-condition will have gone already
+         * through simplification (and thus potentially have been reduced to a
+         * LogicConstantNode).
+         *-------------------------------------------------------------------------------------
+         */
+        boolean paysOffToReduce = false;
+        if (node instanceof ControlSplitNode) {
+            // desire to simplify control flow
+            paysOffToReduce = true;
+        } else if (node instanceof ReturnNode) {
+            paysOffToReduce = true;
+        } else if (node instanceof AccessFieldNode || node instanceof AccessArrayNode) {
+            // desire to remove null-checks
+            paysOffToReduce = true;
+        }
+
+        // TODO comb the remaining FixedWithNextNode subclasses, pick those with good changes of
+        // paying-off
+
+        // TODO UnsafeLoadNode takes a condition
+
+        if (paysOffToReduce) {
+            deverbosifyInputsInPlace(node);
+        }
+
+        /*---------------------------------------------------------------------------------------
+         * Step 6: Any additional special-case handling, this time after having inputs reduced.
+         * For example, leverage anchors provided by the FixedNode, to add facts to the factbase.
+         *---------------------------------------------------------------------------------------
+         */
+
+        // TODO some nodes are GuardingNodes (eg, FixedAccessNode) we could use them to track state
+        // TODO others are additionally guarded (eg JavaReadNode), thus *their* guards could be
+        // simplified.
+
+    }
+
+    /**
+     * In case the scrutinee:
+     *
+     * <ul>
+     * <li>is known to be null, an unconditional deopt is added.</li>
+     * <li>is known to be non-null, the NullCheckNode is removed.</li>
+     * </ul>
+     *
+     * <p>
+     * Precondition: the input (ie, object) hasn't been deverbosified yet.
+     * </p>
+     * */
+    private void visitNullCheckNode(NullCheckNode ncn) {
+        ValueNode object = ncn.getObject();
+        if (state.isNull(object)) {
+            postponedDeopts.addDeoptBefore(ncn, NullCheckException);
+            state.impossiblePath();
+            return;
+        }
+        if (state.isNonNull(object)) {
+            /*
+             * Redundant NullCheckNode. Unlike GuardingPiNode or FixedGuardNode, NullCheckNode-s
+             * aren't used as GuardingNode-s, thus in this case can be removed without further ado.
+             */
+            assert FlowUtil.lacksUsages(ncn);
+            graph.removeFixed(ncn);
+            return;
+        }
+        // TODO ANCHOR NEEDED: state.trackNN(object, ncn);
+    }
+
+    /**
+     * The {@link com.oracle.graal.nodes.AbstractEndNode} at the end of the current code path
+     * contributes values to {@link com.oracle.graal.nodes.PhiNode}s. Now is a good time to
+     * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)
+     * EquationalReasoner#deverbosify} those values.
+     *
+     * <p>
+     * Precondition: inputs haven't been deverbosified yet.
+     * </p>
+     * */
+    private void visitAbstractEndNode(AbstractEndNode endNode) {
+        MergeNode merge = endNode.merge();
+        for (PhiNode phi : merge.phis()) {
+            if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) {
+                assert phi.verify();
+                int index = merge.phiPredecessorIndex(endNode);
+                ValueNode original = phi.valueAt(index);
+                ValueNode reduced = (ValueNode) reasoner.deverbosify(original);
+                if (reduced != original) {
+                    phi.setValueAt(index, reduced);
+                    // `original` if unused will be removed in finished()
+                }
+            }
+        }
+    }
+
+    /**
+     * One or more arguments at `invoke` may have control-flow sensitive simplifications. In such
+     * case, a new {@link com.oracle.graal.nodes.java.MethodCallTargetNode MethodCallTargetNode} is
+     * prepared just for this callsite, consuming reduced arguments. This proves useful in
+     * connection with inlining, in order to specialize callees on the types of arguments other than
+     * the receiver (examples: multi-methods, the inlining problem, lambdas as arguments).
+     *
+     * <p>
+     * Precondition: inputs haven't been deverbosified yet.
+     * </p>
+     * */
+    private void visitInvoke(Invoke invoke) {
+        if (invoke.asNode().stamp() instanceof IllegalStamp) {
+            return; // just to be safe
+        }
+        boolean isMethodCallTarget = invoke.callTarget() instanceof MethodCallTargetNode;
+        if (!isMethodCallTarget) {
+            return;
+        }
+        FlowUtil.replaceInPlace(invoke.asNode(), invoke.callTarget(), deverbosifyInputsCopyOnWrite((MethodCallTargetNode) invoke.callTarget()));
+        MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
+        if (callTarget.invokeKind() != MethodCallTargetNode.InvokeKind.Interface && callTarget.invokeKind() != MethodCallTargetNode.InvokeKind.Virtual) {
+            return;
+        }
+        ValueNode receiver = callTarget.receiver();
+        if (receiver == null) {
+            return;
+        }
+        if (!FlowUtil.hasLegalObjectStamp(receiver)) {
+            return;
+        }
+        Witness w = state.typeInfo(receiver);
+        ResolvedJavaType type;
+        ResolvedJavaType stampType = StampTool.typeOrNull(receiver);
+        if (w == null || w.cluelessAboutType()) {
+            // can't improve on stamp but wil try to devirtualize anyway
+            type = stampType;
+        } else {
+            type = FlowUtil.tighten(w.type(), stampType);
+        }
+        if (type == null) {
+            return;
+        }
+        ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod());
+        if (method == null) {
+            return;
+        }
+        if (method.canBeStaticallyBound() || Modifier.isFinal(type.getModifiers())) {
+            metricMethodResolved.increment();
+            callTarget.setInvokeKind(MethodCallTargetNode.InvokeKind.Special);
+            callTarget.setTargetMethod(method);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.PhaseContext;
+
+public class FlowSensitiveReductionPhase extends BasePhase<PhaseContext> {
+
+    private final MetaAccessProvider metaAccess;
+
+    public MetaAccessProvider getMetaAccess() {
+        return metaAccess;
+    }
+
+    public FlowSensitiveReductionPhase(MetaAccessProvider metaAccess) {
+        this.metaAccess = metaAccess;
+    }
+
+    @Override
+    protected final void run(StructuredGraph graph, PhaseContext context) {
+        try (Debug.Scope s = Debug.scope("FlowSensitiveReduction")) {
+            new FlowSensitiveReduction(graph.start(), new State(), context).apply();
+        } catch (Throwable e) {
+            throw Debug.handle(e);
+        }
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,317 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.ResolvedJavaType;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.debug.DebugConfig;
+import com.oracle.graal.debug.DebugConfigScope;
+import com.oracle.graal.debug.internal.DebugScope;
+import com.oracle.graal.graph.InputType;
+import com.oracle.graal.graph.Node;
+import com.oracle.graal.graph.NodeClass;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.compiler.common.type.ObjectStamp;
+import com.oracle.graal.compiler.common.type.Stamp;
+import com.oracle.graal.compiler.common.type.StampFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class FlowUtil {
+
+    private FlowUtil() {
+        // no instances of this class
+    }
+
+    public static boolean lacksUsages(Node n) {
+        return n.recordsUsages() && n.usages().isEmpty();
+    }
+
+    public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) {
+        if (a == null || b == null) {
+            return null;
+        } else if (a.equals(b)) {
+            return a;
+        } else {
+            return a.findLeastCommonAncestor(b);
+        }
+    }
+
+    /**
+     * @return whether the first argument is strictly more precise than the second.
+     * */
+    public static boolean isMorePrecise(ResolvedJavaType a, ResolvedJavaType b) {
+        if (a == null) {
+            return false;
+        }
+        if (b == null) {
+            return true;
+        }
+        assert !a.isPrimitive();
+        assert !b.isPrimitive();
+        if (a.equals(b)) {
+            return false;
+        }
+        if (b.isInterface()) {
+            return b.isAssignableFrom(a);
+        }
+        if (a.isInterface()) {
+            return b.isInterface() && b.isAssignableFrom(a);
+        }
+        return b.isAssignableFrom(a);
+    }
+
+    public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) {
+        if (a == null) {
+            assert b == null || !b.isPrimitive();
+            return b;
+        }
+        if (b == null) {
+            assert !a.isPrimitive();
+            return a;
+        }
+        assert !a.isPrimitive();
+        assert !b.isPrimitive();
+        if (a.equals(b)) {
+            return a;
+        }
+        if (isMorePrecise(a, b)) {
+            return a;
+        } else if (isMorePrecise(b, a)) {
+            return b;
+        } else {
+            /*
+             * Not comparable, two cases:
+             * 
+             * Example 1: 'a' standing for j.l.Number and 'b' for j.l.String We return null for lack
+             * of a value representing NullType, the right answer. Same goes when both arguments are
+             * non-comparable interfaces.
+             * 
+             * Example 2: 'a' standing for sun/nio/ch/DirectBuffer (an interface) and b for
+             * java/nio/Buffer (an abstract class). The class always takes precedence.
+             */
+            if (a.isInterface()) {
+                return b.isInterface() ? null : b;
+            }
+            if (b.isInterface()) {
+                return a.isInterface() ? null : a;
+            }
+            return null; // a and b aren't comparable, can't tighten() them
+        }
+    }
+
+    /**
+     *
+     * There are "illegal" stamps that are not of type IllegalStamp.
+     *
+     * For example, there may be an IntegerStamp with upperBound < lowerBound that returns
+     * !isLegal() but we still know it's an integer and thus not of type IllegalStamp.
+     *
+     * An IllegalStamp should never happen. In contrast, !isLegal() values could happen due to dead
+     * code not yet removed, or upon some non-sideeffecting instructions floating out of a dead
+     * branch.
+     * */
+    public static boolean isLegalObjectStamp(Stamp s) {
+        return isObjectStamp(s) && s.isLegal();
+    }
+
+    public static boolean hasLegalObjectStamp(ValueNode v) {
+        return isLegalObjectStamp(v.stamp());
+    }
+
+    public static boolean isObjectStamp(Stamp stamp) {
+        return stamp instanceof ObjectStamp;
+    }
+
+    public static void inferStampAndCheck(ValueNode n) {
+        n.inferStamp();
+        if (n.stamp() instanceof ObjectStamp) {
+            ObjectStamp objectStamp = (ObjectStamp) n.stamp();
+            assert !objectStamp.isExactType() || objectStamp.type() != null;
+        }
+    }
+
+    /**
+     * Compares the arguments along three dimensions (nullness, exactness, and type). For the first
+     * argument to be more precise than the second, it may not score lower in any dimension and must
+     * score higher in at least one dimension.
+     *
+     * When comparing types s and t, sameness counts as 0; while being more precise is awarded with
+     * a score of 1. In all other cases (non-comparable, or supertype) the score is -1.
+     *
+     * @return whether the first argument is strictly more precise than the second.
+     * */
+    public static boolean isMorePrecise(ObjectStamp a, ObjectStamp b) {
+        int d0 = MINUS(a.alwaysNull(), b.alwaysNull());
+        if (d0 == -1) {
+            return false;
+        }
+        int d1 = MINUS(a.nonNull(), b.nonNull());
+        if (d1 == -1) {
+            return false;
+        }
+        int d2 = MINUS(a.isExactType(), b.isExactType());
+        if (d2 == -1) {
+            return false;
+        }
+        int d3;
+        ResolvedJavaType ta = a.type();
+        ResolvedJavaType tb = b.type();
+        if (ta == null) {
+            d3 = (tb == null) ? 0 : -1;
+        } else if (tb == null) {
+            d3 = 1;
+        } else if (isMorePrecise(ta, tb)) {
+            d3 = 1;
+        } else if (ta.equals(tb)) {
+            d3 = 0;
+        } else {
+            d3 = -1;
+        }
+        if (d3 == -1) {
+            return false;
+        }
+        int maxScore = Math.max(Math.max(d0, d1), Math.max(d2, d3));
+        return maxScore > 0;
+    }
+
+    private static int MINUS(boolean a, boolean b) {
+        int aa = a ? 1 : 0;
+        int bb = b ? 1 : 0;
+        return aa - bb;
+    }
+
+    public static LogicConstantNode asLogicConstantNode(LogicNode cond) {
+        return (cond instanceof LogicConstantNode) ? (LogicConstantNode) cond : null;
+    }
+
+    public static boolean isLiteralNode(ValueNode f) {
+        return f instanceof ConstantNode || f instanceof LogicConstantNode;
+    }
+
+    public static boolean isConstantTrue(LogicNode cond) {
+        LogicConstantNode c = asLogicConstantNode(cond);
+        return (c != null) && c.getValue();
+    }
+
+    public static boolean isConstantFalse(LogicNode cond) {
+        LogicConstantNode c = asLogicConstantNode(cond);
+        return (c != null) && !c.getValue();
+    }
+
+    public static boolean alwaysFails(boolean isNegated, LogicNode cond) {
+        LogicConstantNode c = asLogicConstantNode(cond);
+        return (c != null) && (c.getValue() == isNegated);
+    }
+
+    public static boolean alwaysSucceeds(boolean isNegated, LogicNode cond) {
+        LogicConstantNode c = asLogicConstantNode(cond);
+        return (c != null) && (c.getValue() != isNegated);
+    }
+
+    /**
+     * Returns (preserving order) the ValueNodes without duplicates found among the argument's
+     * direct inputs.
+     * */
+    @SuppressWarnings("unchecked")
+    public static List<ValueNode> distinctValueAndConditionInputs(Node n) {
+        ArrayList<ValueNode> result = null;
+        NodeClass.NodeClassIterator iter = n.inputs().iterator();
+        while (iter.hasNext()) {
+            NodeClass.Position pos = iter.nextPosition();
+            InputType inputType = pos.getInputType(n);
+            boolean isReducibleInput = (inputType == InputType.Value || inputType == InputType.Condition);
+            if (isReducibleInput) {
+                ValueNode i = (ValueNode) pos.get(n);
+                if (!isLiteralNode(i)) {
+                    if (result == null) {
+                        result = new ArrayList<>();
+                    }
+                    if (!result.contains(i)) {
+                        result.add(i);
+                    }
+                }
+            }
+        }
+        return result == null ? Collections.EMPTY_LIST : result;
+    }
+
+    public static ObjectStamp asNonNullStamp(ObjectStamp stamp) {
+        ObjectStamp result = (ObjectStamp) stamp.join(StampFactory.objectNonNull());
+        assert result.isLegal();
+        return result;
+    }
+
+    public static ObjectStamp asRefinedStamp(ObjectStamp stamp, ResolvedJavaType joinType) {
+        assert !joinType.isInterface();
+        ObjectStamp result = (ObjectStamp) stamp.join(StampFactory.declared(joinType));
+        assert result.isLegal();
+        return result;
+    }
+
+    /**
+     * Start situation: the parent node has <code>oldInput</code> among its (direct) inputs. After
+     * this method has run, all such occurrences have been replaced with <code>newInput</code>. In
+     * case that makes <code>oldInput</code> disconnected, it is removed from the graph.
+     * */
+    public static void replaceInPlace(Node parent, Node oldInput, Node newInput) {
+        assert parent != null;
+        assert parent.inputs().contains(oldInput);
+        if (oldInput == newInput) {
+            return;
+        }
+        assert oldInput != null && newInput != null;
+        assert !isLiteralNode((ValueNode) oldInput);
+        do {
+            parent.replaceFirstInput(oldInput, newInput);
+        } while (parent.inputs().contains(oldInput));
+        // `oldInput` if unused wil be removed in finished()
+    }
+
+    public static StructuredGraph visualize(StructuredGraph graph, String title) {
+        DebugConfig debugConfig = DebugScope.getConfig();
+        DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, debugConfig.dumpHandlers(), debugConfig.output());
+        try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
+            Debug.dump(graph, title);
+
+            return graph;
+        }
+    }
+
+    public static final String ANSI_RESET = "\u001B[0m";
+    public static final String ANSI_BLACK = "\u001B[30m";
+    public static final String ANSI_RED = "\u001B[31m";
+    public static final String ANSI_GREEN = "\u001B[32m";
+    public static final String ANSI_YELLOW = "\u001B[33m";
+    public static final String ANSI_BLUE = "\u001B[34m";
+    public static final String ANSI_PURPLE = "\u001B[35m";
+    public static final String ANSI_CYAN = "\u001B[36m";
+    public static final String ANSI_WHITE = "\u001B[37m";
+
+    public static void highlightInRed(String msg) {
+        System.out.println(ANSI_RED + msg + ANSI_RESET);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,373 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.IsNullNode;
+import com.oracle.graal.nodes.extended.GuardingNode;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.compiler.common.type.ObjectStamp;
+import com.oracle.graal.nodes.type.StampTool;
+import com.oracle.graal.phases.tiers.PhaseContext;
+
+/**
+ * <p>
+ * This class implements control-flow sensitive reductions for
+ * {@link com.oracle.graal.nodes.GuardingPiNode}.
+ * </p>
+ * 
+ * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)
+ * */
+public abstract class GuardingPiReduction extends BaseReduction {
+
+    public GuardingPiReduction(FixedNode start, State initialState, PhaseContext context) {
+        super(start, initialState, context);
+    }
+
+    /**
+     * <p>
+     * By the time a {@link com.oracle.graal.nodes.GuardingPiNode GuardingPiNode} is visited, the
+     * available type refinements may allow reductions similar to those performed for
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
+     * CheckCastNode}.
+     * </p>
+     * 
+     * <ol>
+     * <li>
+     * If the condition needs no reduction (ie, it's already a
+     * {@link com.oracle.graal.nodes.LogicConstantNode LogicConstantNode}), this method basically
+     * gives up (thus letting other phases take care of it).</li>
+     * <li>
+     * Otherwise, an attempt is made to find a {@link com.oracle.graal.nodes.extended.GuardingNode}
+     * that implies the combination of (negated, condition) of the
+     * {@link com.oracle.graal.nodes.GuardingPiNode} being visited. Details in
+     * {@link #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}. If found, the node
+     * can be removed.</li>
+     * <li>
+     * Otherwise, the node is lowered to a {@link com.oracle.graal.nodes.FixedGuardNode} and its
+     * usages replaced with {@link com.oracle.graal.nodes.PiNode}. Details in
+     * {@link #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}.</li>
+     * </ol>
+     * 
+     * <p>
+     * Precondition: the condition hasn't been deverbosified yet.
+     * </p>
+     * 
+     * */
+    protected final void visitGuardingPiNode(GuardingPiNode envelope) {
+
+        if (!FlowUtil.hasLegalObjectStamp(envelope)) {
+            // this situation exercised by com.oracle.graal.jtt.optimize.NCE_FlowSensitive02
+            return;
+        }
+        if (!FlowUtil.hasLegalObjectStamp(envelope.object())) {
+            return;
+        }
+
+        /*
+         * (1 of 3) Cover the case of GuardingPiNode(LogicConstantNode, ...)
+         */
+
+        if (envelope.condition() instanceof LogicConstantNode) {
+            if (FlowUtil.alwaysFails(envelope.isNegated(), envelope.condition())) {
+                state.impossiblePath();
+                // let GuardingPiNode(false).canonical() prune the dead-code control-path
+                return;
+            }
+            // if not always-fails and condition-constant, then it always-succeeds!
+            assert FlowUtil.alwaysSucceeds(envelope.isNegated(), envelope.condition());
+            // let GuardingPiNode(true).canonical() replaceAtUsages
+            return;
+        }
+
+        /*
+         * The trick used in visitFixedGuardNode to look up an equivalent GuardingNode for the
+         * combination of (negated, condition) at hand doesn't work for GuardingPiNode, because the
+         * condition showing up here (a ShortCircuitOrNode that can be detected by
+         * CastCheckExtractor) doesn't appear as key in trueFacts, falseFacts. Good thing we have
+         * CastCheckExtractor!
+         */
+
+        /*
+         * (2 of 3) Cover the case of the condition known-to-be-false or known-to-be-true, but not
+         * LogicConstantNode.
+         * 
+         * If deverbosify(condition) == falseConstant, it would be safe to set:
+         * `envelope.setCondition(falseConstant)` (only the API won't allow).
+         * 
+         * On the other hand, it's totally unsafe to do something like that for trueConstant. What
+         * we can do about that case is the province of `tryRemoveGuardingPiNode(envelope)`
+         */
+
+        if (tryRemoveGuardingPiNode(envelope)) {
+            return;
+        }
+
+        /*
+         * Experience has shown that an attempt to eliminate the current GuardingPiNode by using a
+         * GuardingNode already in scope and with equivalent condition (grabbed from `trueFacts`
+         * resp. `falseFacts`) proves futile. Therefore we're not even attempting that here.
+         */
+
+        /*
+         * (3 of 3) Neither always-succeeds nor always-fails, ie we don't known. Converting to
+         * FixedGuardNode allows tracking the condition via a GuardingNode, thus potentially
+         * triggering simplifications down the road.
+         */
+        FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated()));
+        graph.addBeforeFixed(envelope, fixedGuard);
+
+        if (!FlowUtil.lacksUsages(envelope)) {
+            // not calling wrapInPiNode() because we don't want to rememberSubstitution()
+            PiNode replacement = graph.unique(new PiNode(envelope.object(), envelope.stamp(), fixedGuard));
+            reasoner.added.add(replacement);
+            // before removing the GuardingPiNode replace its usages
+            envelope.replaceAtUsages(replacement);
+        }
+
+        graph.removeFixed(envelope);
+
+        state.addFact(!fixedGuard.isNegated(), fixedGuard.condition(), fixedGuard);
+
+    }
+
+    /**
+     * <p>
+     * Based on flow-sensitive knowledge, two pre-requisites have to be fulfilled in order to remove
+     * a {@link com.oracle.graal.nodes.GuardingPiNode}:
+     * 
+     * <ul>
+     * <li>the condition must refer only to the payload of the
+     * {@link com.oracle.graal.nodes.GuardingPiNode}</li>
+     * <li>the condition must check properties about which the state tracks not only a true/false
+     * answer, but also an anchor witnessing that fact</li>
+     * <li>the condition may not check anything else beyond what's stated in the items above.</li>
+     * </ul>
+     * </p>
+     * 
+     * <p>
+     * Provided a condition as above can be reduced to a constant (and an anchor obtained in the
+     * process), this method replaces all usages of the
+     * {@link com.oracle.graal.nodes.GuardingPiNode} (necessarily of
+     * {@link com.oracle.graal.graph.InputType#Value}) with a {@link com.oracle.graal.nodes.PiNode}
+     * that wraps the payload and the anchor in question.
+     * </p>
+     * 
+     * <p>
+     * Precondition: the condition hasn't been deverbosified yet.
+     * </p>
+     * 
+     * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)
+     * 
+     * */
+    private boolean tryRemoveGuardingPiNode(GuardingPiNode envelope) {
+
+        LogicNode cond = envelope.condition();
+        ValueNode payload = envelope.object();
+
+        ObjectStamp outgoingStamp = (ObjectStamp) envelope.stamp();
+        ObjectStamp payloadStamp = (ObjectStamp) payload.stamp();
+
+        if (isNullCheckOn(cond, payload)) {
+            if (envelope.isNegated()) {
+                /*
+                 * GuardingPiNode succeeds if payload non-null
+                 */
+                if (!outgoingStamp.equals(FlowUtil.asNonNullStamp(payloadStamp))) {
+                    warnAboutOutOfTheBlueGuardingPiNode(envelope);
+                }
+                return tryRemoveGuardingPiNodeNonNullCond(envelope);
+            } else {
+                /*
+                 * GuardingPiNode succeeds if payload null
+                 */
+                ValueNode replacement = StampTool.isObjectAlwaysNull(payload) ? payload : reasoner.untrivialNull(payload);
+                if (replacement != null) {
+                    // replacement == null means !isKnownNull(payload)
+                    removeGuardingPiNode(envelope, replacement);
+                    return true;
+                }
+                return false;
+            }
+        } else if (CastCheckExtractor.isInstanceOfCheckOn(cond, payload)) {
+            if (envelope.isNegated()) {
+                return false;
+            }
+            /*
+             * GuardingPiNode succeeds if payload instanceof <something>
+             */
+            InstanceOfNode io = (InstanceOfNode) cond;
+            assert io.type() != null;
+            Witness w = state.typeInfo(payload);
+            if (w != null && w.isNonNull() && isEqualOrMorePrecise(w.type(), io.type())) {
+                ValueNode d = reasoner.downcasted(payload);
+                removeGuardingPiNode(envelope, d);
+                return true;
+            }
+            return false;
+        } else if (cond instanceof ShortCircuitOrNode) {
+            if (envelope.isNegated()) {
+                return false;
+            }
+            CastCheckExtractor cce = CastCheckExtractor.extract(cond);
+            if (cce == null || cce.subject != payload) {
+                return false;
+            }
+            /*
+             * GuardingPiNode succeeds if payload check-casts toType
+             */
+            return tryRemoveGuardingPiNodeCheckCastCond(envelope, cce.type);
+        }
+
+        return false;
+    }
+
+    /**
+     * Porcelain method.
+     * 
+     * This method handles the case where the GuardingPiNode succeeds if payload known to be
+     * non-null.
+     * 
+     * @see #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)
+     * */
+    private boolean tryRemoveGuardingPiNodeNonNullCond(GuardingPiNode envelope) {
+
+        ValueNode payload = envelope.object();
+
+        if (state.isNull(payload)) {
+            // the GuardingPiNode fails always
+            postponedDeopts.addDeoptBefore(envelope, envelope.getReason());
+            state.impossiblePath();
+            return true;
+        }
+
+        if (StampTool.isObjectNonNull(payload)) {
+            // payload needs no downcasting, it satisfies as-is the GuardingPiNode's condition.
+            if (precisionLoss(envelope, payload)) {
+                /*
+                 * TODO The GuardingPiNode has an outgoing stamp whose narrowing goes beyond what
+                 * the condition checks. That's suspicious.
+                 */
+                PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp()));
+                reasoner.added.add(replacement);
+                removeGuardingPiNode(envelope, replacement);
+                return true;
+            } else {
+                removeGuardingPiNode(envelope, payload);
+                return true;
+            }
+        }
+        // if a non-null witness available, the GuardingPiNode can be removed
+
+        Witness w = state.typeInfo(payload);
+        GuardingNode nonNullAnchor = (w != null && w.isNonNull()) ? w.guard() : null;
+        if (nonNullAnchor != null) {
+            PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp(), nonNullAnchor.asNode()));
+            reasoner.added.add(replacement);
+            removeGuardingPiNode(envelope, replacement);
+            return true;
+        }
+
+        /*
+         * TODO What about, nodes that always denote non-null values? (Even though their stamp
+         * forgot to make that clear) Candidates: ObjectGetClassNode, Parameter(0) on instance
+         */
+
+        return false;
+    }
+
+    /**
+     * Porcelain method.
+     * 
+     * This method handles the case where the GuardingPiNode succeeds if payload null or its actual
+     * type equal or subtype of `toType`
+     * 
+     * @see #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)
+     * 
+     * */
+    private boolean tryRemoveGuardingPiNodeCheckCastCond(GuardingPiNode envelope, ResolvedJavaType toType) {
+        assert toType != null;
+        ValueNode payload = envelope.object();
+
+        ObjectStamp outgoingStamp = (ObjectStamp) envelope.stamp();
+        ObjectStamp payloadStamp = (ObjectStamp) payload.stamp();
+
+        if (!outgoingStamp.equals(FlowUtil.asRefinedStamp(payloadStamp, toType))) {
+            warnAboutOutOfTheBlueGuardingPiNode(envelope);
+        }
+
+        ValueNode d = reasoner.downcasted(payload);
+        if (d == null) {
+            return false;
+        }
+
+        if (StampTool.isObjectAlwaysNull(d)) {
+            removeGuardingPiNode(envelope, d);
+            return true;
+        }
+        ObjectStamp dStamp = (ObjectStamp) d.stamp();
+        if (isEqualOrMorePrecise(dStamp.type(), toType)) {
+            removeGuardingPiNode(envelope, d);
+            return true;
+        }
+        return false;
+    }
+
+    /*
+     * TODO There should be an assert in GuardingPiNode to detect that as soon as it happens
+     * (constructor, setStamp).
+     */
+    private static void warnAboutOutOfTheBlueGuardingPiNode(GuardingPiNode envelope) {
+        Debug.log(String.format("GuardingPiNode has an outgoing stamp whose narrowing goes beyond what its condition checks: %s", envelope));
+    }
+
+    private static boolean isNullCheckOn(LogicNode cond, ValueNode subject) {
+        if (!(cond instanceof IsNullNode)) {
+            return false;
+        }
+        IsNullNode isNull = (IsNullNode) cond;
+        return isNull.object() == subject;
+    }
+
+    /**
+     * Porcelain method.
+     * */
+    private void removeGuardingPiNode(GuardingPiNode envelope, ValueNode replacement) {
+        assert !precisionLoss(envelope, replacement);
+        metricGuardingPiNodeRemoved.increment();
+        envelope.replaceAtUsages(replacement);
+        assert FlowUtil.lacksUsages(envelope);
+        graph.removeFixed(envelope);
+    }
+
+    public static boolean isEqualOrMorePrecise(ResolvedJavaType a, ResolvedJavaType b) {
+        return a.equals(b) || FlowUtil.isMorePrecise(a, b);
+    }
+
+    public static boolean isEqualOrMorePrecise(ObjectStamp a, ObjectStamp b) {
+        return a.equals(b) || FlowUtil.isMorePrecise(a, b);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,70 @@
+/*
+ * 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.phases.common.cfs;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+public class Histogram extends TreeMap<Integer, Integer> {
+
+    private static final long serialVersionUID = 7188324319057387738L;
+
+    private final String prefix;
+
+    public Histogram(String prefix) {
+        this.prefix = prefix;
+    }
+
+    public void tick(int bucket) {
+        Integer entry = get(bucket);
+        put(bucket, entry == null ? 1 : entry + 1);
+    }
+
+    public void print() {
+
+        // printing takes time, allow concurrent updates during printing
+        Histogram histogram = clone();
+
+        float casesTotal = 0;
+        for (int i : histogram.values()) {
+            casesTotal += i;
+        }
+        for (Map.Entry<Integer, Integer> entry : histogram.entrySet()) {
+            int numCases = entry.getValue();
+            int percentOut = (int) (numCases / casesTotal * 100);
+            String msg = prefix + String.format("%d iters in %4d cases (%2d %%)", entry.getKey(), numCases, percentOut);
+            if (entry.getKey() > 3) {
+                FlowUtil.highlightInRed(msg);
+            } else {
+                System.out.println(msg);
+            }
+        }
+        System.out.println(prefix + "--------------------------");
+    }
+
+    @Override
+    public Histogram clone() {
+        return (Histogram) super.clone();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,90 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.CanonicalizerPhase;
+import com.oracle.graal.phases.common.util.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class IterativeFlowSensitiveReductionPhase extends BasePhase<PhaseContext> {
+
+    private static final int MAX_ITERATIONS = 256;
+
+    private final CanonicalizerPhase canonicalizer;
+
+    public IterativeFlowSensitiveReductionPhase(CanonicalizerPhase canonicalizer) {
+        this.canonicalizer = canonicalizer;
+    }
+
+    public static class CountingListener extends HashSetNodeChangeListener {
+
+        public int count;
+
+        @Override
+        public void nodeChanged(Node node) {
+            super.nodeChanged(node);
+        }
+
+    }
+
+    // private Histogram histogram = new Histogram("FSR-");
+
+    @Override
+    protected void run(StructuredGraph graph, PhaseContext context) {
+        FlowSensitiveReductionPhase eliminate = new FlowSensitiveReductionPhase(context.getMetaAccess());
+        CountingListener listener = new CountingListener();
+        int count = 1;
+        while (true) {
+            listener.count = count;
+            graph.trackInputChange(listener);
+            graph.trackUsagesDroppedZero(listener);
+            eliminate.apply(graph, context);
+            graph.stopTrackingInputChange();
+            graph.stopTrackingUsagesDroppedZero();
+            if (listener.getChangedNodes().isEmpty()) {
+                // histogram.tick(count);
+                break;
+            }
+            for (Node node : graph.getNodes()) {
+                if (node instanceof Simplifiable) {
+                    listener.getChangedNodes().add(node);
+                }
+            }
+            canonicalizer.applyIncremental(graph, context, listener.getChangedNodes());
+            listener.getChangedNodes().clear();
+            if (++count > MAX_ITERATIONS) {
+                // System.out.println("Bailing out IterativeFlowSensitiveReductionPhase for graph: "
+                // + graph);
+                // FlowUtil.visualize(graph, "Bailout");
+                throw new BailoutException("Number of iterations in FlowSensitiveReductionPhase exceeds " + MAX_ITERATIONS);
+            }
+        }
+        // histogram.print();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,813 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.api.meta.ResolvedJavaType;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.debug.DebugMetric;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.IsNullNode;
+import com.oracle.graal.nodes.calc.ObjectEqualsNode;
+import com.oracle.graal.nodes.extended.GuardedNode;
+import com.oracle.graal.nodes.extended.GuardingNode;
+import com.oracle.graal.nodes.java.InstanceOfNode;
+import com.oracle.graal.nodes.spi.ValueProxy;
+import com.oracle.graal.compiler.common.type.ObjectStamp;
+import com.oracle.graal.nodes.type.StampTool;
+import com.oracle.graal.nodes.util.GraphUtil;
+import com.oracle.graal.phases.graph.MergeableState;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+/**
+ * A State instance is mutated in place as each FixedNode is visited in a basic block of
+ * instructions. Basic block: starts with a {@link com.oracle.graal.nodes.BeginNode BeginNode}, ends
+ * at an {@link com.oracle.graal.nodes.EndNode EndNode} or
+ * {@link com.oracle.graal.nodes.ControlSinkNode ControlSinkNode} and lacks intervening control
+ * splits or merges.
+ */
+public final class State extends MergeableState<State> implements Cloneable {
+
+    private static final DebugMetric metricTypeRegistered = Debug.metric("TypeRegistered");
+    private static final DebugMetric metricNullnessRegistered = Debug.metric("NullnessRegistered");
+    private static final DebugMetric metricObjectEqualsRegistered = Debug.metric("ObjectEqualsRegistered");
+    private static final DebugMetric metricImpossiblePathDetected = Debug.metric("ImpossiblePathDetected");
+
+    /**
+     * <p>
+     * Each state update results in a higher {@link State#versionNr versionNr}. The
+     * {@link State#versionNr versionNr} of different State instances can't be meaningfully compared
+     * (ie, same {@link State#versionNr versionNr} just indicates they've gone through the same
+     * number of updates). In particular, the {@link State#versionNr versionNr} of a merged state
+     * doesn't guarantee any more than being different from those of the states being merged.
+     * </p>
+     *
+     * <p>
+     * Still, {@link State#versionNr versionNr} proves useful in two cases:
+     *
+     * <ul>
+     * <li>recording the {@link State#versionNr versionNr} right after {@link State State} cloning,
+     * allows finding out afterwards whether (a) both states have diverged, (b) just one of them, or
+     * (c) none of them.</li>
+     * <li>a {@link State State} may become {@link State#isUnreachable isUnreachable}. In such case,
+     * it may make a difference whether any updates were performed on the state from the time it was
+     * cloned. Those updates indicate information not available in the state is was cloned from. For
+     * the purposes of {@link FlowSensitiveReduction FlowSensitiveReduction} an unreachable state
+     * need not be merged with any other (because control-flow won't reach the merge point over the
+     * path of the unreachable state).</li>
+     * </ul>
+     * </p>
+     *
+     * */
+    int versionNr = 0;
+
+    boolean isUnreachable = false;
+
+    /**
+     * Getting here implies an opportunity was detected for dead-code-elimination. A counterpoint
+     * argument goes as follows: perhaps we don't get here that often, in which case the effort to
+     * detect an "impossible path" could be shaved off.
+     *
+     * @see com.oracle.graal.phases.common.cfs.BaseReduction.PostponedDeopt
+     * */
+    void impossiblePath() {
+        isUnreachable = true;
+        metricImpossiblePathDetected.increment();
+    }
+
+    /**
+     * <p>
+     * This map semantically tracks "facts" (ie, properties valid for the program-point the state
+     * refers to) as opposed to floating-guard-dependent properties. The
+     * {@link com.oracle.graal.nodes.extended.GuardingNode} being tracked comes handy at
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)}
+     * .
+     * </p>
+     *
+     * <p>
+     * On a related note, {@link #typeRefinements} also captures information the way
+     * {@link #trueFacts} and {@link #falseFacts} do, including "witnessing" guards. Why not just
+     * standardize on one of them, and drop the other? Because the {@link #typeRefinements} eagerly
+     * aggregates information for easier querying afterwards, e.g. when producing a "downcasted"
+     * value (which involves building a {@link com.oracle.graal.nodes.PiNode}, see
+     * {@link EquationalReasoner#downcasted(com.oracle.graal.nodes.ValueNode) downcasted()}
+     * </p>
+     *
+     * */
+    private IdentityHashMap<ValueNode, Witness> typeRefinements;
+
+    IdentityHashMap<ValueNode, GuardingNode> knownNull;
+    IdentityHashMap<LogicNode, GuardingNode> trueFacts;
+    IdentityHashMap<LogicNode, GuardingNode> falseFacts;
+
+    public State() {
+        this.typeRefinements = new IdentityHashMap<>();
+        this.knownNull = new IdentityHashMap<>();
+        this.trueFacts = new IdentityHashMap<>();
+        this.falseFacts = new IdentityHashMap<>();
+    }
+
+    public State(State other) {
+        this.isUnreachable = other.isUnreachable;
+        this.versionNr = other.versionNr;
+        this.typeRefinements = new IdentityHashMap<>();
+        for (Map.Entry<ValueNode, Witness> entry : other.typeRefinements.entrySet()) {
+            this.typeRefinements.put(entry.getKey(), new Witness(entry.getValue()));
+        }
+        this.knownNull = new IdentityHashMap<>(other.knownNull);
+        this.trueFacts = new IdentityHashMap<>(other.trueFacts);
+        this.falseFacts = new IdentityHashMap<>(other.falseFacts);
+    }
+
+    /**
+     * @return A new list containing only those states that are reachable.
+     * */
+    private static ArrayList<State> reachableStates(List<State> states) {
+        ArrayList<State> result = new ArrayList<>(states);
+        Iterator<State> iter = result.iterator();
+        while (iter.hasNext()) {
+            if (iter.next().isUnreachable) {
+                iter.remove();
+            }
+        }
+        return result;
+    }
+
+    private IdentityHashMap<ValueNode, Witness> mergeKnownTypes(MergeNode merge, ArrayList<State> withReachableStates) {
+        IdentityHashMap<ValueNode, Witness> newKnownTypes = new IdentityHashMap<>();
+
+        for (Map.Entry<ValueNode, Witness> entry : typeRefinements.entrySet()) {
+            ValueNode node = entry.getKey();
+            Witness type = new Witness(entry.getValue());
+
+            for (State other : withReachableStates) {
+                Witness otherType = other.typeInfo(node);
+                if (otherType == null) {
+                    type = null;
+                    break;
+                }
+                type.merge(otherType, merge);
+            }
+            if (type != null && type.knowsBetterThan(node)) {
+                assert node == GraphUtil.unproxify(node);
+                newKnownTypes.put(node, type);
+            }
+        }
+
+        return newKnownTypes;
+    }
+
+    private IdentityHashMap<ValueNode, GuardingNode> mergeKnownNull(MergeNode merge, ArrayList<State> withReachableStates) {
+        // newKnownNull starts empty
+        IdentityHashMap<ValueNode, GuardingNode> newKnownNull = new IdentityHashMap<>();
+        for (Map.Entry<ValueNode, GuardingNode> entry : knownNull.entrySet()) {
+            ValueNode key = entry.getKey();
+            GuardingNode newGN = entry.getValue();
+            boolean missing = false;
+
+            for (State other : withReachableStates) {
+                GuardingNode otherGuard = other.knownNull.get(key);
+                if (otherGuard == null) {
+                    missing = true;
+                    break;
+                }
+                if (otherGuard != newGN) {
+                    newGN = merge;
+                }
+            }
+            if (!missing) {
+                newKnownNull.put(key, newGN);
+            }
+        }
+        return newKnownNull;
+    }
+
+    /**
+     * <p>
+     * This method handles phis, by adding to the resulting state any information that can be gained
+     * (about type-refinement and nullness) based on the data available at each of the incoming
+     * branches.
+     * </p>
+     *
+     * <p>
+     * In more detail, <code>FlowSensitiveReduction#visitAbstractEndNode()</code> has already
+     * deverbosified the phi-values contributed by each reachable branch. The paths that
+     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction} determined to be
+     * unreachable will be eliminated by canonicalization and dead code elimination. For now they
+     * still exist, thus polluting the result of
+     * {@link com.oracle.graal.nodes.ValuePhiNode#inferPhiStamp()} but we are careful to skip them
+     * when merging type-witnesses and known-null maps.
+     * </p>
+     */
+    private void mergePhis(MergeNode merge, List<State> withStates, IdentityHashMap<ValueNode, Witness> newKnownPhiTypes, IdentityHashMap<ValueNode, GuardingNode> newKnownNullPhis) {
+
+        if (merge instanceof LoopBeginNode) {
+            return;
+        }
+
+        for (PhiNode phi : merge.phis()) {
+            assert phi == GraphUtil.unproxify(phi);
+            if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) {
+                ArrayList<ValueNode> reachingValues = new ArrayList<>();
+                if (!isUnreachable) {
+                    reachingValues.add(phi.valueAt(0));
+                }
+                for (int i = 0; i < withStates.size(); i++) {
+                    State otherState = withStates.get(i);
+                    if (!otherState.isUnreachable) {
+                        reachingValues.add(phi.valueAt(i + 1));
+                    }
+                }
+                assert !reachingValues.isEmpty();
+                ObjectStamp phiStamp = (ObjectStamp) phi.stamp();
+                ObjectStamp nonPollutedStamp = (ObjectStamp) StampTool.meet(reachingValues);
+                Witness w = new Witness(nonPollutedStamp, merge);
+                if (FlowUtil.isMorePrecise(w.type(), phiStamp.type())) {
+                    // precision gain regarding type
+                    newKnownPhiTypes.put(phi, w);
+                    // confirm no precision loss regarding nullness
+                    assert implies(phiStamp.nonNull(), w.isNonNull());
+                } else if (w.isNonNull() && !phiStamp.nonNull()) {
+                    // precision gain regarding nullness
+                    newKnownPhiTypes.put(phi, w);
+                    // confirm no precision loss regarding type
+                    assert !FlowUtil.isMorePrecise(phiStamp.type(), w.type());
+                }
+                if (nonPollutedStamp.alwaysNull()) {
+                    newKnownNullPhis.put(phi, merge);
+                }
+            }
+        }
+
+    }
+
+    private static boolean implies(boolean a, boolean b) {
+        return !a || b;
+    }
+
+    @Override
+    public boolean merge(MergeNode merge, List<State> withStates) {
+
+        ArrayList<State> withReachableStates = reachableStates(withStates);
+        if (withReachableStates.isEmpty()) {
+            return true;
+        }
+
+        for (State state : withReachableStates) {
+            versionNr = Math.max(versionNr, state.versionNr) + 1;
+            isUnreachable &= state.isUnreachable;
+        }
+
+        if (isUnreachable) {
+            typeRefinements.clear();
+            knownNull.clear();
+            return true;
+        }
+
+        // may also get updated in a moment, during processing of phi nodes.
+        IdentityHashMap<ValueNode, Witness> newKnownTypes = mergeKnownTypes(merge, withReachableStates);
+        // may also get updated in a moment, during processing of phi nodes.
+        IdentityHashMap<ValueNode, GuardingNode> newKnownNull = mergeKnownNull(merge, withReachableStates);
+        mergePhis(merge, withStates, newKnownTypes, newKnownNull);
+        this.typeRefinements = newKnownTypes;
+        this.knownNull = newKnownNull;
+
+        this.trueFacts = mergeTrueFacts(withReachableStates, merge);
+        this.falseFacts = mergeFalseFacts(withReachableStates, merge);
+        return true;
+    }
+
+    private IdentityHashMap<LogicNode, GuardingNode> mergeTrueFacts(ArrayList<State> withReachableStates, GuardingNode merge) {
+        IdentityHashMap<LogicNode, GuardingNode> newTrueConditions = new IdentityHashMap<>();
+        for (Map.Entry<LogicNode, GuardingNode> entry : trueFacts.entrySet()) {
+            LogicNode check = entry.getKey();
+            GuardingNode guard = entry.getValue();
+
+            for (State other : withReachableStates) {
+                GuardingNode otherGuard = other.trueFacts.get(check);
+                if (otherGuard == null) {
+                    guard = null;
+                    break;
+                }
+                if (otherGuard != guard) {
+                    guard = merge;
+                }
+            }
+            if (guard != null) {
+                newTrueConditions.put(check, guard);
+            }
+        }
+        return newTrueConditions;
+    }
+
+    private IdentityHashMap<LogicNode, GuardingNode> mergeFalseFacts(ArrayList<State> withReachableStates, GuardingNode merge) {
+        IdentityHashMap<LogicNode, GuardingNode> newFalseConditions = new IdentityHashMap<>();
+        for (Map.Entry<LogicNode, GuardingNode> entry : falseFacts.entrySet()) {
+            LogicNode check = entry.getKey();
+            GuardingNode guard = entry.getValue();
+
+            for (State other : withReachableStates) {
+                GuardingNode otherGuard = other.falseFacts.get(check);
+                if (otherGuard == null) {
+                    guard = null;
+                    break;
+                }
+                if (otherGuard != guard) {
+                    guard = merge;
+                }
+            }
+            if (guard != null) {
+                newFalseConditions.put(check, guard);
+            }
+        }
+        return newFalseConditions;
+    }
+
+    /**
+     * @retun null if no type-witness available for the argument, the witness otherwise.
+     */
+    public Witness typeInfo(ValueNode object) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        return typeRefinements.get(GraphUtil.unproxify(object));
+    }
+
+    /**
+     * @retun true iff the argument is known to stand for null.
+     */
+    public boolean isNull(ValueNode object) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        return StampTool.isObjectAlwaysNull(object) || knownNull.containsKey(GraphUtil.unproxify(object));
+    }
+
+    /**
+     * <p>
+     * It makes a difference calling {@link Witness#isNonNull()} as opposed to
+     * {@link State#isNonNull(com.oracle.graal.nodes.ValueNode)}. The former guarantees the witness
+     * provides a guard certifying non-nullness. The latter just tells us there exists some guard
+     * that certifies the property we asked about.
+     * </p>
+     *
+     * <p>
+     * TODO improvement: isKnownNonNull could be made smarter by noticing some nodes always denote a
+     * non-null value (eg, ObjectGetClassNode). Similarly for isKnownNull. Code that looks at the
+     * stamp as well as code that looks for a non-null-witness would benefit from also checking such
+     * extended isKnownNonNull. Alternatively, the stamp of those nodes should always have
+     * is-non-null set.
+     * </p>
+     *
+     * @retun true iff the argument is known to stand for non-null.
+     */
+    public boolean isNonNull(ValueNode object) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        if (StampTool.isObjectNonNull(object)) {
+            return true;
+        }
+        Witness w = typeInfo(object);
+        return w == null ? false : w.isNonNull();
+    }
+
+    /**
+     * @retun true iff the argument is known to stand for an object conforming to the given type.
+     */
+    public boolean knownToConform(ValueNode object, ResolvedJavaType to) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        assert !to.isPrimitive();
+        ResolvedJavaType stampType = StampTool.typeOrNull(object);
+        if (stampType != null && to.isAssignableFrom(stampType)) {
+            return true;
+        }
+        final ValueNode scrutinee = GraphUtil.unproxify(object);
+        if (isNull(scrutinee)) {
+            return true;
+        }
+        Witness w = typeInfo(scrutinee);
+        boolean witnessAnswer = w != null && w.type() != null && to.isAssignableFrom(w.type());
+        if (witnessAnswer) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @retun true iff the argument is known to stand for an object that definitely does not conform
+     *        to the given type.
+     */
+    public boolean knownNotToConform(ValueNode object, ResolvedJavaType to) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        assert !to.isPrimitive();
+        final ValueNode scrutinee = GraphUtil.unproxify(object);
+        if (isNull(scrutinee)) {
+            return false;
+        }
+        ResolvedJavaType stampType = StampTool.typeOrNull(object);
+        if (stampType != null && knownNotToConform(stampType, to)) {
+            return true;
+        }
+        Witness w = typeInfo(scrutinee);
+        boolean witnessAnswer = w != null && !w.cluelessAboutType() && knownNotToConform(w.type(), to);
+        if (witnessAnswer) {
+            return true;
+        }
+        return false;
+    }
+
+    // @formatter:off
+    /**
+     *   \   |     |     |     |
+     *    \ b|     |     |     |
+     *   a \ |     |     |     |
+     *      \|iface|final|non-f|
+     *  -----+-----------------|
+     *  iface|  F  |  F  |  F  |
+     *  -----+-----------------|
+     *  final|  C  |  C  |  C  |
+     *  -----+-----------------|
+     *  non-f|  F  |  C  |  C  |
+     *  -----------------------+
+     *
+     *  where:
+     *    F:     false
+     *    C:     check
+     *    iface: interface
+     *    final: exact non-interface reference-type
+     *    non-f: non-exact non-interface reference-type
+     *
+     * @retun true iff the first argument is known not to conform to the second argument.
+     */
+    // @formatter:on
+    public static boolean knownNotToConform(ResolvedJavaType a, ResolvedJavaType b) {
+        assert !a.isPrimitive();
+        assert !b.isPrimitive();
+        if (b.isAssignableFrom(a)) {
+            return false;
+        }
+        if (a.isInterface()) {
+            return false;
+        }
+        boolean aFinal = Modifier.isFinal(a.getModifiers());
+        if (b.isInterface() && !aFinal) {
+            return false;
+        }
+        if (a.isAssignableFrom(b)) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    @Override
+    public State clone() {
+        return new State(this);
+    }
+
+    /**
+     * Porcelain method.
+     */
+    private Witness getOrElseAddTypeInfo(ValueNode object) {
+        ValueNode scrutinee = GraphUtil.unproxify(object);
+        Witness w = typeRefinements.get(scrutinee);
+        if (w == null) {
+            w = new Witness();
+            typeRefinements.put(scrutinee, w);
+        }
+        return w;
+    }
+
+    /**
+     * <p>
+     * Updates this {@link State State} to account for an observation about the scrutinee being
+     * non-null. In case instanceof was observed,
+     * {@link #trackIO(com.oracle.graal.nodes.ValueNode, com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode)
+     * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead.
+     * </p>
+     *
+     * <p>
+     * No check is made on whether a contradiction would be introduced into the factbase (in which
+     * case the state should be marked unreachable), the caller takes care of that.
+     * </p>
+     *
+     * @return whether state was updated (iff the observation added any new information)
+     */
+    public boolean trackNN(ValueNode object, GuardingNode anchor) {
+        if (isDependencyTainted(object, anchor)) {
+            return false;
+        }
+        ResolvedJavaType stampType = StampTool.typeOrNull(object);
+        if (stampType != null && !stampType.isInterface()) {
+            return trackIO(object, stampType, anchor);
+        }
+        Witness w = getOrElseAddTypeInfo(object);
+        if (w.trackNN(anchor)) {
+            versionNr++;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Updates this {@link State State} to account for an observation about the scrutinee conforming
+     * to a type. In case instanceof was observed,
+     * {@link #trackIO(com.oracle.graal.nodes.ValueNode, com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode)
+     * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead.
+     *
+     * <p>
+     * No check is made on whether a contradiction would be introduced into the factbase (in which
+     * case the state should be marked unreachable), the caller must take care of that.
+     * </p>
+     *
+     * @return false iff the observed type is an interface, or doesn't provide any new information
+     *         not already known. Ie, this method returns true iff the observation resulted in
+     *         information gain.
+     */
+    public boolean trackCC(ValueNode object, ResolvedJavaType observed, GuardingNode anchor) {
+        if (observed.isInterface()) {
+            return false;
+        }
+        if (isDependencyTainted(object, anchor)) {
+            return false;
+        }
+        Witness w = getOrElseAddTypeInfo(object);
+        if (w.trackCC(observed, anchor)) {
+            versionNr++;
+            metricTypeRegistered.increment();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Updates this {@link State State} to account for an observation about the non-null scrutinee
+     * conforming to a type.
+     *
+     * <p>
+     * No check is made on whether a contradiction would be introduced into the factbase (in which
+     * case the state should be marked unreachable), the caller must take care of that.
+     * </p>
+     *
+     * @return whether state was updated (iff the observation added any new information)
+     */
+    public boolean trackIO(ValueNode object, ResolvedJavaType observed, GuardingNode anchor) {
+        assert !observed.isInterface() : "no infrastructure yet in State.Witness to support interfaces in general";
+        if (isDependencyTainted(object, anchor)) {
+            return false;
+        }
+        Witness w = getOrElseAddTypeInfo(object);
+        if (w.trackIO(observed, anchor)) {
+            versionNr++;
+            metricTypeRegistered.increment();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * This method increases {@link #versionNr} (thus potentially invalidating
+     * {@link EquationalReasoner EquationalReasoner}'s caches) only if the fact wasn't known
+     * already.
+     *
+     * <p>
+     * No check is made on whether a contradiction would be introduced into the factbase (in which
+     * case the state should be marked unreachable), the caller must take care of that.
+     * </p>
+     *
+     * */
+    private void addFactPrimordial(LogicNode condition, IdentityHashMap<LogicNode, GuardingNode> to, GuardingNode anchor) {
+        assert condition != null;
+        if (!to.containsKey(condition)) {
+            versionNr++;
+            to.put(condition, anchor);
+        }
+    }
+
+    /**
+     * Ideas for the future:
+     * <ul>
+     * <li>track inferred less-than edges from (accumulated) CompareNode-s</li>
+     * <li>track set-representative for equality classes determined by (chained) IntegerTestNode</li>
+     * </ul>
+     *
+     * */
+    public void addFact(boolean isTrue, LogicNode condition, GuardingNode anchor) {
+        assert anchor != null;
+        assert !isUnreachable;
+
+        if (condition instanceof LogicConstantNode) {
+            if (((LogicConstantNode) condition).getValue() != isTrue) {
+                impossiblePath();
+            }
+            return;
+        }
+
+        if (condition instanceof LogicNegationNode) {
+            addFact(!isTrue, ((LogicNegationNode) condition).getInput(), anchor);
+        } else if (condition instanceof ShortCircuitOrNode) {
+            /*
+             * We can register the conditions being or-ed as long as the anchor is a fixed node,
+             * because floating guards will be registered at a BeginNode but might be "valid" only
+             * later due to data flow dependencies. Therefore, registering both conditions of a
+             * ShortCircuitOrNode for a floating guard could lead to cycles in data flow, because
+             * the guard will be used as anchor for both conditions, and one condition could be
+             * depending on the other.
+             */
+            if (isTrue) {
+                CastCheckExtractor cce = CastCheckExtractor.extract(condition);
+                if (cce == null || isDependencyTainted(cce.subject, anchor)) {
+                    addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor);
+                } else {
+                    trackCC(cce.subject, cce.type, anchor);
+                }
+            } else {
+                ShortCircuitOrNode disjunction = (ShortCircuitOrNode) condition;
+                addFact(disjunction.isXNegated(), disjunction.getX(), anchor);
+                // previous addFact might have resulted in impossiblePath()
+                if (isUnreachable) {
+                    return;
+                }
+                addFact(disjunction.isYNegated(), disjunction.getY(), anchor);
+            }
+        } else if (condition instanceof InstanceOfNode) {
+            addFactInstanceOf(isTrue, (InstanceOfNode) condition, anchor);
+        } else if (condition instanceof IsNullNode) {
+            IsNullNode nullCheck = (IsNullNode) condition;
+            addNullness(isTrue, nullCheck.object(), anchor);
+        } else if (condition instanceof ObjectEqualsNode) {
+            addFactObjectEqualsNode(isTrue, (ObjectEqualsNode) condition, anchor);
+        } else {
+            addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor);
+        }
+    }
+
+    /**
+     * An instanceof hint is tracked differently depending on whether it's an interface-test or not
+     * (because type-refinements currently lacks the ability to track interface types).
+     *
+     */
+    private void addFactInstanceOf(boolean isTrue, InstanceOfNode instanceOf, GuardingNode anchor) {
+        ValueNode object = instanceOf.object();
+        if (isTrue) {
+            if (knownNotToConform(object, instanceOf.type())) {
+                impossiblePath();
+                return;
+            }
+            addNullness(false, object, anchor);
+            if (instanceOf.type().isInterface()) {
+                if (!knownToConform(object, instanceOf.type())) {
+                    addFactPrimordial(instanceOf, trueFacts, anchor);
+                }
+            } else {
+                trackIO(object, instanceOf.type(), anchor);
+            }
+        } else {
+            if (knownToConform(object, instanceOf.type())) {
+                impossiblePath(); // TODO this used to be a bug
+                return;
+            }
+            if (instanceOf.type().isInterface()) {
+                if (!knownNotToConform(object, instanceOf.type())) {
+                    addFactPrimordial(instanceOf, falseFacts, anchor);
+                }
+            }
+        }
+    }
+
+    private void addFactObjectEqualsNode(boolean isTrue, ObjectEqualsNode equals, GuardingNode anchor) {
+        if (isDependencyTainted(equals.x(), anchor)) {
+            return;
+        }
+        if (isDependencyTainted(equals.y(), anchor)) {
+            return;
+        }
+        ValueNode x = GraphUtil.unproxify(equals.x());
+        ValueNode y = GraphUtil.unproxify(equals.y());
+        if (isTrue) {
+            if (isNull(x) && isNonNull(y)) {
+                impossiblePath();
+                return;
+            }
+            if (isNonNull(x) && isNull(y)) {
+                impossiblePath();
+                return;
+            }
+            if (isNull(x) || isNull(y)) {
+                metricObjectEqualsRegistered.increment();
+                addNullness(true, equals.x(), anchor);
+                addNullness(true, equals.y(), anchor);
+            } else if (isNonNull(x) || isNonNull(y)) {
+                metricObjectEqualsRegistered.increment();
+                addNullness(false, equals.x(), anchor);
+                addNullness(false, equals.y(), anchor);
+            }
+            Witness wx = typeInfo(x);
+            Witness wy = typeInfo(y);
+            if (wx == null && wy == null) {
+                return;
+            } else if (wx != null && wy != null) {
+                // tighten their type-hints, provided at least one available
+                // both witnesses may have seen == null, ie they may be NN witnesses
+                ResolvedJavaType best = FlowUtil.tighten(wx.type(), wy.type());
+                if (best != null) {
+                    assert !best.isInterface();
+                    // type tightening is enough, nullness already taken care of
+                    trackCC(equals.x(), best, anchor);
+                    trackCC(equals.y(), best, anchor);
+                }
+            } else if (wx == null) {
+                typeRefinements.put(x, new Witness(wy));
+            } else if (wy == null) {
+                typeRefinements.put(y, new Witness(wx));
+            }
+        } else {
+            if (isNull(x) && !isNonNull(y)) {
+                metricObjectEqualsRegistered.increment();
+                addNullness(false, equals.y(), anchor);
+            } else if (!isNonNull(x) && isNull(y)) {
+                metricObjectEqualsRegistered.increment();
+                addNullness(false, equals.x(), anchor);
+            }
+        }
+    }
+
+    /**
+     * Adds information about the nullness of a value. If isNull is true then the value is known to
+     * be null, otherwise the value is known to be non-null.
+     */
+    public void addNullness(boolean isNull, ValueNode value, GuardingNode anchor) {
+        if (isDependencyTainted(value, anchor)) {
+            return;
+        }
+        ValueNode original = GraphUtil.unproxify(value);
+        boolean wasNull = isNull(original);
+        boolean wasNonNull = isNonNull(original);
+        if (isNull) {
+            if (wasNonNull) {
+                impossiblePath();
+            } else {
+                metricNullnessRegistered.increment();
+                versionNr++;
+                knownNull.put(original, anchor);
+            }
+        } else {
+            if (wasNull) {
+                impossiblePath();
+            } else {
+                metricNullnessRegistered.increment();
+                trackNN(original, anchor);
+            }
+        }
+    }
+
+    /**
+     *
+     * @return true iff `value` may lose dependency not covered by `anchor`.
+     * */
+    public static boolean isDependencyTainted(ValueNode value, GuardingNode anchor) {
+        if (value instanceof ValueProxy) {
+            if (value instanceof GuardedNode) {
+                GuardedNode gn = (GuardedNode) value;
+                GuardingNode guardian = gn.getGuard();
+                if (guardian != null) {
+                    boolean isGuardedByFixed = guardian instanceof FixedNode;
+                    if (!isGuardedByFixed) {
+                        return true;
+                    }
+                }
+            }
+            // if (value instanceof GuardingNode) {
+            // return true;
+            // }
+            ValueProxy proxy = (ValueProxy) value;
+            return isDependencyTainted(proxy.getOriginalNode(), anchor);
+        }
+        return false;
+    }
+
+    public void clear() {
+        versionNr = 0;
+        isUnreachable = false;
+        typeRefinements.clear();
+        knownNull.clear();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Witness.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,440 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.api.meta.ResolvedJavaType;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.GuardingNode;
+import com.oracle.graal.compiler.common.type.ObjectStamp;
+
+/**
+ * <p>
+ * A witness progressively tracks more detailed properties about an object value (the scrutinee);
+ * the properties in question comprise whether the scrutinee has been observed:
+ *
+ * <ul>
+ * <li>as non-null,</li>
+ * <li>in a successful checkcast, or</li>
+ * <li>in a successful instanceof.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * A witness is updated only when doing so increases the information content of the witness. For
+ * example, upon visiting a {@link com.oracle.graal.nodes.java.CheckCastNode CheckCastNode} the
+ * witness gets a chance to become updated.
+ * </p>
+ *
+ * <p>
+ * Therefore, at any given time, a witness represents the most detailed knowledge available so far
+ * about the scrutinee, which is the knowledge most relevant for upcoming program-points.
+ * </p>
+ *
+ * <p>
+ * The availability of witnesses about both non-nullness and checkcast (for a given scrutinee)
+ * promotes to an instanceof-style witness . The "levels" of knowledge a witness may exhibit are
+ * captured by {@link com.oracle.graal.phases.common.cfs.Witness.LEVEL}. For conciseness, the
+ * following query methods are available for a {@link com.oracle.graal.phases.common.cfs.Witness}:
+ * <ul>
+ * <li>{@link #atNonNull()}</li>
+ * <li>{@link #atCheckCast()}</li>
+ * <li>{@link #atInstanceOf()}</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * Only non-interface object types (ie, class and array types) are tracked. Small extensions are
+ * required to track interfaces, extensions that might be added after the current scheme proves
+ * itself.
+ * </p>
+ *
+ * <p>
+ * Some useful facts about the Statechart implemented by {@link Witness Witness}:
+ *
+ * <ul>
+ * <li>the start-state is "clueless"</li>
+ * <li>
+ * A self-transition via trackCC from whichever the current state is to itself, without information
+ * gain, is always possible. Just give {@link Object java.lang.Object} as observed type.</li>
+ * </ul>
+ * </p>
+ *
+ */
+public class Witness implements Cloneable {
+
+    private static enum LEVEL {
+        CLUELESS,
+        NN,
+        CC,
+        IO
+    }
+
+    private boolean atNonNull() {
+        return level == LEVEL.NN;
+    }
+
+    private boolean atCheckCast() {
+        return level == LEVEL.CC;
+    }
+
+    private boolean atInstanceOf() {
+        return level == LEVEL.IO;
+    }
+
+    private void transition(LEVEL to, GuardingNode newAnchor) {
+        this.level = to;
+        this.gn = newAnchor;
+        assert repOK();
+    }
+
+    public Witness() {
+    }
+
+    public Witness(Witness other) {
+        level = other.level;
+        seen = other.seen;
+        gn = other.gn;
+    }
+
+    /**
+     * Counterpart to {@link #asStamp()}
+     * */
+    public Witness(ObjectStamp stamp, GuardingNode anchor) {
+        assert stamp.isLegal();
+        assert anchor != null;
+        boolean isNonIface = (stamp.type() != null && !stamp.type().isInterface());
+        if (stamp.nonNull()) {
+            if (isNonIface) {
+                seen = stamp.type();
+                transition(LEVEL.IO, anchor);
+            } else {
+                seen = null;
+                transition(LEVEL.NN, anchor);
+            }
+        } else {
+            if (isNonIface) {
+                seen = stamp.type();
+                transition(LEVEL.CC, anchor);
+            } else {
+                seen = null;
+                transition(LEVEL.CLUELESS, null);
+                assert clueless();
+            }
+        }
+        assert repOK();
+    }
+
+    /**
+     * Type-witnesses aren't tracked for known-to-be-null. Therefore, although method
+     * {@link #isNonNull() isNonNull()} can be found in this class there's on purpose no companion
+     * <code>isNull()</code> .
+     */
+    public boolean isNonNull() {
+        return atNonNull() || atInstanceOf();
+    }
+
+    /**
+     * The most precise type known so far about the scrutinee. (Please notice that nothing can be
+     * deduced about the non-nullness-status of the scrutinee from invoking this method alone).
+     */
+    public ResolvedJavaType type() {
+        return seen;
+    }
+
+    public ObjectStamp asStamp() {
+        boolean isKnownExact = (seen != null && seen.equals(seen.asExactType()));
+        return new ObjectStamp(seen, isKnownExact, isNonNull(), false);
+    }
+
+    private LEVEL level = LEVEL.CLUELESS;
+    private ResolvedJavaType seen = null;
+
+    /**
+     * Evidence (ie, a {@link com.oracle.graal.nodes.extended.GuardingNode}) attesting to the status
+     * reported by this witness.
+     *
+     * May be one of:
+     *
+     * <ul>
+     * <li>
+     * {@link com.oracle.graal.nodes.BeginNode BeginNode},</li>
+     * <li>
+     * {@link com.oracle.graal.nodes.LoopExitNode LoopExitNode},</li>
+     * <li>
+     * {@link com.oracle.graal.nodes.FixedGuardNode FixedGuardNode}</li>
+     * <li>{@link com.oracle.graal.nodes.MergeNode MergeNode}, resulting from merging two witnesses
+     * with different values for this anchor</li>
+     * </ul>
+     *
+     * <p>
+     * An {@link com.oracle.graal.nodes.calc.ObjectEqualsNode ObjectEqualsNode} test results in the
+     * more-clueless of both scrutinees having its witness upgraded to that of the other (both
+     * scrutinees share the same {@link Witness Witness} instance from then on). For this reason,
+     * this field may also hold the anchors associated to an
+     * {@link com.oracle.graal.nodes.calc.ObjectEqualsNode ObjectEqualsNode} occurrence, ie nodes
+     * that can serve as {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} for the
+     * purposes of building a {@link com.oracle.graal.nodes.PiNode PiNode}.
+     * </p>
+     *
+     */
+    private GuardingNode gn = null;
+
+    /**
+     * Invariants of this class:
+     * <ul>
+     * <li>All fields holding null is ok, the hallmark of a {@link #clueless() clueless} witness.
+     * Another way for a witness to be clueless is by recording <code>java.lang.Object</code> as the
+     * seen type and nothing more.</li>
+     * <li>{@link #seen seen} may be null as long as the only hint being recorded is non-nullness</li>
+     * <li>A non-null value for {@link #seen seen} can't be tracked with NN, that combination
+     * amounts to IO and is tracked as such</li>
+     * <li>At most one of NN, CC, IO may be tracked at any given time</li>
+     * <li>A non-null CC or a non-null IO force {@link #seen seen} to be non-null</li>
+     * <li>{@link #seen seen} must be null or denote a non-interface reference type (ie, either a
+     * class-type or an array-type)</li>
+     * </ul>
+     */
+    private boolean repOK() {
+        if (clueless()) {
+            assert level == LEVEL.CLUELESS;
+            return true;
+        }
+        if (level == LEVEL.NN) {
+            assert seen == null;
+        }
+        if (seen != null) {
+            assert !seen.isInterface();
+            assert !seen.isPrimitive();
+        }
+        boolean gnOK = gn instanceof BeginNode || gn instanceof LoopExitNode || gn instanceof MergeNode || gn instanceof FixedGuardNode;
+        assert gnOK;
+        return true;
+    }
+
+    /**
+     * Helper method for readability in complex conditions.
+     */
+    public boolean clueless() {
+        return cluelessAboutType() && cluelessAboutNonNullness();
+    }
+
+    /**
+     * Helper method for readability in complex conditions.
+     */
+    public boolean cluelessAboutType() {
+        // TODO also clueless when `seen` is `java.lang.Object`
+        return seen == null;
+    }
+
+    /**
+     * Helper method for readability in complex conditions.
+     */
+    public boolean cluelessAboutNonNullness() {
+        return !atNonNull() && !atInstanceOf();
+    }
+
+    /**
+     * Whether this {@link Witness Witness} tracks information strictly more precise than that in
+     * the given {@link com.oracle.graal.compiler.common.type.ObjectStamp}.
+     */
+    boolean knowsBetterThan(ObjectStamp other) {
+        return FlowUtil.isMorePrecise(asStamp(), other);
+    }
+
+    /**
+     * Whether this {@link Witness Witness} tracks information strictly more precise than that in
+     * the {@link com.oracle.graal.compiler.common.type.ObjectStamp} of the given argument.
+     */
+    boolean knowsBetterThan(ValueNode other) {
+        return knowsBetterThan((ObjectStamp) other.stamp());
+    }
+
+    /**
+     * Porcelain method for internal use only, invoked upon a Facade method being notified about
+     * checkcast or instanceof.
+     *
+     * @return whether the state was updated (iff the observation adds any new information)
+     */
+    private boolean refinesSeenType(ResolvedJavaType observed) {
+        if (cluelessAboutType() || FlowUtil.isMorePrecise(observed, seen)) {
+            seen = observed;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Updates this {@link Witness Witness} to account for an observation about the scrutinee being
+     * non-null. In case instanceof was observed,
+     * {@link #trackIO(com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode)
+     * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead
+     *
+     * @return whether this {@link Witness Witness} was updated (iff the observation adds any new
+     *         information)
+     */
+    public boolean trackNN(GuardingNode anchor) {
+        assert repOK();
+        try {
+            if (atInstanceOf()) {
+                return false;
+            }
+            if (atCheckCast()) {
+                transition(LEVEL.IO, anchor);
+                return true;
+            }
+            if (!atNonNull()) {
+                transition(LEVEL.NN, anchor);
+                return true;
+            }
+            return false;
+        } finally {
+            assert repOK();
+        }
+    }
+
+    /**
+     * Updates this {@link Witness Witness} to account for an observation about the scrutinee
+     * conforming to the provided type. In case instanceof was observed,
+     * {@link #trackIO(com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode)
+     * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead.
+     *
+     * @return true iff information was gained.
+     */
+    public boolean trackCC(ResolvedJavaType observed, GuardingNode anchor) {
+        assert !observed.isInterface();
+        assert anchor != null;
+        assert repOK();
+        try {
+            boolean anchorObsolete = refinesSeenType(observed);
+            if (atInstanceOf()) {
+                /*
+                 * Statechart: self-transition at IO, potential information gain.
+                 */
+                if (anchorObsolete) {
+                    transition(LEVEL.IO, anchor);
+                    return true;
+                }
+                return false;
+            }
+            if (anchorObsolete) {
+                if (!atNonNull()) {
+                    /* Statechart: transition from clueless to CC. */
+                    transition(LEVEL.CC, anchor);
+                    return true;
+                } else {
+                    /* Statechart: transition from NN to IO. */
+                    transition(LEVEL.IO, anchor);
+                    return true;
+                }
+            }
+            /*
+             * Statechart: self-transition from whichever the current state is to itself, without
+             * information gain.
+             */
+            return false;
+        } finally {
+            assert repOK();
+        }
+    }
+
+    /**
+     * Updates this {@link Witness Witness} to account for an observation about the non-null
+     * scrutinee conforming to a type.
+     *
+     * @return whether this {@link Witness Witness} was updated (iff the observation adds any new
+     *         information)
+     */
+    public boolean trackIO(ResolvedJavaType observed, GuardingNode anchor) {
+        assert repOK();
+        try {
+            boolean gotMorePreciseType = refinesSeenType(observed);
+            if (!atInstanceOf() || gotMorePreciseType) {
+                transition(LEVEL.IO, anchor);
+                return true;
+            }
+            return gotMorePreciseType;
+        } finally {
+            assert repOK();
+        }
+    }
+
+    /**
+     * Shallow cloning is enough because what's reachable from {@link Witness} is primitive or used
+     * read-only when merging states.
+     * */
+    @Override
+    public Witness clone() {
+        return new Witness(this);
+    }
+
+    /**
+     * @return null for a clueless method, non-null otherwise.
+     * */
+    GuardingNode guard() {
+        return gn;
+    }
+
+    /**
+     * Merges another state into this one, by mutating this object, the other is left as is.
+     * */
+    public void merge(Witness that, MergeNode merge) {
+        assert this.repOK();
+        assert that.repOK();
+
+        if (clueless()) {
+            return;
+        }
+
+        // umbrella type over the observations from both witnesses
+        ResolvedJavaType newSeen = (seen == null || that.seen == null) ? null : FlowUtil.widen(seen, that.seen);
+
+        // preserve guarding node only if matches other, otherwise settle on `merge`
+        final GuardingNode resultGuard = guard() == that.guard() ? guard() : merge;
+
+        /*
+         * guarantee on (both conformance and non-nullness) required from each input in order for
+         * the result to be able to offer such guarantee
+         */
+        final boolean resultIO = atInstanceOf() && that.atInstanceOf();
+        /* failing that, attempt to rescue type-conformance */
+        final boolean resultCC = !resultIO && (!cluelessAboutType() && !that.cluelessAboutType());
+        /* if all else fails, attempt to rescue non-nullness */
+        final boolean resultNN = !resultIO && !resultCC && (isNonNull() && that.isNonNull());
+
+        seen = newSeen;
+        level = resultIO ? LEVEL.IO : resultCC ? LEVEL.CC : resultNN ? LEVEL.NN : LEVEL.CLUELESS;
+        gn = resultGuard;
+
+        assert repOK();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(cluelessAboutType() ? "seen=?" : "seen=" + seen);
+        sb.append(";");
+        sb.append("gn=" + gn);
+        return sb.toString();
+    }
+
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Mon Apr 28 11:18:15 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,8 +61,8 @@
             } 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 {
                             assert false : "unexpected cycle detected at input " + node + " -> " + input;
                         }
@@ -119,8 +122,7 @@
                 }
             }
         } catch (GraalInternalError e) {
-            e.addContext(node);
-            throw e;
+            throw GraalGraphInternalError.transformAndAddContext(e, node);
         }
     }
 
@@ -140,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;
                 }
 
@@ -156,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;
@@ -180,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Providers.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Mon Apr 28 11:18:15 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.*;
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,6 +31,7 @@
 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;
@@ -379,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(" ");
         }
@@ -488,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Mon Apr 28 11:18:15 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/AMD64FloatConvertNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,11 @@
 
 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.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
@@ -37,7 +38,7 @@
 @ServiceProvider(ReplacementsProvider.class)
 public class AMD64Substitutions implements ReplacementsProvider {
 
-    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, Replacements replacements, TargetDescription target) {
+    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) {
         if (Intrinsify.getValue()) {
             replacements.registerSubstitutions(ArraysSubstitutions.class);
             replacements.registerSubstitutions(StringSubstitutions.class);
--- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Mon Apr 28 11:18:15 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/CheckCastTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.replacements.test;
 
+import org.junit.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.test.*;
 
 /**
  * Tests the implementation of checkcast, allowing profiling information to be manually specified.
@@ -41,7 +42,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void test1() {
         test("asNumber", profile(), 111);
         test("asNumber", profile(Integer.class), 111);
@@ -51,7 +52,7 @@
         test("asNumberExt", profile(Long.class, Short.class), 111);
     }
 
-    @LongTest
+    @Test
     public void test2() {
         test("asString", profile(), "111");
         test("asString", profile(String.class), "111");
@@ -67,27 +68,27 @@
         test("asStringExt", profile(String.class), "111");
     }
 
-    @LongTest
+    @Test
     public void test3() {
         test("asNumber", profile(), "111");
     }
 
-    @LongTest
+    @Test
     public void test4() {
         test("asString", profile(String.class), 111);
     }
 
-    @LongTest
+    @Test
     public void test5() {
         test("asNumberExt", profile(), "111");
     }
 
-    @LongTest
+    @Test
     public void test6() {
         test("asStringExt", profile(String.class), 111);
     }
 
-    @LongTest
+    @Test
     public void test7() {
         Throwable throwable = new Exception();
         test("asThrowable", profile(), throwable);
@@ -95,12 +96,12 @@
         test("asThrowable", profile(Exception.class, Error.class), throwable);
     }
 
-    @LongTest
+    @Test
     public void test8() {
         test("arrayStore", new Object[100], "111");
     }
 
-    @LongTest
+    @Test
     public void test801() {
         test("arrayFill", new Object[100], "111");
     }
@@ -197,7 +198,7 @@
         return (Cloneable) o;
     }
 
-    @LongTest
+    @Test
     public void test9() {
         Object o = new Depth13();
         test("asDepth12", profile(), o);
@@ -205,7 +206,7 @@
         test("asDepth12", profile(Depth13.class, Depth14.class), o);
     }
 
-    @LongTest
+    @Test
     public void test10() {
         Object o = new Depth13[3][];
         test("asDepth12Arr", o);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,10 @@
  */
 package com.oracle.graal.replacements.test;
 
+import org.junit.*;
+
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.test.*;
 
 /**
  * Tests for {@link InstanceOfDynamicNode}.
@@ -35,7 +36,7 @@
         return value;
     }
 
-    @LongTest
+    @Test
     public void test100() {
         final Object nul = null;
         test("isStringDynamic", nul);
@@ -43,7 +44,7 @@
         test("isStringDynamic", Object.class);
     }
 
-    @LongTest
+    @Test
     public void test101() {
         final Object nul = null;
         test("isStringIntDynamic", nul);
@@ -51,7 +52,7 @@
         test("isStringIntDynamic", Object.class);
     }
 
-    @LongTest
+    @Test
     public void test103() {
         test("isInstanceDynamic", String.class, null);
         test("isInstanceDynamic", String.class, "object");
@@ -61,7 +62,7 @@
         test("isInstanceDynamic", int.class, Object.class);
     }
 
-    @LongTest
+    @Test
     public void test104() {
         test("isInstanceIntDynamic", String.class, null);
         test("isInstanceIntDynamic", String.class, "object");
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,8 @@
 
 import java.util.*;
 
+import org.junit.*;
+
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.code.CompilationResult.Site;
@@ -34,7 +36,6 @@
 import com.oracle.graal.replacements.test.CheckCastTest.Depth12;
 import com.oracle.graal.replacements.test.CheckCastTest.Depth13;
 import com.oracle.graal.replacements.test.CheckCastTest.Depth14;
-import com.oracle.graal.test.*;
 
 /**
  * Tests the implementation of instanceof, allowing profiling information to be manually specified.
@@ -54,7 +55,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void test1() {
         test("isString", profile(), "object");
         test("isString", profile(String.class), "object");
@@ -63,7 +64,7 @@
         test("isString", profile(String.class), Object.class);
     }
 
-    @LongTest
+    @Test
     public void test2() {
         test("isStringInt", profile(), "object");
         test("isStringInt", profile(String.class), "object");
@@ -72,7 +73,7 @@
         test("isStringInt", profile(String.class), Object.class);
     }
 
-    @LongTest
+    @Test
     public void test201() {
         test("isStringIntComplex", profile(), "object");
         test("isStringIntComplex", profile(String.class), "object");
@@ -81,7 +82,7 @@
         test("isStringIntComplex", profile(String.class), Object.class);
     }
 
-    @LongTest
+    @Test
     public void test3() {
         Throwable throwable = new Exception();
         test("isThrowable", profile(), throwable);
@@ -93,7 +94,7 @@
         test("isThrowable", profile(Exception.class, Error.class), Object.class);
     }
 
-    @LongTest
+    @Test
     public void test301() {
         onlyFirstIsException(new Exception(), new Error());
         test("onlyFirstIsException", profile(), new Exception(), new Error());
@@ -102,7 +103,7 @@
         test("onlyFirstIsException", profile(), new Error(), new Error());
     }
 
-    @LongTest
+    @Test
     public void test4() {
         Throwable throwable = new Exception();
         test("isThrowableInt", profile(), throwable);
@@ -114,7 +115,7 @@
         test("isThrowableInt", profile(Exception.class, Error.class), Object.class);
     }
 
-    @LongTest
+    @Test
     public void test5() {
         Map<?, ?> map = new HashMap<>();
         test("isMap", profile(), map);
@@ -127,7 +128,7 @@
         test("isMap", profile(String.class, HashMap.class), Object.class);
     }
 
-    @LongTest
+    @Test
     public void test6() {
         Map<?, ?> map = new HashMap<>();
         test("isMapInt", profile(), map);
@@ -139,7 +140,7 @@
         test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class);
     }
 
-    @LongTest
+    @Test
     public void test7() {
         Object o = new Depth13();
         test("isDepth12", profile(), o);
@@ -153,7 +154,7 @@
         test("isDepth12", profile(String.class, HashMap.class), o);
     }
 
-    @LongTest
+    @Test
     public void test8() {
         Object o = new Depth13();
         test("isDepth12Int", profile(), o);
@@ -259,7 +260,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void test9() {
         MyCall callAt63 = new MyCall(63);
         MyMark markAt63 = new MyMark(63);
@@ -276,11 +277,10 @@
         return s1.offset - s2.offset;
     }
 
-    @LongTest
+    @Test
     public void test10() {
-        Mark[] noMarks = {};
         Call callAt63 = new Call(null, 63, 5, true, null);
-        Mark markAt63 = new Mark(63, "1", noMarks);
+        Mark markAt63 = new Mark(63, "1");
         test("compareSites", callAt63, callAt63);
         test("compareSites", callAt63, markAt63);
         test("compareSites", markAt63, callAt63);
@@ -301,7 +301,7 @@
      * The test exists in this source file as the transformation was originally motivated by the
      * need to remove use of special JumpNodes in the {@code InstanceOfSnippets}.
      */
-    @LongTest
+    @Test
     public void testRemoveIntermediateMaterialization() {
         List<String> list = Arrays.asList("1", "2", "3", "4");
         test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no");
@@ -356,7 +356,7 @@
         return o instanceof D[];
     }
 
-    @LongTest
+    @Test
     public void testArray() {
         Object aArray = new A[10];
         test("isArrayOfA", aArray);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,7 +25,6 @@
 import org.junit.*;
 
 import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.test.*;
 
 /**
  * Tests the implementation of {@code [A]NEWARRAY}.
@@ -58,7 +57,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void test1() {
         for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
             test("new" + type + "Array7");
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,7 +27,6 @@
 import org.junit.*;
 
 import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.test.*;
 
 /**
  * Tests the implementation of {@code NEW}.
@@ -57,12 +56,12 @@
         }
     }
 
-    @LongTest
+    @Test
     public void test1() {
         test("newObject");
     }
 
-    @LongTest
+    @Test
     public void test2() {
         test("newObjectTwice");
     }
@@ -71,37 +70,37 @@
         return new Object();
     }
 
-    @LongTest
+    @Test
     public void test3() {
         test("newObjectLoop", 100);
     }
 
-    @LongTest
+    @Test
     public void test4() {
         test("newBigObject");
     }
 
-    @LongTest
+    @Test
     public void test5() {
         test("newSomeObject");
     }
 
-    @LongTest
+    @Test
     public void test6() {
         test("newEmptyString");
     }
 
-    @LongTest
+    @Test
     public void test7() {
         test("newString", "value");
     }
 
-    @LongTest
+    @Test
     public void test8() {
         test("newHashMap", 31);
     }
 
-    @LongTest
+    @Test
     public void test9() {
         test("newRegression", true);
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,12 +25,13 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import org.junit.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.test.*;
 
 /**
  * Tests the lowering of the MULTIANEWARRAY instruction.
@@ -86,7 +87,7 @@
     Class<?> bottomClass;
     int[] dimensions;
 
-    @LongTest
+    @Test
     public void test1() {
         for (Class<?> clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) {
             bottomClass = clazz;
@@ -117,7 +118,7 @@
         return new Object[10][9][8];
     }
 
-    @LongTest
+    @Test
     public void test2() {
         test("newMultiArrayException");
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Mon Apr 28 11:18:15 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<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 testMathSubstitutions() {
         assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class);     // Java
--- /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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,8 @@
 
 import java.lang.reflect.*;
 
+import org.junit.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
@@ -31,7 +33,6 @@
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing;
 import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
-import com.oracle.graal.test.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -53,7 +54,7 @@
         return installer.makeGraph(resolvedMethod, null, resolvedMethod, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect);
     }
 
-    @LongTest
+    @Test
     public void construction() {
         long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
                         Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
@@ -65,7 +66,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void testArithmetic() {
         long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
                         Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
@@ -102,7 +103,7 @@
         }
     }
 
-    @LongTest
+    @Test
     public void testCompare() {
         long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE};
         for (long word1 : words) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,22 +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;
@@ -57,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) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Mon Apr 28 11:18:15 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/GraalMethodSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,11 @@
  */
 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.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -35,7 +36,7 @@
 @ServiceProvider(ReplacementsProvider.class)
 public class GraalMethodSubstitutions implements ReplacementsProvider {
 
-    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) {
+    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) {
         for (Class<?> clazz : BoxingSubstitutions.getClasses()) {
             replacements.registerSubstitutions(clazz);
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Mon Apr 28 11:18:15 2014 +0200
@@ -96,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);
     }
 
     /**
@@ -125,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);
@@ -157,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);
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,6 +28,7 @@
 
 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.*;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,6 +30,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.internal.*;
 import com.oracle.graal.graph.*;
@@ -40,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.*;
@@ -80,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);
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Apr 28 11:18:15 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,6 +35,7 @@
 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.*;
@@ -95,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) {
@@ -531,7 +532,7 @@
     }
 
     private static boolean isInlinable(final ResolvedJavaMethod method) {
-        return !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers());
+        return !method.isAbstract() && !method.isNative();
     }
 
     private static String originalName(Method substituteMethod, String methodSubstitution) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,23 +24,21 @@
 
 //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.*;
+import com.oracle.graal.word.*;
 
 /**
  * A counter that can be safely {@linkplain #inc() incremented} from within a snippet for gathering
  * snippet specific metrics.
  */
 public class SnippetCounter implements Comparable<SnippetCounter> {
-    private static final LocationIdentity SNIPPET_COUNTER_LOCATION = new NamedLocationIdentity("SnippetCounter");
-
     /**
      * A group of related counters.
      */
@@ -107,7 +105,7 @@
 
     /**
      * Creates a counter.
-     * 
+     *
      * @param group the group to which the counter belongs. If this is null, the newly created
      *            counter is disabled and {@linkplain #inc() incrementing} is a no-op.
      * @param name the name of the counter
@@ -130,12 +128,20 @@
     }
 
     /**
+     * We do not want to use the {@link LocationIdentity} of the {@link #value} field, so that the
+     * usage in snippets is always possible. If a method accesses the counter via the field and the
+     * snippet, the result might not be correct though.
+     */
+    protected static final LocationIdentity SNIPPET_COUNTER_LOCATION = new NamedLocationIdentity("SnippetCounter");
+
+    /**
      * Increments the value of this counter. This method can be safely used in a snippet if it is
      * invoked on a compile-time constant {@link SnippetCounter} object.
      */
     public void inc() {
         if (group != null) {
-            DirectObjectStoreNode.storeLong(this, countOffset(), 0, value + 1, SNIPPET_COUNTER_LOCATION);
+            long loadedValue = ObjectAccess.readLong(this, countOffset(), SNIPPET_COUNTER_LOCATION);
+            ObjectAccess.writeLong(this, countOffset(), loadedValue + 1, SNIPPET_COUNTER_LOCATION);
         }
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,11 @@
 package com.oracle.graal.replacements;
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.debug.Debug.*;
 import static java.util.FormattableFlags.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -35,11 +37,13 @@
 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.*;
+import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
@@ -47,7 +51,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 +104,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];
@@ -964,7 +967,15 @@
          * if no FloatingReadNode is reading from this location, the kill to this location is fine.
          */
         for (FloatingReadNode frn : replacee.graph().getNodes(FloatingReadNode.class)) {
-            assert !(kills.contains(frn.location().getLocationIdentity())) : frn + " reads from " + frn.location().getLocationIdentity() + " but " + replacee + " does not kill this location";
+            LocationIdentity locationIdentity = frn.location().getLocationIdentity();
+            if (SnippetCounters.getValue()) {
+                // accesses to snippet counters are artificially introduced and violate the memory
+                // semantics.
+                if (locationIdentity == SnippetCounter.SNIPPET_COUNTER_LOCATION) {
+                    continue;
+                }
+            }
+            assert !kills.contains(locationIdentity) : frn + " reads from location \"" + locationIdentity + "\" but " + replacee + " does not kill this location";
         }
         return true;
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Mon Apr 28 11:18:15 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, Kind.Object);
+        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, Kind.Int);
+        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, Kind.Long);
+        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Long, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,20 +23,18 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 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.*;
 
 /**
  * Compares two arrays with the same length.
  */
-public class ArrayEqualsNode extends FixedWithNextNode implements LIRGenLowerable, Canonicalizable, Virtualizable {
+public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable {
 
     /** {@link Kind} of the arrays to compare. */
     private final Kind kind;
@@ -131,7 +129,7 @@
     public static native boolean equals(double[] array1, double[] array2, int length);
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         Variable result = gen.newVariable(Kind.Int);
         gen.emitArrayEquals(kind, result, gen.operand(array1), gen.operand(array2), gen.operand(length));
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,16 +23,15 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.spi.*;
 
-public class BitCountNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
+public class BitCountNode extends FloatingNode implements LIRLowerable, Canonicalizable {
 
     @Input private ValueNode value;
 
@@ -65,7 +64,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         Variable result = gen.newVariable(Kind.Int);
         gen.emitBitCount(result, gen.operand(value));
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,16 +23,15 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.spi.*;
 
-public class BitScanForwardNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
+public class BitScanForwardNode extends FloatingNode implements LIRLowerable, Canonicalizable {
 
     @Input private ValueNode value;
 
@@ -72,7 +71,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         Variable result = gen.newVariable(Kind.Int);
         gen.emitBitScanForward(result, gen.operand(value));
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,16 +23,15 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.spi.*;
 
-public class BitScanReverseNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
+public class BitScanReverseNode extends FloatingNode implements LIRLowerable, Canonicalizable {
 
     @Input private ValueNode value;
 
@@ -79,7 +78,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         Variable result = gen.newVariable(Kind.Int);
         gen.getLIRGeneratorTool().emitBitScanReverse(result, gen.operand(value));
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,16 +23,15 @@
 package com.oracle.graal.replacements.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.spi.*;
 
-public class ReverseBytesNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
+public class ReverseBytesNode extends FloatingNode implements LIRLowerable, Canonicalizable {
 
     @Input private ValueNode value;
 
@@ -66,9 +65,9 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilder gen) {
+    public void generate(NodeLIRBuilderTool gen) {
         Variable result = gen.newVariable(value.getKind());
-        gen.getLIRGenerator().emitByteSwap(result, gen.operand(value));
+        gen.getLIRGeneratorTool().emitByteSwap(result, gen.operand(value));
         gen.setResult(this, result);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Mon Apr 28 11:18:15 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.sparc/src/com/oracle/graal/sparc/SPARC.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 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
@@ -35,28 +35,28 @@
  */
 public class SPARC extends Architecture {
 
-    // @formatter:off
-
     public static final RegisterCategory CPU = new RegisterCategory("CPU");
     public static final RegisterCategory FPU = new RegisterCategory("FPU");
 
     // General purpose registers
-    public static final Register r0  = new Register(0, 0, "g0", CPU);
-    public static final Register r1  = new Register(1, 1, "g1", CPU);
-    public static final Register r2  = new Register(2, 2, "g2", CPU);
-    public static final Register r3  = new Register(3, 3, "g3", CPU);
-    public static final Register r4  = new Register(4, 4, "g4", CPU);
-    public static final Register r5  = new Register(5, 5, "g5", CPU);
-    public static final Register r6  = new Register(6, 6, "g6", CPU);
-    public static final Register r7  = new Register(7, 7, "g7", CPU);
-    public static final Register r8  = new Register(8, 8, "o0", CPU);
-    public static final Register r9  = new Register(9, 9, "o1", CPU);
+    public static final Register r0 = new Register(0, 0, "g0", CPU);
+    public static final Register r1 = new Register(1, 1, "g1", CPU);
+    public static final Register r2 = new Register(2, 2, "g2", CPU);
+    public static final Register r3 = new Register(3, 3, "g3", CPU);
+    public static final Register r4 = new Register(4, 4, "g4", CPU);
+    public static final Register r5 = new Register(5, 5, "g5", CPU);
+    public static final Register r6 = new Register(6, 6, "g6", CPU);
+    public static final Register r7 = new Register(7, 7, "g7", CPU);
+
+    public static final Register r8 = new Register(8, 8, "o0", CPU);
+    public static final Register r9 = new Register(9, 9, "o1", CPU);
     public static final Register r10 = new Register(10, 10, "o2", CPU);
     public static final Register r11 = new Register(11, 11, "o3", CPU);
     public static final Register r12 = new Register(12, 12, "o4", CPU);
     public static final Register r13 = new Register(13, 13, "o5", CPU);
     public static final Register r14 = new Register(14, 14, "o6", CPU);
     public static final Register r15 = new Register(15, 15, "o7", CPU);
+
     public static final Register r16 = new Register(16, 16, "l0", CPU);
     public static final Register r17 = new Register(17, 17, "l1", CPU);
     public static final Register r18 = new Register(18, 18, "l2", CPU);
@@ -65,6 +65,7 @@
     public static final Register r21 = new Register(21, 21, "l5", CPU);
     public static final Register r22 = new Register(22, 22, "l6", CPU);
     public static final Register r23 = new Register(23, 23, "l7", CPU);
+
     public static final Register r24 = new Register(24, 24, "i0", CPU);
     public static final Register r25 = new Register(25, 25, "i1", CPU);
     public static final Register r26 = new Register(26, 26, "i2", CPU);
@@ -113,12 +114,14 @@
     public static final Register sp = o6;
     public static final Register fp = i6;
 
+    // @formatter:off
     public static final Register[] cpuRegisters = {
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
         r8,  r9,  r10, r11, r12, r13, r14, r15,
         r16, r17, r18, r19, r20, r21, r22, r23,
         r24, r25, r26, r27, r28, r29, r30, r31
     };
+    // @formatter:on
 
     // Floating point registers
     public static final Register f0 = new Register(32, 0, "f0", FPU);
@@ -130,6 +133,43 @@
     public static final Register f6 = new Register(38, 6, "f6", FPU);
     public static final Register f7 = new Register(39, 7, "f7", FPU);
 
+    public static final Register f8 = new Register(40, 8, "f8", FPU);
+    public static final Register f9 = new Register(41, 9, "f9", FPU);
+    public static final Register f10 = new Register(42, 10, "f10", FPU);
+    public static final Register f11 = new Register(43, 11, "f11", FPU);
+    public static final Register f12 = new Register(44, 12, "f12", FPU);
+    public static final Register f13 = new Register(45, 13, "f13", FPU);
+    public static final Register f14 = new Register(46, 14, "f14", FPU);
+    public static final Register f15 = new Register(47, 15, "f15", FPU);
+
+    public static final Register f16 = new Register(48, 16, "f16", FPU);
+    public static final Register f17 = new Register(49, 17, "f17", FPU);
+    public static final Register f18 = new Register(50, 18, "f18", FPU);
+    public static final Register f19 = new Register(51, 19, "f19", FPU);
+    public static final Register f20 = new Register(52, 20, "f20", FPU);
+    public static final Register f21 = new Register(53, 21, "f21", FPU);
+    public static final Register f22 = new Register(54, 22, "f22", FPU);
+    public static final Register f23 = new Register(55, 23, "f23", FPU);
+
+    public static final Register f24 = new Register(56, 24, "f24", FPU);
+    public static final Register f25 = new Register(57, 25, "f25", FPU);
+    public static final Register f26 = new Register(58, 26, "f26", FPU);
+    public static final Register f27 = new Register(59, 27, "f27", FPU);
+    public static final Register f28 = new Register(60, 28, "f28", FPU);
+    public static final Register f29 = new Register(61, 29, "f29", FPU);
+    public static final Register f30 = new Register(62, 30, "f30", FPU);
+    public static final Register f31 = new Register(63, 31, "f31", FPU);
+
+    // @formatter:off
+    public static final Register[] fpuRegisters = {
+        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15,
+        f16, f17, f18, f19, f20, f21, f22, f23,
+        f24, f25, f26, f27, f28, f29, f30, f31
+    };
+    // @formatter:on
+
+    // @formatter:off
     public static final Register[] allRegisters = {
         // CPU
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
@@ -138,9 +178,16 @@
         r24, r25, r26, r27, r28, r29, r30, r31,
         // FPU
         f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15,
+        f16, f17, f18, f19, f20, f21, f22, f23,
+        f24, f25, f26, f27, f28, f29, f30, f31
     };
+    // @formatter:on
 
-    // @formatter:on
+    /**
+     * Stack bias for stack and frame pointer loads.
+     */
+    public static final int STACK_BIAS = 0x7ff;
 
     public SPARC() {
         super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + 1, 8);
--- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalLongUnitTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +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.test;
-
-import java.util.*;
-
-import org.junit.*;
-import org.junit.runners.*;
-import org.junit.runners.model.*;
-
-public class GraalLongUnitTest extends BlockJUnit4ClassRunner {
-
-    public GraalLongUnitTest(Class<?> klass) throws InitializationError {
-        super(klass);
-    }
-
-    @Override
-    protected List<FrameworkMethod> computeTestMethods() {
-        List<FrameworkMethod> methods = new ArrayList<>(5);
-        methods.addAll(getTestClass().getAnnotatedMethods(Test.class));
-        methods.addAll(getTestClass().getAnnotatedMethods(LongTest.class));
-        return methods;
-    }
-}
--- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,14 +26,12 @@
 import java.util.*;
 
 import org.junit.*;
-import org.junit.runner.*;
 
 /**
  * Base class for Graal tests.
  * <p>
  * This contains common utility methods that are used in multiple test projects.
  */
-@RunWith(GraalLongUnitTest.class)
 public class GraalTest {
 
     protected Method getMethod(String methodName) {
--- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/LongTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +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.test;
-
-import java.lang.annotation.*;
-
-/* copy of org.junit.Test */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
-public @interface LongTest {
-
-    static final class None extends Throwable {
-
-        private static final long serialVersionUID = 1L;
-
-        private None() {
-        }
-    }
-
-    Class<? extends Throwable> expected() default None.class;
-
-    long timeout() default 0L;
-}
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java	Mon Apr 28 11:18:15 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);
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,16 +25,16 @@
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.stack.*;
-import com.oracle.graal.graph.*;
+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.impl.*;
 import com.oracle.truffle.api.nodes.*;
 
 public abstract class HotSpotFrameInstance implements FrameInstance {
 
-    private final InspectedFrame stackFrame;
+    protected final InspectedFrame stackFrame;
 
     public HotSpotFrameInstance(InspectedFrame stackFrame) {
         this.stackFrame = stackFrame;
@@ -51,13 +51,15 @@
         if (access == FrameAccess.NONE) {
             return null;
         }
-        if (!slowPath) {
+        if (!slowPath && getNotifyIndex() != -1) {
             MaterializedFrameNotify notify = (MaterializedFrameNotify) stackFrame.getLocal(getNotifyIndex());
-            if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) {
-                notify.setOutsideFrameAccess(access);
-            }
-            if (stackFrame.isVirtual(getFrameIndex())) {
-                stackFrame.materializeVirtualObjects(true);
+            if (notify != null) {
+                if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) {
+                    notify.setOutsideFrameAccess(access);
+                }
+                if (stackFrame.isVirtual(getFrameIndex())) {
+                    stackFrame.materializeVirtualObjects(true);
+                }
             }
         }
         switch (access) {
@@ -82,29 +84,28 @@
         return stackFrame.isVirtual(getFrameIndex());
     }
 
-    public CallTarget getCallTarget() {
-        return (CallTarget) stackFrame.getLocal(getCallTargetIndex());
-    }
+    public abstract CallTarget getCallTarget();
 
-    public CallNode getCallNode() {
+    public abstract CallTarget getTargetCallTarget();
+
+    public Node getCallNode() {
         Object receiver = stackFrame.getLocal(getNotifyIndex());
-        if (receiver instanceof CallNode) {
-            return (CallNode) receiver;
-        } else {
-            return null;
+        if (receiver instanceof DirectCallNode || receiver instanceof IndirectCallNode) {
+            return (Node) receiver;
         }
+        return null;
     }
 
     /**
      * This class represents a frame that is taken from the
-     * {@link DefaultCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[])}
+     * {@link OptimizedDirectCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[], boolean, boolean)}
      * method.
      */
-    public static final class NextFrame extends HotSpotFrameInstance {
+    public static final class CallNodeFrame extends HotSpotFrameInstance {
         public static final Method METHOD;
         static {
             try {
-                METHOD = DefaultCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class);
+                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);
             }
@@ -113,7 +114,7 @@
         private static final int CALL_TARGET_INDEX = 1;
         private static final int FRAME_INDEX = 2;
 
-        public NextFrame(InspectedFrame stackFrame) {
+        public CallNodeFrame(InspectedFrame stackFrame) {
             super(stackFrame);
         }
 
@@ -131,6 +132,16 @@
         protected int getFrameIndex() {
             return FRAME_INDEX;
         }
+
+        @Override
+        public CallTarget getCallTarget() {
+            return getCallNode().getRootNode().getCallTarget();
+        }
+
+        @Override
+        public CallTarget getTargetCallTarget() {
+            return (CallTarget) stackFrame.getLocal(getCallTargetIndex());
+        }
     }
 
     /**
@@ -138,26 +149,28 @@
      * {@link RootCallTarget#callProxy(VirtualFrame)} method.
      */
     @SuppressWarnings("javadoc")
-    public static final class CurrentFrame extends HotSpotFrameInstance {
+    public static final class CallTargetFrame extends HotSpotFrameInstance {
         public static final Method METHOD;
         static {
             try {
-                METHOD = RootCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class);
+                METHOD = OptimizedCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class);
             } catch (NoSuchMethodException | SecurityException e) {
                 throw new GraalInternalError(e);
             }
         }
-        private static final int NOTIFY_INDEX = 0;
+        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 CurrentFrame(InspectedFrame stackFrame) {
+        public CallTargetFrame(InspectedFrame stackFrame, boolean currentFrame) {
             super(stackFrame);
+            this.currentFrame = currentFrame;
         }
 
         @Override
         public Frame getFrame(FrameAccess access, boolean slowPath) {
-            if (!slowPath) {
+            if (!slowPath && currentFrame) {
                 throw new UnsupportedOperationException("cannot access current frame as fast path");
             }
             return super.getFrame(access, slowPath);
@@ -177,5 +190,15 @@
         protected int getFrameIndex() {
             return FRAME_INDEX;
         }
+
+        @Override
+        public CallTarget getCallTarget() {
+            return (CallTarget) stackFrame.getLocal(getCallTargetIndex());
+        }
+
+        @Override
+        public CallTarget getTargetCallTarget() {
+            return null;
+        }
     }
 }
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +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.hotspot;
-
-import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
-
-import java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.truffle.*;
-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 HotSpotOptimizedCallTarget extends OptimizedCallTarget {
-
-    protected final TruffleCompiler compiler;
-    private Future<InstalledCode> installedCodeTask;
-    private SpeculationLog speculationLog = new HotSpotSpeculationLog();
-
-    HotSpotOptimizedCallTarget(RootNode rootNode, TruffleCompiler compiler, int invokeCounter, int compilationThreshold, boolean compilationEnabled) {
-        super(rootNode, invokeCounter, compilationThreshold, compilationEnabled, TruffleUseTimeForCompilationDecision.getValue() ? new TimedCompilationPolicy() : new DefaultCompilationPolicy());
-        this.compiler = compiler;
-    }
-
-    @Override
-    public SpeculationLog getSpeculationLog() {
-        return speculationLog;
-    }
-
-    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.");
-        }
-        HotSpotTruffleRuntime.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();
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,7 +28,6 @@
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.*;
-import com.oracle.graal.truffle.hotspot.substitutions.*;
 
 public final class HotSpotTruffleReplacements extends TruffleReplacements {
 
@@ -41,10 +40,4 @@
         SnippetReflectionProvider snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class);
         return new HotSpotTruffleReplacements(providers, snippetReflection);
     }
-
-    @Override
-    protected void registerTruffleSubstitutions() {
-        super.registerTruffleSubstitutions();
-        registerSubstitutions(HotSpotOptimizedCallTargetSubstitutions.class);
-    }
 }
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,18 +26,20 @@
 import static com.oracle.graal.compiler.GraalCompiler.*;
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
-import java.lang.reflect.*;
 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.graph.*;
+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.*;
@@ -46,6 +48,7 @@
 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.*;
@@ -63,14 +66,38 @@
         return new HotSpotTruffleRuntime();
     }
 
-    private TruffleCompiler truffleCompiler;
+    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() {
@@ -78,20 +105,27 @@
     }
 
     public RootCallTarget createCallTarget(RootNode rootNode) {
-        if (truffleCompiler == null) {
-            truffleCompiler = new TruffleCompilerImpl();
+        CompilationPolicy compilationPolicy;
+        if (acceptForCompilation(rootNode)) {
+            compilationPolicy = new CounterBasedCompilationPolicy();
+        } else {
+            compilationPolicy = new InterpreterOnlyCompilationPolicy();
         }
-        return new HotSpotOptimizedCallTarget(rootNode, truffleCompiler, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), acceptForCompilation(rootNode));
+        return new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, new HotSpotSpeculationLog());
     }
 
-    public CallNode createCallNode(CallTarget target) {
+    public DirectCallNode createDirectCallNode(CallTarget target) {
         if (target instanceof OptimizedCallTarget) {
-            return OptimizedCallNode.create((OptimizedCallTarget) target);
+            return OptimizedDirectCallNode.create((OptimizedCallTarget) target);
         } else {
-            return new DefaultCallNode(target);
+            return new DefaultDirectCallNode(target);
         }
     }
 
+    public IndirectCallNode createIndirectCallNode() {
+        return new OptimizedIndirectCallNode();
+    }
+
     @Override
     public VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
         return OptimizedCallTarget.createFrame(frameDescriptor, arguments);
@@ -166,24 +200,18 @@
     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);
+        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 Method getCallMethod() {
-        Method method;
-        try {
-            method = HotSpotOptimizedCallTarget.class.getDeclaredMethod("call", new Class[]{Object[].class});
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-        return method;
-    }
-
     private static CompilationResultBuilderFactory getOptimizedCallTargetInstrumentationFactory(String arch, ResolvedJavaMethod method) {
         for (OptimizedCallTargetInstrumentationFactory factory : ServiceLoader.loadInstalled(OptimizedCallTargetInstrumentationFactory.class)) {
             if (factory.getArchitecture().equals(arch)) {
@@ -221,16 +249,24 @@
         if (stackIntrospection == null) {
             stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class);
         }
-        ResolvedJavaMethod method = getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.NextFrame.METHOD);
-        final Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(method, method).iterator();
+        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();
-                return new HotSpotFrameInstance.NextFrame(frame);
+                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>() {
@@ -244,13 +280,64 @@
         if (stackIntrospection == null) {
             stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class);
         }
-        ResolvedJavaMethod method = getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CurrentFrame.METHOD);
-        Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(method, method).iterator();
+        Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(callTargetMethod, callTargetMethod, 0).iterator();
         if (frames.hasNext()) {
-            return new HotSpotFrameInstance.CurrentFrame(frames.next());
+            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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/ReadOnlyFrame.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/ReadOnlyFrame.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.truffle.hotspot;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.truffle.api.frame.*;
 
 class ReadOnlyFrame implements Frame {
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/substitutions/HotSpotOptimizedCallTargetSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +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.hotspot.substitutions;
-
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.truffle.*;
-import com.oracle.graal.truffle.hotspot.*;
-import com.oracle.graal.truffle.nodes.asserts.*;
-
-@ClassSubstitution(HotSpotOptimizedCallTarget.class)
-public class HotSpotOptimizedCallTargetSubstitutions {
-
-    @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.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -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));
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Mon Apr 28 11:18:15 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;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CounterBasedCompilationPolicy.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,4 +28,14 @@
 public interface GraalTruffleRuntime extends TruffleRuntime {
 
     Replacements getReplacements();
+
+    void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous);
+
+    boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget);
+
+    boolean isCompiling(OptimizedCallTarget optimizedCallTarget);
+
+    void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget);
+
+    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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +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.frame.*;
-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(VirtualFrame frame, Object[] arguments) {
-        if (CompilerDirectives.inInterpreter()) {
-            interpreterCall();
-            if (inliningCounter.get() > 0 || inliningForced) {
-                return getCurrentCallTarget().callInlined(arguments);
-            }
-        }
-        return callProxy(this, getCurrentCallTarget(), frame, 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Apr 28 11:18:15 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,55 +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 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;
     }
@@ -89,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) {
@@ -103,76 +226,77 @@
         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 (inliningResult != null) {
+        if (inliningPerformed) {
             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);
+        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) {
+        if (result.getCallTarget().inliningPerformed) {
+            return;
+        }
+        result.getCallTarget().inliningPerformed = true;
+        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 == null ? null : 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 callProxy(frame);
+    private static Object castArrayFixedLength(Object[] args, @SuppressWarnings("unused") int length) {
+        return args;
     }
 
     public static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) {
         return new FrameWithoutBoxing(descriptor, args);
     }
 
-    public static FrameWithoutBoxing createMaterializedFrame(FrameDescriptor descriptor, Object[] args) {
-        return new FrameWithoutBoxing(descriptor, args);
-    }
-
     @Override
     public void reportLoopCount(int count) {
         compilationProfile.reportLoopCount(count);
@@ -184,242 +308,11 @@
         invalidate(oldNode, newNode, reason);
     }
 
-    public abstract SpeculationLog getSpeculationLog();
-
     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();
-                }
-            });
-        }
-    }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,9 @@
  */
 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.*;
@@ -35,8 +34,8 @@
 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.*;
@@ -44,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.*;
@@ -69,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) {
@@ -86,11 +82,11 @@
             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())) {
@@ -113,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;
@@ -132,7 +123,16 @@
             if (TraceTruffleCompilationHistogram.getValue() && constantReceivers != null) {
                 DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes");
                 for (Constant c : constantReceivers) {
-                    histogram.add(providers.getMetaAccess().lookupJavaType(c).getName());
+                    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);
             }
@@ -175,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(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) {
@@ -202,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);
                                 }
@@ -259,79 +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;
-        }
-
-        /*
-         * Accessing the 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);
-        Object receiverValue = snippetReflection.asObject(receiverNode.asConstant());
-        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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.truffle;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.nodes.*;
@@ -47,7 +45,7 @@
         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);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Apr 28 11:18:15 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,7 +62,6 @@
     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};
 
@@ -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(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 OptimizedCallTarget compilable) {
+    public void compileMethodImpl(final OptimizedCallTarget compilable) {
         final StructuredGraph graph;
 
         if (TraceTruffleCompilation.getValue()) {
-            OptimizedCallTarget.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()));
 
-            OptimizedCallTarget.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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -54,7 +54,7 @@
     @Option(help = "Enable automatic inlining of call targets")
     public static final OptionValue<Boolean> TruffleFunctionInlining = new OptionValue<>(true);
     @Option(help = "Maximum number of Graal IR nodes during partial evaluation")
-    public static final OptionValue<Integer> TruffleGraphMaxNodes = new OptionValue<>(45000);
+    public static final OptionValue<Integer> TruffleGraphMaxNodes = new OptionValue<>(200000);
     @Option(help = "Stop inlining if caller's cumulative tree size would exceed this limit")
     public static final OptionValue<Integer> TruffleInliningMaxCallerSize = new OptionValue<>(2250);
     @Option(help = "Skip inlining candidate if its tree size exceeds this limit")
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java	Mon Apr 28 11:18:15 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;
 
@@ -51,7 +50,7 @@
         int sourceMethodBci = callTarget.invoke().bci();
         ResolvedJavaMethod targetMethod = callTarget.targetMethod();
         ResolvedJavaType targetReceiverType = null;
-        if (!Modifier.isStatic(sourceMethod.getModifiers()) && callTarget.receiver().isConstant()) {
+        if (!sourceMethod.isStatic() && callTarget.receiver().isConstant()) {
             targetReceiverType = providers.getMetaAccess().lookupJavaType(callTarget.arguments().first().asConstant());
         }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java	Mon Apr 28 11:18:15 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 (target.inliningPerformed || 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,7 +26,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.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java	Mon Apr 28 11:18:15 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/LoadIndexedFinalNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.truffle.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.*;
@@ -58,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 {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Mon Apr 28 11:18:15 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);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,11 @@
  */
 package com.oracle.graal.truffle.nodes.frame;
 
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.spi.*;
 
-public class ForceMaterializeNode extends FixedWithNextNode implements LIRGenLowerable {
+public class ForceMaterializeNode extends FixedWithNextNode implements LIRLowerable {
 
     @Input private ValueNode object;
 
@@ -36,7 +35,7 @@
         this.object = object;
     }
 
-    public void generate(NodeLIRBuilder generator) {
+    public void generate(NodeLIRBuilderTool generator) {
         // nothing to do
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,12 +27,13 @@
 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.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,13 +23,14 @@
 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.*;
 
@@ -88,7 +89,7 @@
     public void lower(LoweringTool tool) {
         CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph()));
         LocationIdentity locationIdentity;
-        if (location.asConstant().isNull()) {
+        if (!location.isConstant() || location.asConstant().isNull()) {
             locationIdentity = LocationIdentity.ANY_LOCATION;
         } else {
             locationIdentity = ObjectLocationIdentity.create(location.asConstant());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,7 @@
 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.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Mon Apr 28 11:18:15 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.*;
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -55,6 +55,11 @@
     }
 
     @MethodSubstitution
+    public static boolean inCompiledCode() {
+        return true;
+    }
+
+    @MethodSubstitution
     public static void interpreterOnly(@SuppressWarnings("unused") Runnable runnable) {
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationBlockState.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Mon Apr 28 11:18:15 2014 +0200
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Apr 28 11:18:15 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.*;
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Apr 28 11:18:15 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.*;
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Mon Apr 28 11:18:15 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.*;
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,12 +26,14 @@
 
 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.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that can be used inside a snippet without having the elements (including the
@@ -107,7 +109,7 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
+    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);
     }
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,6 +28,9 @@
 
 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;
@@ -141,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.
@@ -231,7 +234,7 @@
             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);
@@ -379,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;
     }
 
@@ -400,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +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.*;
@@ -109,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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/OnAdoptTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,130 @@
+/*
+ * 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.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Inserting Extra Nodes into the AST Transparently</h3>
+ * 
+ * <p>
+ * The {@link Node} class provides a callback that is invoked whenever a node is adopted in an AST
+ * by insertion or replacement. Node classes can override the {@code onAdopt()} method to run extra
+ * functionality upon adoption.
+ * </p>
+ * 
+ * <p>
+ * This test demonstrates how node instances of a specific class can be automatically wrapped in
+ * extra nodes when they are inserted into the AST.
+ * </p>
+ */
+public class OnAdoptTest {
+
+    static class Root extends RootNode {
+
+        @Child private Base child1;
+        @Child private Base child2;
+
+        public Root(Base child1, Base child2) {
+            super(null);
+            this.child1 = child1;
+            this.child2 = child2;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return child1.executeInt(frame) + child2.executeInt(frame);
+        }
+
+    }
+
+    abstract static class Base extends Node {
+        public abstract int executeInt(VirtualFrame frame);
+    }
+
+    static class Wrapper extends Base {
+
+        @Child private Base wrappee;
+
+        public Wrapper(Base wrappee) {
+            this.wrappee = wrappee;
+        }
+
+        @Override
+        public int executeInt(VirtualFrame frame) {
+            return 1 + wrappee.executeInt(frame);
+        }
+
+    }
+
+    abstract static class GenBase extends Base {
+
+        private final int k;
+
+        public GenBase(int k) {
+            this.k = k;
+        }
+
+        @Override
+        public int executeInt(VirtualFrame frame) {
+            return k;
+        }
+
+    }
+
+    static class Gen extends GenBase {
+        public Gen(int k) {
+            super(k);
+        }
+    }
+
+    static class GenWrapped extends GenBase {
+
+        public GenWrapped(int k) {
+            super(k);
+        }
+
+        @Override
+        protected void onAdopt() {
+            Wrapper w = new Wrapper(this);
+            this.replace(w);
+        }
+
+    }
+
+    @Test
+    public void testOnInsert() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        Base b1 = new Gen(11);
+        Base b2 = new GenWrapped(11);
+        Root r = new Root(b1, b2);
+        CallTarget ct = runtime.createCallTarget(r);
+        Object result = ct.call();
+        Assert.assertEquals(23, result);
+    }
+
+}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java	Mon Apr 28 11:18:15 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) {
@@ -182,7 +180,7 @@
             }
         }
 
-        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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Mon Apr 28 11:18:15 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,11 +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);
-    }
-
-    public abstract void setNeedsMaterializedFrame();
+    Object call(Object... arguments);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Mon Apr 28 11:18:15 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.
      *
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,38 +24,13 @@
  */
 package com.oracle.truffle.api;
 
-import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
 /**
  * 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;
-    }
-
-    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;
-        }
-    }
+    RootNode getRootNode();
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java	Mon Apr 28 11:18:15 2014 +0200
@@ -34,12 +34,21 @@
     /**
      * Returns the name of this resource holding a guest language program. An example would be the
      * name of a guest language source code file.
-     * 
+     *
      * @return the name of the guest language program
      */
     String getName();
 
     /**
+     * Returns a short version of the name of the resource holding a guest language program (as
+     * described in @getName). For example, this could be just the name of the file, rather than a
+     * full path.
+     *
+     * @return the short name of the guest language program
+     */
+    String getShortName();
+
+    /**
      * The normalized, canonical name of the file.
      */
     String getPath();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,21 +31,21 @@
 
     /**
      * Returns the object representing the source program that contains this section.
-     * 
+     *
      * @return the source object
      */
     Source getSource();
 
     /**
      * Returns 1-based line number of the first character in this source section (inclusive).
-     * 
+     *
      * @return the starting line number
      */
     int getStartLine();
 
     /**
      * Returns the 1-based column number of the first character in this source section (inclusive).
-     * 
+     *
      * @return the starting column number
      */
     int getStartColumn();
@@ -55,7 +55,7 @@
      * <p>
      * The complete text of the source that contains this section can be retrieved via
      * {@link Source#getCode()}.
-     * 
+     *
      * @return the starting character index
      */
     int getCharIndex();
@@ -65,7 +65,7 @@
      * <p>
      * The complete text of the source that contains this section can be retrieved via
      * {@link Source#getCode()}.
-     * 
+     *
      * @return the number of characters in the section
      */
     int getCharLength();
@@ -73,42 +73,54 @@
     /**
      * Returns the index of the text position immediately following the last character in the
      * section.
-     * 
+     *
      * @return the end position of the section
      */
     int getCharEndIndex();
 
     /**
      * Returns the identifier of this source section that is used for printing the section.
-     * 
+     *
      * @return the identifier of the section
      */
     String getIdentifier();
 
     /**
      * Returns text of the code represented by this source section.
-     * 
+     *
      * @return the code as a String object
      */
     String getCode();
 
     /**
+     * Returns a short description of the source section, using just the file name, rather than its
+     * full path.
+     *
+     * @return a short description of the source section
+     */
+    String getShortDescription();
+
+    /**
      * Singleton instance with no content.
      */
     SourceSection NULL = new NullSourceSection() {
 
+        @Override
         public Source getSource() {
             return null;
         }
 
+        @Override
         public int getStartLine() {
             return 0;
         }
 
+        @Override
         public int getStartColumn() {
             return 0;
         }
 
+        @Override
         public int getCharIndex() {
             return 0;
         }
@@ -118,18 +130,26 @@
             return 0;
         }
 
+        @Override
         public int getCharEndIndex() {
             return 0;
         }
 
+        @Override
         public String getIdentifier() {
             return null;
         }
 
+        @Override
         public String getCode() {
             return null;
         }
 
+        @Override
+        public String getShortDescription() {
+            return "short";
+        }
+
     };
 
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,7 +25,6 @@
 package com.oracle.truffle.api;
 
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
 
 /**
@@ -51,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.
@@ -94,9 +106,7 @@
 
     /**
      * Accesses the current stack, i.e., the contents of the {@link Frame}s and the associated
-     * {@link CallTarget}s. For this functionality to work each call needs to go through
-     * {@link DefaultCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[])}
-     * instead of calling {@link CallTarget#call(Object[])} directly.
+     * {@link CallTarget}s.
      *
      * @return a lazy collection of {@link FrameInstance}.
      */
@@ -107,4 +117,5 @@
      * 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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;
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java	Mon Apr 28 11:18:15 2014 +0200
@@ -40,7 +40,7 @@
 
     boolean isVirtualFrame();
 
-    CallNode getCallNode();
+    Node getCallNode();
 
     CallTarget getCallTarget();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractExecutionContext.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +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.CompilerDirectives.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.frame.FrameInstance.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class DefaultCallNode extends CallNode implements MaterializedFrameNotify {
-
-    @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE;
-
-    public DefaultCallNode(CallTarget target) {
-        super(target);
-    }
-
-    @Override
-    public Object call(VirtualFrame frame, Object[] arguments) {
-        return callProxy(this, getCurrentCallTarget(), frame, arguments);
-    }
-
-    public static Object callProxy(MaterializedFrameNotify notify, CallTarget callTarget, VirtualFrame frame, Object[] arguments) {
-        try {
-            if (notify.getOutsideFrameAccess() != FrameAccess.NONE) {
-                CompilerDirectives.materialize(frame);
-            }
-            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 FrameAccess getOutsideFrameAccess() {
-        return outsideFrameAccess;
-    }
-
-    @Override
-    public void setOutsideFrameAccess(FrameAccess outsideFrameAccess) {
-        this.outsideFrameAccess = outsideFrameAccess;
-    }
-
-    @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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,7 +25,6 @@
 package com.oracle.truffle.api.impl;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
@@ -33,22 +32,28 @@
  * 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;
 
-    @CompilationFinal protected boolean needsMaterializedFrame = true;
-
-    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) {
-        VirtualFrame frame = new DefaultVirtualFrame(getRootNode().getFrameDescriptor(), args);
-        return callProxy(frame);
+    public String toString() {
+        return rootNode.toString();
+    }
+
+    public final RootNode getRootNode() {
+        return rootNode;
     }
 
     @Override
-    public void setNeedsMaterializedFrame() {
-        needsMaterializedFrame = true;
+    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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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/DefaultSourceSection.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java	Mon Apr 28 11:18:15 2014 +0200
@@ -53,7 +53,7 @@
      * a character index. The (row,column) coordinates of a newline character should never appear in
      * a text section.
      * <p>
-     * 
+     *
      * @param source object representing the complete source program that contains this section
      * @param identifier an identifier used when printing the section
      * @param startLine the 1-based number of the start line of the section
@@ -102,6 +102,10 @@
         return getSource().getCode().substring(charIndex, charIndex + charLength);
     }
 
+    public final String getShortDescription() {
+        return String.format("%s:%d", source.getShortName(), startLine);
+    }
+
     @Override
     public String toString() {
         return String.format("%s:%d", source.getName(), startLine);
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Mon Apr 28 11:18:15 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
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/MaterializedFrameNotify.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +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.impl;
-
-import com.oracle.truffle.api.frame.FrameInstance.*;
-
-public interface MaterializedFrameNotify {
-
-    FrameAccess getOutsideFrameAccess();
-
-    void setOutsideFrameAccess(FrameAccess outsideFrameAccess);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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.*;
-import com.oracle.truffle.api.frame.*;
-
-/**
- * Represents a call to a {@link CallTarget} in the Truffle AST. In addition to calling the
- * {@link CallTarget}, this {@link Node} enables the runtime system to implement further
- * optimizations. Optimizations that can possibly be 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(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 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 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/DirectCallNode.java	Mon Apr 28 11:18:15 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	Mon Apr 28 11:18:15 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/Node.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Apr 28 11:18:15 2014 +0200
@@ -191,8 +191,12 @@
         if (newChild == this) {
             throw new IllegalStateException("The parent of a node can never be the node itself.");
         }
+        boolean isInserted = newChild.parent == null;
         newChild.parent = this;
         newChild.adoptHelper();
+        if (isInserted) {
+            newChild.onAdopt();
+        }
     }
 
     private void adoptHelper() {
@@ -209,8 +213,12 @@
         if (newChild == this) {
             throw new IllegalStateException("The parent of a node can never be the node itself.");
         }
+        boolean isInserted = newChild.parent == null;
         newChild.parent = this;
         newChild.adoptUnadoptedHelper();
+        if (isInserted) {
+            newChild.onAdopt();
+        }
     }
 
     private void adoptUnadoptedHelper() {
@@ -332,7 +340,6 @@
     }
 
     private void traceRewrite(Node newNode, CharSequence reason) {
-
         if (TruffleOptions.TraceRewritesFilterFromCost != null) {
             if (filterByKind(this, TruffleOptions.TraceRewritesFilterFromCost)) {
                 return;
@@ -352,8 +359,21 @@
             return;
         }
 
+        final SourceSection reportedSourceSection = getEncapsulatingSourceSection();
+
         PrintStream out = System.out;
-        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason);
+        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s%s%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason != null && reason.length() > 0 ? reason
+                        : "unknown", reportedSourceSection != null ? " at " + reportedSourceSection.getShortDescription() : "");
+    }
+
+    /**
+     * Subclasses of {@link Node} can implement this method to execute extra functionality when a
+     * node is effectively inserted into the AST. The {@code onAdopt} callback is called after the
+     * node has been effectively inserted, and it is guaranteed to be called only once for any given
+     * node.
+     */
+    protected void onAdopt() {
+        // empty default
     }
 
     private static String formatNodeInfo(Node node) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 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/SourceManager.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceManager.java	Mon Apr 28 11:18:15 2014 +0200
@@ -70,7 +70,7 @@
     /**
      * Gets the canonical representation of a source file, whose contents will be read lazily and
      * then cached.
-     * 
+     *
      * @param reset forces any existing {@link Source} cache to be cleared, forcing a re-read
      */
     public Source get(String fileName, boolean reset) {
@@ -227,6 +227,11 @@
         }
 
         @Override
+        public String getShortName() {
+            return name;
+        }
+
+        @Override
         public String getCode() {
             return code;
         }
@@ -292,6 +297,11 @@
         }
 
         @Override
+        public String getShortName() {
+            return file.getName();
+        }
+
+        @Override
         public String getCode() {
             if (code == null || timeStamp != file.lastModified()) {
                 try {
--- a/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl	Mon Apr 28 11:18:15 2014 +0200
@@ -19,4 +19,4 @@
     doIt(i);
     i = i + 1;
   }
-}  
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Mon Apr 28 11:18:15 2014 +0200
@@ -35,11 +35,11 @@
 public abstract class SLHelloEqualsWorldBuiltin extends SLBuiltinNode {
 
     @Specialization
-    public Object change() {
+    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 null;
+        return "world";
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Mon Apr 28 11:18:15 2014 +0200
@@ -45,13 +45,17 @@
     @SlowPath
     private static String createStackTrace() {
         StringBuilder str = new StringBuilder();
-        for (FrameInstance frame : Truffle.getRuntime().getStackTrace()) {
-            dumpFrame(str, frame.getCallNode().getRootNode(), frame.getFrame(FrameAccess.READ_ONLY, true), frame.isVirtualFrame());
+        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, RootNode rootNode, Frame frame, boolean isVirtual) {
+    private static void dumpFrame(StringBuilder str, CallTarget rootNode, Frame frame, boolean isVirtual) {
         if (str.length() > 0) {
             str.append("\n");
         }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java	Mon Apr 28 11:18:15 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;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,19 +22,23 @@
  */
 package com.oracle.truffle.sl.nodes.call;
 
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
-import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
 /**
  * Slow-path code for a call, used when the polymorphic inline cache exceeded its maximum size. Such
  * calls are not optimized any further, e.g., no method inlining is performed.
  */
-final class SLGenericDispatchNode extends SLAbstractDispatchNode implements MaterializedFrameNotify {
+final class SLGenericDispatchNode extends SLAbstractDispatchNode {
 
-    @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE;
+    /**
+     * {@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) {
@@ -42,14 +46,7 @@
          * SL has a quite simple call lookup: just ask the function for the current call target, and
          * call it.
          */
-        return DefaultCallNode.callProxy(this, function.getCallTarget(), frame, arguments);
+        return callNode.call(frame, function.getCallTarget(), arguments);
     }
 
-    public FrameAccess getOutsideFrameAccess() {
-        return outsideFrameAccess;
-    }
-
-    public void setOutsideFrameAccess(FrameAccess outsideFrameAccess) {
-        this.outsideFrameAccess = outsideFrameAccess;
-    }
 }
--- a/make/linux/makefiles/buildtree.make	Fri Apr 25 16:21:07 2014 +0200
+++ b/make/linux/makefiles/buildtree.make	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/make/linux/makefiles/vm.make	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/make/solaris/makefiles/mapfile-vers	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Mon Apr 28 11:18:15 2014 +0200
@@ -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	Fri Apr 25 16:21:07 2014 +0200
+++ b/mx/mx_graal.py	Mon Apr 28 11:18:15 2014 +0200
@@ -28,13 +28,14 @@
 
 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
 import sanitycheck
 import itertools
 import json, textwrap
+import fnmatch
 
 # This works because when mx loads this file, it makes sure __file__ gets an absolute path
 _graal_home = dirname(dirname(__file__))
@@ -828,7 +829,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 +861,9 @@
                 mx.log('warning: no tests matched by substring "' + t)
         projectscp = mx.classpath(projs)
 
+    if whitelist:
+        classes = [c for c in classes if any((glob.match(c) for glob in whitelist))]
+
     if len(classes) != 0:
         f_testfile = open(testfile, 'w')
         for c in classes:
@@ -867,7 +871,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 +898,18 @@
             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:
+
+      --whitelist            run only testcases which are included
+                             in the given whitelist
+
+    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 +938,46 @@
 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,
+        )
+    parser.add_argument('--whitelist', help='run testcases specified in whitelist only', metavar='<path>')
+
+    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.whitelist:
+        try:
+            with open(join(_graal_home, parsed_args.whitelist)) as fp:
+                whitelist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')]
+        except IOError:
+            mx.log('warning: could not read whitelist: ' + parsed_args.whitelist)
+
+    _unittest(args, ['@Test', '@Parameters'], whitelist=whitelist)
 
 def shortunittest(args):
-    """run the JUnit tests (short testcases only){0}"""
-
-    _unittest(args, ['@Test'])
+    """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'{0}"""
 
-def longunittest(args):
-    """run the JUnit tests (long testcases only){0}"""
-
-    _unittest(args, ['@LongTest', '@Parameters'])
+    args = ['--whitelist', 'test/whitelist_shortunittest.txt'] + args
+    unittest(args)
 
 def buildvms(args):
     """build one or more VMs in various configurations"""
@@ -1047,6 +1086,11 @@
         unittest([])
         tasks.append(t.stop())
 
+    with VM('server', 'product'):  # hosted mode
+        t = Task('UnitTests-BaselineCompiler:hosted-product')
+        unittest(['--whitelist', 'test/whitelist_baseline.txt', '-G:+UseBaselineCompiler'])
+        tasks.append(t.stop())
+
     for vmbuild in ['fastdebug', 'product']:
         for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild) + sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild):
             t = Task(str(test) + ':' + vmbuild)
@@ -1248,10 +1292,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,17 +1389,140 @@
         with open(resultFile, 'w') as f:
             f.write(json.dumps(results))
 
+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
+
+    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)
+
+    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)
+
+    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)
+
+    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
+
+    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"""
+    """run the JMH benchmarks
 
-    # TODO: add option for `mvn clean package'
+    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 = {'-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'}
+    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:
@@ -1366,21 +1533,10 @@
                 else:
                     jmhArgs[n] = v
         except ValueError as e:
-            mx.abort('error parsing JSON input: {}"\n{}'.format(j, e))
-
-    jmhPath = mx.get_env('JMH_BENCHMARKS', None)
-    if not jmhPath or not exists(jmhPath):
-        mx.abort("$JMH_BENCHMARKS not properly defined: " + str(jmhPath))
+            mx.abort('error parsing JSON input: {}\n{}'.format(j, e))
 
-    def _blackhole(x):
-        mx.logv(x[:-1])
-
-
-    env = os.environ.copy()
-    env['JAVA_HOME'] = _jdk(vmToCheck='graal')
-    env['MAVEN_OPTS'] = '-graal'
-    mx.log("Building benchmarks...")
-    mx.run(['mvn', 'package'], cwd=jmhPath, out=_blackhole, env=env)
+    jmhPath = _get_jmh_path()
+    mx.log('Using benchmarks in ' + jmhPath)
 
     matchedSuites = set()
     numBench = [0]
@@ -1394,8 +1550,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:"):
@@ -1435,7 +1590,6 @@
                 javaArgs.append(str(v))
         mx.run_java(javaArgs + regex, addDefaultArgs=False, cwd=jmhPath)
 
-
 def specjvm2008(args):
     """run one or more SPECjvm2008 benchmarks"""
 
@@ -1556,14 +1710,14 @@
     """make truffle.jar"""
 
     # Test with the built classes
-    _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@LongTest', '@Parameters'])
+    _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@Parameters'])
 
     # We use the DSL processor as the starting point for the classpath - this
     # therefore includes the DSL processor, the DSL and the API.
     packagejar(mx.classpath("com.oracle.truffle.dsl.processor").split(os.pathsep), "truffle.jar", None, "com.oracle.truffle.dsl.processor.TruffleProcessor")
 
     # Test with the JAR
-    _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@LongTest', '@Parameters'], "truffle.jar:")
+    _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@Parameters'], "truffle.jar:")
 
 
 def isGraalEnabled(vm):
@@ -1765,6 +1919,7 @@
 def mx_init(suite):
     commands = {
         'build': [build, ''],
+        'buildjmh': [buildjmh, '[-options]'],
         'buildvars': [buildvars, ''],
         'buildvms': [buildvms, '[-options]'],
         'c1visualizer' : [c1visualizer, ''],
@@ -1784,9 +1939,9 @@
         '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],
+        '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	Fri Apr 25 16:21:07 2014 +0200
+++ b/mx/projects	Mon Apr 28 11:18:15 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
@@ -31,20 +42,23 @@
 library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar
 library@DACAPO_SCALA@sha1=59b64c974662b5cf9dbd3cf9045d293853dd7a51
 
-library@OKRA@path=lib/okra-1.8.jar
-library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.8.jar
-library@OKRA@sourcePath=lib/okra-1.8-src.jar
-library@OKRA@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-src.jar
+library@OKRA@path=lib/okra-1.9.jar
+library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.9.jar
+library@OKRA@sourcePath=lib/okra-1.9-src.jar
+library@OKRA@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-src.jar
 
-library@OKRA_WITH_SIM@path=lib/okra-1.8-with-sim.jar
-library@OKRA_WITH_SIM@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim.jar
-library@OKRA_WITH_SIM@sourcePath=lib/okra-1.8-with-sim-src.jar
-library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim-src.jar
+library@OKRA_WITH_SIM@path=lib/okra-1.9-with-sim.jar
+library@OKRA_WITH_SIM@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim.jar
+library@OKRA_WITH_SIM@sourcePath=lib/okra-1.9-with-sim-src.jar
+library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim-src.jar
 
 library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar
 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,10 +422,11 @@
 # 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
+project@com.oracle.graal.compiler@annotationProcessorForDependents=true
 project@com.oracle.graal.compiler@workingSets=Graal
 
 # graal.compiler.amd64
@@ -485,6 +500,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 +634,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 +746,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/mxtool/mx.py	Mon Apr 28 11:18:15 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)
 
@@ -1690,10 +1800,13 @@
     parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)')
     parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects')
     parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects')
-    parser.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not')
-    parser.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='<path>')
     parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors')
-    parser.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>')
+    parser.add_argument('--jdt-show-task-tags', action='store_true', help='show task tags as Eclipse batch compiler warnings')
+    compilerSelect = parser.add_mutually_exclusive_group()
+    compilerSelect.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>')
+    compilerSelect.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='<path>')
+    compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not')
+
 
     if suppliedParser:
         parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
@@ -1775,12 +1888,11 @@
 
         cp = classpath(p.name, includeSelf=True)
         sourceDirs = p.source_dirs()
-        mustBuild = args.force
-        if not mustBuild:
+        buildReason = 'forced build' if args.force else None
+        if not buildReason:
             for dep in p.all_deps([], False):
                 if dep.name in built:
-                    mustBuild = True
-
+                    buildReason = dep.name + ' rebuilt'
 
         jasminAvailable = None
         javafilelist = []
@@ -1829,20 +1941,19 @@
                         if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)):
                             shutil.copyfile(src, dst)
 
-                if not mustBuild:
+                if not buildReason:
                     for javafile in javafiles:
                         classfile = TimeStampFile(outputDir + javafile[len(sourceDir):-len('java')] + 'class')
                         if not classfile.exists() or classfile.isOlderThan(javafile):
-                            mustBuild = True
+                            buildReason = 'class file(s) out of date'
                             break
 
         aps = p.annotation_processors()
         apsOutOfDate = p.update_current_annotation_processors_file()
         if apsOutOfDate:
-            logv('[annotation processors for {0} changed]'.format(p.name))
-            mustBuild = True
-
-        if not mustBuild:
+            buildReason = 'annotation processor(s) changed'
+
+        if not buildReason:
             logv('[all class files for {0} are up to date - skipping]'.format(p.name))
             continue
 
@@ -1874,10 +1985,14 @@
 
         toBeDeleted = [argfileName]
         try:
+
+            def logCompilation(p, compiler, reason):
+                log('Compiling Java sources for {} with {}... [{}]'.format(p.name, compiler, reason))
+
             if not jdtJar:
                 mainJava = java()
                 if not args.error_prone:
-                    log('Compiling Java sources for {0} with javac...'.format(p.name))
+                    logCompilation(p, 'javac', buildReason)
                     javacCmd = [mainJava.javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()]
                     if jdk.debug_port is not None:
                         javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)]
@@ -1888,7 +2003,7 @@
                         javacCmd.append('-XDignore.symbol.file')
                     run(javacCmd)
                 else:
-                    log('Compiling Java sources for {0} with javac (with error-prone)...'.format(p.name))
+                    logCompilation(p, 'javac (with error-prone)', buildReason)
                     javaArgs = ['-Xmx1g']
                     javacArgs = ['-g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()]
                     javacArgs += processorArgs
@@ -1897,7 +2012,7 @@
                         javacArgs.append('-XDignore.symbol.file')
                     run_java(javaArgs + ['-cp', os.pathsep.join([mainJava.toolsjar, args.error_prone]), 'com.google.errorprone.ErrorProneCompiler'] + javacArgs)
             else:
-                log('Compiling Java sources for {0} with JDT...'.format(p.name))
+                logCompilation(p, 'JDT', buildReason)
 
                 jdtVmArgs = ['-Xmx1g', '-jar', jdtJar]
 
@@ -1918,11 +2033,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 +2062,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 +2197,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 +2318,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 +2541,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 +2915,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')
@@ -3611,7 +3685,7 @@
         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'}) # TODO use p.output_dir() ?
+        moduleXml.element('output', attributes={'url': 'file://$MODULE_DIR$/bin'})
         moduleXml.element('exclude-output')
 
         moduleXml.open('content', attributes={'url': 'file://$MODULE_DIR$'})
@@ -3675,12 +3749,12 @@
         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.path, suite.dir) + '!/'})
+        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.sourcePath, suite.dir) + '!/'})
+            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')
@@ -3732,7 +3806,7 @@
     # 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.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'))
@@ -3773,7 +3847,7 @@
 
 
 def ideinit(args, refreshOnly=False, buildProcessorJars=True):
-    """(re)generate Eclipse and NetBeans project configurations"""
+    """(re)generate Eclipse, NetBeans and Intellij project configurations"""
     eclipseinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
     netbeansinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
     intellijinit(args, refreshOnly=refreshOnly)
@@ -4270,6 +4344,111 @@
                 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('-a', '--include-all', action='store_true', help="include all defined libaries")
+    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 + ']')
+
+        libsToExport = set()
+        if args.include_all:
+            for lib in _libs.itervalues():
+                libsToExport.add(lib)
+        else:
+            def isValidLibrary(dep):
+                if dep in _libs.iterkeys():
+                    lib = _libs[dep]
+                    if len(lib.urls) != 0 or args.include_system_libs:
+                        return lib
+                return None
+
+            # iterate over all project dependencies and find used libraries
+            for p in _projects.itervalues():
+                for dep in p.deps:
+                    r = isValidLibrary(dep)
+                    if r:
+                        libsToExport.add(r)
+
+            # a library can have other libraries as dependency
+            size = 0
+            while size != len(libsToExport):
+                size = len(libsToExport)
+                for lib in libsToExport.copy():
+                    for dep in lib.deps:
+                        r = isValidLibrary(dep)
+                        if r:
+                            libsToExport.add(r)
+
+        for lib in libsToExport:
+            add(lib.get_path(resolve=True), lib.path)
+            if lib.sha1:
+                add(lib.get_path(resolve=True) + ".sha1", lib.path + ".sha1")
+            if lib.sourcePath:
+                add(lib.get_source_path(resolve=True), lib.sourcePath)
+                if lib.sourceSha1:
+                    add(lib.get_source_path(resolve=True) + ".sha1", lib.sourcePath + ".sha1")
+
+        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"""
 
@@ -4338,6 +4517,7 @@
     'clean': [clean, ''],
     'eclipseinit': [eclipseinit, ''],
     'eclipseformat': [eclipseformat, ''],
+    'exportlibs': [exportlibs, ''],
     'findclass': [findclass, ''],
     'fsckprojects': [fsckprojects, ''],
     'help': [help_, '[command]'],
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/graalCodeInstaller_x86.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/cpu/x86/vm/vmStructs_x86.hpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/gpu/hsail/vm/gpu_hsail.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/gpu/hsail/vm/gpu_hsail.hpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.hpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/os/bsd/vm/gpu_bsd.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/os/linux/vm/gpu_linux.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/os/windows/vm/gpu_windows.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Mon Apr 28 11:18:15 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) \
@@ -227,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) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Apr 28 11:18:15 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")                      \
@@ -344,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")                           \
--- a/src/share/vm/code/codeBlob.hpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/code/codeBlob.hpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/code/compiledIC.cpp	Mon Apr 28 11:18:15 2014 +0200
@@ -228,11 +228,13 @@
   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_method = caller->is_compiled_by_c1();
-  assert( is_c1_method ||
+  bool is_c1_or_graal_method = caller->is_compiled_by_c1() || caller->is_compiled_by_graal();
+  assert( is_c1_or_graal_method ||
          !is_monomorphic ||
          is_optimized() ||
          (cached_metadata() != NULL && cached_metadata()->is_klass()), "sanity check");
--- a/src/share/vm/code/debugInfoRec.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/code/debugInfoRec.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/code/nmethod.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/compiler/disassembler.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/gc_interface/collectedHeap.hpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Apr 28 11:18:15 2014 +0200
@@ -455,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.
@@ -677,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));
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Mon Apr 28 11:18:15 2014 +0200
@@ -130,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/graalCompiler.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Mon Apr 28 11:18:15 2014 +0200
@@ -101,12 +101,10 @@
       _external_deopt_i2c_entry = create_external_deopt_i2c();
 #ifdef COMPILERGRAAL
       bool bootstrap = FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal;
-      bool hostedOnly = false;
 #else
       bool bootstrap = false;
-      bool hostedOnly = true;
 #endif
-      VMToCompiler::startCompiler(bootstrap, hostedOnly);
+      VMToCompiler::startCompiler(bootstrap);
       _initialized = true;
       CompilationPolicy::completed_vm_startup();
       if (bootstrap) {
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Apr 28 11:18:15 2014 +0200
@@ -157,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);
@@ -191,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()));
@@ -207,6 +210,7 @@
 #undef set_boolean
 #undef set_int
 #undef set_long
+#undef set_address
 
 C2V_END
 
@@ -527,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());
@@ -557,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));
@@ -630,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);
   }
@@ -721,14 +728,14 @@
 
 
 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, getJavaMirror, (JNIEnv *env, jobject, jlong metaspace_klass))
@@ -736,12 +743,6 @@
   return JNIHandles::make_local(klass->java_mirror());
 C2V_END
 
-C2V_VMENTRY(void, setNodeClass, (JNIEnv *env, jobject, jobject java_class_handle, jobject value))
-  oop java_class = JNIHandles::resolve(java_class_handle);
-  InstanceKlass* iklass = (InstanceKlass*) java_lang_Class::as_Klass(java_class);
-  iklass->set_graal_node_class(JNIHandles::resolve(value));
-C2V_END
-
 C2V_VMENTRY(jlong, readUnsafeKlassPointer, (JNIEnv *env, jobject, jobject o))
   oop resolved_o = JNIHandles::resolve(o);
   jlong klass = (jlong)(address)resolved_o->klass();
@@ -756,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
@@ -786,12 +787,21 @@
   return tty->time_stamp().milliseconds();
 C2V_END
 
-// public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, ResolvedJavaMethod method);
-C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv *env, jobject compilerToVM, jobject hs_frame, jobject hs_method))
+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;
-  methodHandle method = hs_method == NULL ? NULL : asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hs_method));
   Handle result = InstanceKlass::cast(HotSpotStackFrameReference::klass())->allocate_instance(thread);
   HotSpotStackFrameReference::klass()->initialize(thread);
 
@@ -840,48 +850,48 @@
       if (vf->is_compiled_frame()) {
         // compiled method frame
         compiledVFrame* cvf = compiledVFrame::cast(vf);
-        if (method == NULL || cvf->method() == method()) {
-          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);
+        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);
             }
 
-            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());
-          if (hs_method == NULL) {
+            locals = cvf->locals();
+            HotSpotStackFrameReference::set_bci(result, cvf->bci());
             HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) cvf->method());
-          } else {
-            HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) method());
           }
         }
       } else if (vf->is_interpreted_frame()) {
         // interpreted method frame
         interpretedVFrame* ivf = interpretedVFrame::cast(vf);
-        if (method == NULL || ivf->method() == method()) {
-          locals = ivf->locals();
-          HotSpotStackFrameReference::set_bci(result, ivf->bci());
-          if (hs_method == NULL) {
+        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());
-          } else {
-            HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) method());
+            HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
           }
-          HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
         }
       }
 
@@ -923,7 +933,13 @@
   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))
@@ -1031,9 +1047,10 @@
 #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"
@@ -1067,25 +1084,25 @@
   {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"invalidateInstalledCode",                      CC"("INSTALLED_CODE")V",                                          FN_PTR(invalidateInstalledCode)},
   {CC"getJavaMirror",                                CC"("METASPACE_KLASS")"CLASS,                                     FN_PTR(getJavaMirror)},
-  {CC"setNodeClass",                                 CC"("CLASS NODE_CLASS")V",                                        FN_PTR(setNodeClass)},
   {CC"readUnsafeKlassPointer",                       CC"("OBJECT")J",                                                  FN_PTR(readUnsafeKlassPointer)},
   {CC"collectCounters",                              CC"()[J",                                                         FN_PTR(collectCounters)},
   {CC"getGPUs",                                      CC"()"STRING,                                                     FN_PTR(getGPUs)},
@@ -1093,7 +1110,7 @@
   {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 HS_RESOLVED_METHOD")"HS_STACK_FRAME_REF,  FN_PTR(getNextStackFrame)},
+  {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)},
 };
 
--- a/src/share/vm/graal/graalEnv.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalEnv.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalGlobals.hpp	Mon Apr 28 11:18:15 2014 +0200
@@ -52,6 +52,9 @@
   COMPILERGRAAL_PRESENT(product(bool, BootstrapGraal, true,                 \
           "Bootstrap Graal before running Java main method"))               \
                                                                             \
+  product(bool, ForceGraalInitialization, false,                            \
+          "Force VM to initialize the Compiler although not used")          \
+                                                                            \
   product(intx, TraceGraal, 0,                                              \
           "Trace level for Graal")                                          \
                                                                             \
@@ -88,6 +91,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Mon Apr 28 11:18:15 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;")                                                                        \
@@ -310,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
@@ -321,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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Mon Apr 28 11:18:15 2014 +0200
@@ -144,15 +144,13 @@
   }
 }
 
-void VMToCompiler::startCompiler(jboolean bootstrap_enabled, jboolean hosted_only) {
+void VMToCompiler::startCompiler(jboolean bootstrap_enabled) {
   JavaThread* THREAD = JavaThread::current();
   JavaValue result(T_VOID);
   JavaCallArguments args;
   args.push_oop(instance());
   args.push_int(bootstrap_enabled);
-  args.push_int(hosted_only);
-  TempNewSymbol bool_bool_void = SymbolTable::new_symbol("(ZZ)V", CHECK);
-  JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), bool_bool_void, &args, THREAD);
+  JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), vmSymbols::bool_void_signature(), &args, THREAD);
   check_pending_exception("Error while calling startCompiler");
 }
 
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Mon Apr 28 11:18:15 2014 +0200
@@ -66,8 +66,8 @@
   // public abstract void shutdownCompiler();
   static void shutdownCompiler();
   
-  // public abstract void startCompiler(boolean bootstrapEnabled, boolean hostedOnly);
-  static void startCompiler(jboolean bootstrap_enabled, jboolean hosted_only);
+  // public abstract void startCompiler(boolean bootstrapEnabled);
+  static void startCompiler(jboolean bootstrap_enabled);
   
   // public abstract void bootstrap();
   static void bootstrap();
--- a/src/share/vm/oops/instanceKlass.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/oops/instanceKlass.cpp	Mon Apr 28 11:18:15 2014 +0200
@@ -1201,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
 }
 
 
--- a/src/share/vm/prims/jni.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/prims/jni.cpp	Mon Apr 28 11:18:15 2014 +0200
@@ -5176,6 +5176,9 @@
 #ifdef GRAAL
     // GraalCompiler needs to have been created in compileBroker.cpp
     GraalCompiler* graal_compiler = GraalCompiler::instance();
+    if (ForceGraalInitialization && graal_compiler == NULL) {
+      graal_compiler = new GraalCompiler();
+    }
     if (graal_compiler != NULL) {
       graal_compiler->initialize();
     } else {
--- a/src/share/vm/runtime/deoptimization.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Mon Apr 28 11:18:15 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/gpu.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/runtime/gpu.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/runtime/gpu.hpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Mon Apr 28 11:18:15 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/runtime/safepoint.cpp	Mon Apr 28 11:18:15 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/thread.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/runtime/thread.cpp	Mon Apr 28 11:18:15 2014 +0200
@@ -1680,9 +1680,11 @@
   if (_thread_stat != NULL) delete _thread_stat;
 
 #ifdef GRAAL
-  if (GraalCounterSize > 0 && graal_counters_include(threadObj())) {
-    for (int i = 0; i < GraalCounterSize; i++) {
-      _graal_old_thread_counters[i] += _graal_counters[i];
+  if (GraalCounterSize > 0) {
+    if (graal_counters_include(threadObj())) {
+      for (int i = 0; i < GraalCounterSize; i++) {
+        _graal_old_thread_counters[i] += _graal_counters[i];
+      }
     }
     FREE_C_HEAP_ARRAY(jlong, _graal_counters, mtInternal);
   }
--- a/src/share/vm/runtime/vmStructs.cpp	Fri Apr 25 16:21:07 2014 +0200
+++ b/src/share/vm/runtime/vmStructs.cpp	Mon Apr 28 11:18:15 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/whitelist_baseline.txt	Mon Apr 28 11:18:15 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/whitelist_shortunittest.txt	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,1 @@
+com.oracle.graal.jtt.bytecode.*