changeset 11858:cdff87c89c5f

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 02 Oct 2013 13:28:17 +0200
parents 3aef4d88fbb9 (current diff) 04b039d82e86 (diff)
children ee88780346a4 952ecf32788a 9d1a5d61cc11
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MemoryMap.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryState.java
diffstat 107 files changed, 807 insertions(+), 729 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ArithmeticOperation.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ArithmeticOperation.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,9 +22,13 @@
  */
 package com.oracle.graal.api.code;
 
+import com.oracle.graal.api.meta.*;
+
 /**
  * An {@code ArithmeticOperation} is an operation that does primitive value arithmetic without side
  * effect.
  */
 public interface ArithmeticOperation {
+
+    Constant evalConst(Constant... inputs);
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Oct 02 13:28:17 2013 +0200
@@ -72,13 +72,6 @@
     ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor);
 
     /**
-     * Encodes a deoptimization action and a deoptimization reason in an integer value.
-     * 
-     * @return the encoded value as an integer
-     */
-    int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason);
-
-    /**
      * Determines if a {@link DataPatch} should be created for a given
      * {@linkplain Constant#getPrimitiveAnnotation() annotated} primitive constant that part of a
      * {@link CompilationResult}. A data patch is always created for an object constant.
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Wed Oct 02 13:28:17 2013 +0200
@@ -44,7 +44,6 @@
     private final BytecodePosition bytecodePosition;
     private final BitSet registerRefMap;
     private final BitSet frameRefMap;
-    private final short deoptimizationReason;
     private RegisterSaveLayout calleeSaveInfo;
 
     /**
@@ -55,11 +54,10 @@
      * @param registerRefMap the register map
      * @param frameRefMap the reference map for {@code frame}, which may be {@code null}
      */
-    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, short deoptimizationReason) {
+    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap) {
         this.bytecodePosition = codePos;
         this.registerRefMap = registerRefMap;
         this.frameRefMap = frameRefMap;
-        this.deoptimizationReason = deoptimizationReason;
     }
 
     /**
@@ -127,15 +125,6 @@
     }
 
     /**
-     * Identifies the reason in case a deoptimization happens at this program counter.
-     * 
-     * @return the reason of the deoptimization
-     */
-    public short getDeoptimizationReason() {
-        return deoptimizationReason;
-    }
-
-    /**
      * Sets the map from the registers (in the caller's frame) to the slots where they are saved in
      * the current frame.
      */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DelegatingCodeCacheProvider.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DelegatingCodeCacheProvider.java	Wed Oct 02 13:28:17 2013 +0200
@@ -58,10 +58,6 @@
         return delegate().lookupForeignCall(descriptor);
     }
 
-    public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
-        return delegate().encodeDeoptActionAndReason(action, reason);
-    }
-
     public boolean needsDataPatch(Constant constant) {
         return delegate().needsDataPatch(constant);
     }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java	Wed Oct 02 13:18:25 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.api.code;
-
-/**
- * Specifies the action that should be taken by the runtime in case a certain deoptimization is
- * triggered.
- */
-public enum DeoptimizationAction {
-    /**
-     * Do not invalidate the machine code. This is typically used when deoptimizing at a point where
-     * it's highly likely nothing will change the likelihood of the deoptimization happening again.
-     * For example, a compiled array allocation where the size is negative.
-     */
-    None(false),
-
-    /**
-     * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is
-     * triggered too often.
-     */
-    RecompileIfTooManyDeopts(true),
-
-    /**
-     * Invalidate the machine code and reset the profiling information.
-     */
-    InvalidateReprofile(true),
-
-    /**
-     * Invalidate the machine code and immediately schedule a recompilation. This is typically used
-     * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not
-     * required to determine that the deoptimization will not re-occur.
-     */
-    InvalidateRecompile(true),
-
-    /**
-     * Invalidate the machine code and stop compiling the outermost method of this compilation.
-     */
-    InvalidateStopCompiling(true);
-
-    private final boolean invalidatesCompilation;
-
-    private DeoptimizationAction(boolean invalidatesCompilation) {
-        this.invalidatesCompilation = invalidatesCompilation;
-    }
-
-    public boolean doesInvalidateCompilation() {
-        return invalidatesCompilation;
-    }
-
-}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Wed Oct 02 13:28:17 2013 +0200
@@ -36,11 +36,11 @@
 
     public static final int MAX_CACHE_SIZE = 1 << 15;
 
-    private List<DeoptimizationReason> speculations = new ArrayList<>();
+    private List<Object> speculations = new ArrayList<>();
     private boolean[] map = new boolean[10];
-    private Set<DeoptimizationReason> snapshot = new HashSet<>();
+    private Set<Object> snapshot = new HashSet<>();
 
-    public short addSpeculation(DeoptimizationReason reason) {
+    private short addSpeculation(Object reason) {
         short index = (short) speculations.indexOf(reason);
         if (index != -1) {
             // Nothing to add, reason already registered.
@@ -68,7 +68,10 @@
         }
     }
 
-    public boolean maySpeculate(DeoptimizationReason reason) {
-        return !snapshot.contains(reason);
+    public Constant maySpeculate(Object reason) {
+        if (snapshot.contains(reason)) {
+            return null;
+        }
+        return Constant.forShort(addSpeculation(reason));
     }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DelegatingMetaAccessProvider.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DelegatingMetaAccessProvider.java	Wed Oct 02 13:28:17 2013 +0200
@@ -86,4 +86,8 @@
     public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
         return delegate.canDeoptimize(descriptor);
     }
+
+    public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
+        return delegate().encodeDeoptActionAndReason(action, reason);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationAction.java	Wed Oct 02 13:28:17 2013 +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.api.meta;
+
+/**
+ * Specifies the action that should be taken by the runtime in case a certain deoptimization is
+ * triggered.
+ */
+public enum DeoptimizationAction {
+    /**
+     * Do not invalidate the machine code. This is typically used when deoptimizing at a point where
+     * it's highly likely nothing will change the likelihood of the deoptimization happening again.
+     * For example, a compiled array allocation where the size is negative.
+     */
+    None(false),
+
+    /**
+     * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is
+     * triggered too often.
+     */
+    RecompileIfTooManyDeopts(true),
+
+    /**
+     * Invalidate the machine code and reset the profiling information.
+     */
+    InvalidateReprofile(true),
+
+    /**
+     * Invalidate the machine code and immediately schedule a recompilation. This is typically used
+     * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not
+     * required to determine that the deoptimization will not re-occur.
+     */
+    InvalidateRecompile(true),
+
+    /**
+     * Invalidate the machine code and stop compiling the outermost method of this compilation.
+     */
+    InvalidateStopCompiling(true);
+
+    private final boolean invalidatesCompilation;
+
+    private DeoptimizationAction(boolean invalidatesCompilation) {
+        this.invalidatesCompilation = invalidatesCompilation;
+    }
+
+    public boolean doesInvalidateCompilation() {
+        return invalidatesCompilation;
+    }
+
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MemoryMap.java	Wed Oct 02 13:18:25 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +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.api.meta;
-
-public interface MemoryMap<T> {
-
-    T getLastLocationAccess(LocationIdentity locationIdentity);
-}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Wed Oct 02 13:28:17 2013 +0200
@@ -113,4 +113,11 @@
      * Determines if deoptimization can occur during a given foreign call.
      */
     boolean canDeoptimize(ForeignCallDescriptor descriptor);
+
+    /**
+     * Encodes a deoptimization action and a deoptimization reason in an integer value.
+     * 
+     * @return the encoded value as an integer
+     */
+    Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason);
 }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Oct 02 13:28:17 2013 +0200
@@ -890,6 +890,6 @@
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        append(new InfopointOp(stateFor(i.getState(), DeoptimizationReason.None), i.reason));
+        append(new InfopointOp(stateFor(i.getState()), i.reason));
     }
 }
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Oct 02 13:28:17 2013 +0200
@@ -579,7 +579,7 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Wed Oct 02 13:28:17 2013 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.api.runtime.Graal;
 import com.oracle.graal.compiler.GraalCompiler;
 import com.oracle.graal.compiler.ptx.PTXBackend;
+import com.oracle.graal.compiler.ptx.PTXTargetMethodAssembler;
 import com.oracle.graal.compiler.test.GraalCompilerTest;
 import com.oracle.graal.debug.Debug;
 import com.oracle.graal.hotspot.meta.HotSpotNmethod;
@@ -138,6 +139,11 @@
             }
             Object r;
             if (dimensionX != 1 || dimensionY != 1 || dimensionZ != 1) {
+                /*
+                 * for now assert that the warp array block is no larger than the number of physical gpu cores.
+                 */
+                assert dimensionX * dimensionY * dimensionZ < PTXTargetMethodAssembler.getAvailableProcessors();
+
                 r = ((HotSpotNmethod) installedCode).executeParallel(dimensionX, dimensionY, dimensionZ, executeArgs);
             } else {
                 r = installedCode.executeVarargs(executeArgs);
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Oct 02 13:28:17 2013 +0200
@@ -673,7 +673,7 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java	Wed Oct 02 13:28:17 2013 +0200
@@ -36,6 +36,12 @@
     private static CompilerToGPU toGPU = HotSpotGraalRuntime.graalRuntime().getCompilerToGPU();
     private static boolean validDevice = toGPU.deviceInit();
 
+    private static final int totalProcessors = (validDevice ? toGPU.availableProcessors() : 0);
+
+    public static int getAvailableProcessors() {
+        return totalProcessors;
+    }
+
     // detach ??
 
     public PTXTargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap,
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Oct 02 13:28:17 2013 +0200
@@ -837,7 +837,7 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Oct 02 13:28:17 2013 +0200
@@ -229,7 +229,7 @@
                 List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, nodeProbabilities);
                 List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, nodeProbabilities);
 
-                LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder, speculationLog);
+                LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder);
                 Debug.dump(lir, "After linear scan order");
                 return lir;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Oct 02 13:28:17 2013 +0200
@@ -48,7 +48,7 @@
     protected HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>();
     protected IdentityHashMap<VirtualObjectNode, EscapeObjectState> objectStates = new IdentityHashMap<>();
 
-    public LIRFrameState build(FrameState topState, short reason, LabelRef exceptionEdge) {
+    public LIRFrameState build(FrameState topState, LabelRef exceptionEdge) {
         assert virtualObjects.size() == 0;
         assert objectStates.size() == 0;
 
@@ -101,11 +101,11 @@
         }
         objectStates.clear();
 
-        return newLIRFrameState(reason, exceptionEdge, frame, virtualObjectsArray);
+        return newLIRFrameState(exceptionEdge, frame, virtualObjectsArray);
     }
 
-    protected LIRFrameState newLIRFrameState(short reason, LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
-        return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason);
+    protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
+        return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge);
     }
 
     protected BytecodeFrame computeFrameForState(FrameState state) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Oct 02 13:28:17 2013 +0200
@@ -228,26 +228,26 @@
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateFor(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason());
+        return stateFor(deopt.getDeoptimizationState());
     }
 
     public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason(), exceptionEdge);
+        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), exceptionEdge);
     }
 
-    public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) {
-        return stateForWithExceptionEdge(state, reason, null);
+    public LIRFrameState stateFor(FrameState state) {
+        return stateForWithExceptionEdge(state, null);
     }
 
-    public LIRFrameState stateForWithExceptionEdge(FrameState state, DeoptimizationReason reason, LabelRef exceptionEdge) {
+    public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) {
         if (needOnlyOopMaps()) {
-            return new LIRFrameState(null, null, null, (short) -1);
+            return new LIRFrameState(null, null, null);
         }
         assert state != null;
-        return debugInfoBuilder.build(state, lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge);
+        return debugInfoBuilder.build(state, exceptionEdge);
     }
 
     /**
@@ -619,10 +619,10 @@
         LIRFrameState state = null;
         if (linkage.canDeoptimize()) {
             if (info != null) {
-                state = stateFor(info.getDeoptimizationState(), info.getDeoptimizationReason());
+                state = stateFor(info.getDeoptimizationState());
             } else {
                 assert needOnlyOopMaps();
-                state = new LIRFrameState(null, null, null, (short) -1);
+                state = new LIRFrameState(null, null, null);
             }
         }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Wed Oct 02 13:28:17 2013 +0200
@@ -23,12 +23,8 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
-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.*;
@@ -36,21 +32,14 @@
 @Opcode("DEOPT")
 final class AMD64DeoptimizeOp extends AMD64LIRInstruction {
 
-    private DeoptimizationAction action;
-    private DeoptimizationReason reason;
     @State private LIRFrameState info;
 
-    AMD64DeoptimizeOp(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
-        this.action = action;
-        this.reason = reason;
+    AMD64DeoptimizeOp(LIRFrameState info) {
         this.info = info;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        HotSpotGraalRuntime runtime = graalRuntime();
-        Register thread = runtime.getRuntime().threadRegister();
-        masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason));
         AMD64Call.directCall(tasm, masm, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP), null, false, info);
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Wed Oct 02 13:28:17 2013 +0200
@@ -23,12 +23,8 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
-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.*;
@@ -39,21 +35,9 @@
 @Opcode("DEOPT_CALLER")
 final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp {
 
-    private final DeoptimizationAction action;
-    private final DeoptimizationReason reason;
-
-    AMD64HotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) {
-        this.action = action;
-        this.reason = reason;
-    }
-
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         leaveFrameAndRestoreRbp(tasm, masm);
-
-        HotSpotGraalRuntime runtime = graalRuntime();
-        Register thread = runtime.getRuntime().threadRegister();
-        masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason));
         AMD64Call.directJmp(tasm, masm, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP));
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Oct 02 13:28:17 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -362,14 +363,29 @@
         append(new AMD64HotSpotUnwindOp(exceptionParameter));
     }
 
+    private void moveDeoptimizationActionAndReasonToThread(Value actionAndReason) {
+        int pendingDeoptimizationOffset = graalRuntime().getConfig().pendingDeoptimizationOffset;
+        RegisterValue thread = runtime().threadRegister().asValue(HotSpotGraalRuntime.wordKind());
+        AMD64AddressValue pendingDeoptAddress = new AMD64AddressValue(actionAndReason.getKind(), thread, pendingDeoptimizationOffset);
+        if (actionAndReason instanceof Constant && !runtime.needsDataPatch((Constant) actionAndReason)) {
+            Constant constantActionAndReason = (Constant) actionAndReason;
+            assert !runtime.needsDataPatch(constantActionAndReason);
+            append(new StoreConstantOp(constantActionAndReason.getKind(), pendingDeoptAddress, constantActionAndReason, null));
+        } else {
+            append(new StoreOp(actionAndReason.getKind(), pendingDeoptAddress, load(actionAndReason), null));
+        }
+    }
+
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
-        append(new AMD64DeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting)));
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
+        moveDeoptimizationActionAndReasonToThread(actionAndReason);
+        append(new AMD64DeoptimizeOp(state(deopting)));
     }
 
     @Override
     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        append(new AMD64HotSpotDeoptimizeCallerOp(action, reason));
+        moveDeoptimizationActionAndReasonToThread(runtime.encodeDeoptActionAndReason(action, reason));
+        append(new AMD64HotSpotDeoptimizeCallerOp());
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,39 +22,24 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.sparc.SPARC.*;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.asm.*;
 
 @Opcode("DEOPT")
 final class SPARCDeoptimizeOp extends SPARCLIRInstruction {
 
-    private DeoptimizationAction action;
-    private DeoptimizationReason reason;
     @State private LIRFrameState info;
 
-    SPARCDeoptimizeOp(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
-        this.action = action;
-        this.reason = reason;
+    SPARCDeoptimizeOp(LIRFrameState info) {
         this.info = info;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-        HotSpotGraalRuntime runtime = graalRuntime();
-        Register thread = runtime.getRuntime().threadRegister();
-        Register scratch = g3;
-        new Mov(tasm.runtime.encodeDeoptActionAndReason(action, reason), scratch).emit(masm);
-        new Stw(scratch, new SPARCAddress(thread, runtime.getConfig().pendingDeoptimizationOffset)).emit(masm);
         // TODO the patched call address looks odd (and is invalid) compared to other runtime calls:
 // 0xffffffff749bb5fc: call 0xffffffff415a720c ; {runtime_call}
 // [Exception Handler]
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,18 +22,14 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.sparc.SPARC.*;
-import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.asm.*;
 
 /**
  * Removes the current frame and tail calls the uncommon trap routine.
@@ -41,14 +37,6 @@
 @Opcode("DEOPT_CALLER")
 final class SPARCHotSpotDeoptimizeCallerOp extends SPARCHotSpotEpilogueOp {
 
-    private final DeoptimizationAction action;
-    private final DeoptimizationReason reason;
-
-    SPARCHotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) {
-        this.action = action;
-        this.reason = reason;
-    }
-
     @Override
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         leaveFrame(tasm);
@@ -58,14 +46,7 @@
 // final boolean isStub = true;
 // HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub);
 // frameContext.enter(tasm);
-
-        HotSpotGraalRuntime runtime = graalRuntime();
-        Register thread = runtime.getRuntime().threadRegister();
-
-        Register scratch = g5;
-        new Mov(tasm.runtime.encodeDeoptActionAndReason(action, reason), scratch).emit(masm);
-        new Stw(scratch, new SPARCAddress(thread, runtime.getConfig().pendingDeoptimizationOffset)).emit(masm);
-
+        Register scratch = g3;
         SPARCCall.indirectJmp(tasm, masm, scratch, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP));
 
 // frameContext.leave(tasm);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Oct 02 13:28:17 2013 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import java.lang.reflect.*;
@@ -183,14 +184,23 @@
         append(new SPARCHotSpotUnwindOp(exceptionParameter));
     }
 
+    private void moveDeoptimizationActionAndReasonToThread(Value actionAndReason) {
+        int pendingDeoptimizationOffset = graalRuntime().getConfig().pendingDeoptimizationOffset;
+        RegisterValue thread = runtime().threadRegister().asValue(HotSpotGraalRuntime.wordKind());
+        SPARCAddressValue pendingDeoptAddress = new SPARCAddressValue(actionAndReason.getKind(), thread, pendingDeoptimizationOffset);
+        append(new StoreOp(actionAndReason.getKind(), pendingDeoptAddress, emitMove(actionAndReason), null));
+    }
+
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
-        append(new SPARCDeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting)));
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
+        moveDeoptimizationActionAndReasonToThread(actionAndReason);
+        append(new SPARCDeoptimizeOp(state(deopting)));
     }
 
     @Override
     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        append(new SPARCHotSpotDeoptimizeCallerOp(action, reason));
+        moveDeoptimizationActionAndReasonToThread(runtime.encodeDeoptActionAndReason(action, reason));
+        append(new SPARCHotSpotDeoptimizeCallerOp());
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Wed Oct 02 13:28:17 2013 +0200
@@ -61,7 +61,7 @@
     }
 
     @Override
-    protected LIRFrameState newLIRFrameState(short reason, LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
-        return new HotSpotLIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason);
+    protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
+        return new HotSpotLIRFrameState(frame, virtualObjectsArray, exceptionEdge);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Wed Oct 02 13:28:17 2013 +0200
@@ -34,8 +34,8 @@
  */
 class HotSpotLIRFrameState extends LIRFrameState {
 
-    public HotSpotLIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge, short deoptimizationReason) {
-        super(topFrame, virtualObjects, exceptionEdge, deoptimizationReason);
+    public HotSpotLIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) {
+        super(topFrame, virtualObjects, exceptionEdge);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java	Wed Oct 02 13:28:17 2013 +0200
@@ -45,6 +45,8 @@
      */
     boolean deviceDetach();
 
+    int availableProcessors();
+
     /**
      * Attempts to generate and return a bound function to the
      * loaded method kernel on the GPU.
@@ -56,6 +58,7 @@
 
     Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
+
     Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ,
                                         Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java	Wed Oct 02 13:28:17 2013 +0200
@@ -38,8 +38,12 @@
 
     public native boolean deviceDetach();
 
-    public native Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    public native int availableProcessors();
+
+    public native Object executeExternalMethodVarargs(Object[] args,
+                                                      HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
     public native Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ,
-                                                      Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+                                                      Object[] args,
+                                                      HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Oct 02 13:28:17 2013 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.hotspot.meta;
 
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
 import static com.oracle.graal.api.code.MemoryBarriers.*;
+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.graph.UnsafeAccess.*;
@@ -1082,13 +1082,13 @@
     }
 
     @Override
-    public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
+    public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
         final int actionShift = 0;
         final int reasonShift = 3;
 
         int actionValue = convertDeoptAction(action);
         int reasonValue = convertDeoptReason(reason);
-        return (~(((reasonValue) << reasonShift) + ((actionValue) << actionShift)));
+        return Constant.forInt(~(((reasonValue) << reasonShift) + ((actionValue) << actionShift)));
     }
 
     public int convertDeoptAction(DeoptimizationAction action) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -36,9 +35,4 @@
     public boolean canDeoptimize() {
         return true;
     }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
@@ -66,11 +65,6 @@
         deoptimizationState = state;
     }
 
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return DeoptimizationReason.NullCheckException;
-    }
-
     public FrameState getState() {
         return deoptimizationState;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Wed Oct 02 13:28:17 2013 +0200
@@ -58,7 +58,6 @@
 public class NewObjectSnippets implements Snippets {
 
     public static final LocationIdentity INIT_LOCATION = new NamedLocationIdentity("Initialization");
-    public static final LocationIdentity ARRAY_LENGTH_LOCATION = new NamedLocationIdentity("ArrayLength");
 
     @Snippet
     public static Word allocate(int size) {
@@ -222,7 +221,7 @@
      * Formats some allocated memory with an object header and zeroes out the rest.
      */
     public static Object formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
-        memory.writeInt(arrayLengthOffset(), length, ARRAY_LENGTH_LOCATION);
+        memory.writeInt(arrayLengthOffset(), length, INIT_LOCATION);
         /*
          * store hub last as the concurrent garbage collectors assume length is valid if hub field
          * is not null
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Wed Oct 02 13:28:17 2013 +0200
@@ -29,7 +29,6 @@
 
 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.nodes.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.nodes.CStringNode.*;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.java;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
 import static com.oracle.graal.api.code.TypeCheckHints.*;
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
@@ -50,7 +50,6 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.util.*;
 
 /**
  * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
@@ -1693,20 +1692,7 @@
     }
 
     private static boolean isBlockEnd(Node n) {
-        return trueSuccessorCount(n) > 1 || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof DeoptimizeNode;
-    }
-
-    private static int trueSuccessorCount(Node n) {
-        if (n == null) {
-            return 0;
-        }
-        int i = 0;
-        for (Node s : n.successors()) {
-            if (Util.isFixed(s)) {
-                i++;
-            }
-        }
-        return i;
+        return n instanceof ControlSplitNode || n instanceof ControlSinkNode;
     }
 
     private void iterateBytecodesForBlock(Block block) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Wed Oct 02 13:28:17 2013 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -71,22 +70,15 @@
 
     private boolean hasArgInCallerFrame;
 
-    private final SpeculationLog speculationLog;
-
     /**
      * Creates a new LIR instance for the specified compilation.
      */
-    public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder, SpeculationLog speculationLog) {
+    public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
         this.cfg = cfg;
         this.blockToNodesMap = blockToNodesMap;
         this.codeEmittingOrder = codeEmittingOrder;
         this.linearScanOrder = linearScanOrder;
         this.lirInstructions = new BlockMap<>(cfg);
-        this.speculationLog = speculationLog;
-    }
-
-    public SpeculationLog getDeoptimizationReasons() {
-        return speculationLog;
     }
 
     /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Oct 02 13:28:17 2013 +0200
@@ -42,13 +42,11 @@
     private final VirtualObject[] virtualObjects;
     public final LabelRef exceptionEdge;
     private DebugInfo debugInfo;
-    private final short deoptimizationReason;
 
-    public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge, short deoptimizationReason) {
+    public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) {
         this.topFrame = topFrame;
         this.virtualObjects = virtualObjects;
         this.exceptionEdge = exceptionEdge;
-        this.deoptimizationReason = deoptimizationReason;
     }
 
     public boolean hasDebugInfo() {
@@ -112,7 +110,7 @@
     }
 
     public void finish(BitSet registerRefMap, BitSet frameRefMap) {
-        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap, deoptimizationReason);
+        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap);
     }
 
     @Override
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Oct 02 13:28:17 2013 +0200
@@ -24,7 +24,6 @@
 
 import static com.oracle.graal.nodes.calc.IntegerArithmeticNode.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.InductionVariable.Direction;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Wed Oct 02 13:28:17 2013 +0200
@@ -48,11 +48,11 @@
             return false;
         }
         CountedLoopInfo counted = loop.counted();
-        long exactTrips = counted.constantMaxTripCount();
+        long maxTrips = counted.constantMaxTripCount();
         int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? ExactFullUnrollMaxNodes.getValue() : FullUnrollMaxNodes.getValue();
         maxNodes = Math.min(maxNodes, MaximumDesiredSize.getValue() - loop.loopBegin().graph().getNodeCount());
         int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
-        return size * exactTrips <= maxNodes;
+        return size * maxTrips <= maxNodes;
     }
 
     public static boolean shouldTryUnswitch(LoopEx loop) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * This node represents an unconditional explicit request for immediate deoptimization.
+ * 
+ * After this node, execution will continue using a fallback execution engine (such as an
+ * interpreter) at the position described by the {@link #getDeoptimizationState() deoptimization
+ * state}.
+ * 
+ */
+@NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
+public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode {
+
+    @Input private FrameState deoptState;
+
+    public AbstractDeoptimizeNode() {
+        super(StampFactory.forVoid());
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
+        deoptState = f;
+    }
+
+    public FrameState getState() {
+        return deoptState;
+    }
+
+    public abstract ValueNode getActionAndReason(MetaAccessProvider runtime);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,30 +22,15 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
-/**
- * This node represents an unconditional explicit request for immediate deoptimization.
- * 
- * After this node, execution will continue using a fallback execution engine (such as an
- * interpreter) at the position described by the {@link #getDeoptimizationState() deoptimization
- * state}.
- * 
- */
-@NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public class DeoptimizeNode extends ControlSinkNode implements IterableNodeType, LIRLowerable, DeoptimizingNode {
-
-    @Input private FrameState deoptState;
+public class DeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable {
 
     private final DeoptimizationAction action;
     private final DeoptimizationReason reason;
 
     public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) {
-        super(StampFactory.forVoid());
         this.action = action;
         this.reason = reason;
     }
@@ -60,34 +45,14 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimize(action, this);
+        gen.emitDeoptimize(gen.getRuntime().encodeDeoptActionAndReason(action, reason), this);
+    }
+
+    @Override
+    public ValueNode getActionAndReason(MetaAccessProvider runtime) {
+        return ConstantNode.forConstant(runtime.encodeDeoptActionAndReason(action, reason), runtime, graph());
     }
 
     @NodeIntrinsic
     public static native void deopt(@ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter DeoptimizationReason reason);
-
-    @Override
-    public boolean canDeoptimize() {
-        return true;
-    }
-
-    @Override
-    public FrameState getDeoptimizationState() {
-        return deoptState;
-    }
-
-    @Override
-    public void setDeoptimizationState(FrameState f) {
-        updateUsages(deoptState, f);
-        deoptState = f;
-    }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return reason;
-    }
-
-    public FrameState getState() {
-        return deoptState;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -46,13 +45,4 @@
      * @param state the FrameState which represents the deoptimization information
      */
     void setDeoptimizationState(FrameState state);
-
-    /**
-     * Returns the reason for deoptimization triggered by this node. If deoptimization at this point
-     * can happen for external reasons (i.e. not explicitely triggered by this node) this method can
-     * return null.
-     * 
-     * @return the reason for deoptimization triggered by this node.
-     */
-    DeoptimizationReason getDeoptimizationReason();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.spi.*;
+
+public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable {
+    @Input private ValueNode actionAndReason;
+
+    public DynamicDeoptimizeNode(ValueNode actionAndReason) {
+        this.actionAndReason = actionAndReason;
+    }
+
+    public ValueNode getActionAndReason() {
+        return actionAndReason;
+    }
+
+    @Override
+    public ValueNode getActionAndReason(MetaAccessProvider runtime) {
+        return getActionAndReason();
+    }
+
+    public void generate(LIRGeneratorTool generator) {
+        generator.emitDeoptimize(generator.operand(actionAndReason), this);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
@@ -136,9 +135,4 @@
     public boolean canDeoptimize() {
         return true;
     }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return reason;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -174,11 +174,6 @@
     }
 
     @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return null;
-    }
-
-    @Override
     public FrameState getDeoptimizationState() {
         if (deoptState == null) {
             FrameState stateDuring = stateDuring();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -219,11 +219,6 @@
     }
 
     @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return null;
-    }
-
-    @Override
     public FrameState getDeoptimizationState() {
         if (deoptState == null) {
             FrameState stateDuring = stateDuring();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Wed Oct 02 13:28:17 2013 +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.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
+
+public abstract class MemoryMapNode extends FloatingNode {
+
+    public MemoryMapNode() {
+        super(StampFactory.forVoid());
+    }
+
+    public abstract Node getLastLocationAccess(LocationIdentity locationIdentity);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryState.java	Wed Oct 02 13:18:25 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +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;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-
-public class MemoryState extends VirtualState {
-
-    private MemoryMap<Node> memoryMap;
-    @Input private Node object;
-
-    public MemoryState(MemoryMap<Node> memoryMap, FixedNode object) {
-        this.memoryMap = memoryMap;
-        this.object = object;
-    }
-
-    public Node object() {
-        return object;
-    }
-
-    public MemoryMap<Node> getMemoryMap() {
-        return memoryMap;
-    }
-
-    @Override
-    public VirtualState duplicateWithVirtualState() {
-        throw new GraalInternalError("should not reach here");
-    }
-
-    @Override
-    public void applyToNonVirtual(NodeClosure<? super ValueNode> closure) {
-        throw new GraalInternalError("should not reach here");
-    }
-
-    @Override
-    public void applyToVirtual(VirtualClosure closure) {
-        throw new GraalInternalError("should not reach here");
-    }
-
-    @Override
-    public boolean isPartOfThisState(VirtualState state) {
-        throw new GraalInternalError("should not reach here");
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -28,6 +28,7 @@
 public final class ReturnNode extends ControlSinkNode implements LIRLowerable {
 
     @Input private ValueNode result;
+    @Input private MemoryMapNode memoryMap;
 
     public ValueNode result() {
         return result;
@@ -40,8 +41,13 @@
      *            void return
      */
     public ReturnNode(ValueNode result) {
+        this(result, null);
+    }
+
+    public ReturnNode(ValueNode result, MemoryMapNode memoryMap) {
         super(StampFactory.forVoid());
         this.result = result;
+        this.memoryMap = memoryMap;
     }
 
     @Override
@@ -53,4 +59,13 @@
     public void generate(LIRGeneratorTool gen) {
         gen.visitReturn(this);
     }
+
+    public void setMemoryMap(MemoryMapNode memoryMap) {
+        updateUsages(this.memoryMap, memoryMap);
+        this.memoryMap = memoryMap;
+    }
+
+    public MemoryMapNode getMemoryMap() {
+        return memoryMap;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -41,11 +40,6 @@
     }
 
     @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return null;
-    }
-
-    @Override
     public boolean canDeoptimize() {
         return true;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -41,6 +41,12 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        return Constant.forIntegerKind(kind(), inputs[0].asLong() & inputs[1].asLong(), null);
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return x();
@@ -49,12 +55,7 @@
             return graph().unique(new AndNode(kind(), y(), x()));
         }
         if (x().isConstant()) {
-            if (kind() == Kind.Int) {
-                return ConstantNode.forInt(x().asConstant().asInt() & y().asConstant().asInt(), graph());
-            } else {
-                assert kind() == Kind.Long;
-                return ConstantNode.forLong(x().asConstant().asLong() & y().asConstant().asLong(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         } else if (y().isConstant()) {
             if (kind() == Kind.Int) {
                 int c = y().asConstant().asInt();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -150,52 +150,59 @@
         this.value = value;
     }
 
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 1;
+        Constant c = inputs[0];
+        switch (opcode) {
+            case I2L:
+                return Constant.forLong(c.asInt());
+            case L2I:
+                return Constant.forInt((int) c.asLong());
+            case I2B:
+                return Constant.forByte((byte) c.asInt());
+            case I2C:
+                return Constant.forChar((char) c.asInt());
+            case I2S:
+                return Constant.forShort((short) c.asInt());
+            case F2D:
+                return Constant.forDouble(c.asFloat());
+            case D2F:
+                return Constant.forFloat((float) c.asDouble());
+            case I2F:
+                return Constant.forFloat(c.asInt());
+            case I2D:
+                return Constant.forDouble(c.asInt());
+            case F2I:
+                return Constant.forInt((int) c.asFloat());
+            case D2I:
+                return Constant.forInt((int) c.asDouble());
+            case L2F:
+                return Constant.forFloat(c.asLong());
+            case L2D:
+                return Constant.forDouble(c.asLong());
+            case F2L:
+                return Constant.forLong((long) c.asFloat());
+            case D2L:
+                return Constant.forLong((long) c.asDouble());
+            case UNSIGNED_I2L:
+                return Constant.forLong(c.asInt() & 0xffffffffL);
+            case MOV_I2F:
+                return Constant.forFloat(java.lang.Float.intBitsToFloat(c.asInt()));
+            case MOV_L2D:
+                return Constant.forDouble(java.lang.Double.longBitsToDouble(c.asLong()));
+            case MOV_F2I:
+                return Constant.forInt(java.lang.Float.floatToRawIntBits(c.asFloat()));
+            case MOV_D2L:
+                return Constant.forLong(java.lang.Double.doubleToRawLongBits(c.asDouble()));
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (value instanceof ConstantNode) {
-            Constant c = ((ConstantNode) value).asConstant();
-            switch (opcode) {
-                case I2L:
-                    return ConstantNode.forLong(c.asInt(), graph());
-                case L2I:
-                    return ConstantNode.forInt((int) c.asLong(), graph());
-                case I2B:
-                    return ConstantNode.forByte((byte) c.asInt(), graph());
-                case I2C:
-                    return ConstantNode.forChar((char) c.asInt(), graph());
-                case I2S:
-                    return ConstantNode.forShort((short) c.asInt(), graph());
-                case F2D:
-                    return ConstantNode.forDouble(c.asFloat(), graph());
-                case D2F:
-                    return ConstantNode.forFloat((float) c.asDouble(), graph());
-                case I2F:
-                    return ConstantNode.forFloat(c.asInt(), graph());
-                case I2D:
-                    return ConstantNode.forDouble(c.asInt(), graph());
-                case F2I:
-                    return ConstantNode.forInt((int) c.asFloat(), graph());
-                case D2I:
-                    return ConstantNode.forInt((int) c.asDouble(), graph());
-                case L2F:
-                    return ConstantNode.forFloat(c.asLong(), graph());
-                case L2D:
-                    return ConstantNode.forDouble(c.asLong(), graph());
-                case F2L:
-                    return ConstantNode.forLong((long) c.asFloat(), graph());
-                case D2L:
-                    return ConstantNode.forLong((long) c.asDouble(), graph());
-                case UNSIGNED_I2L:
-                    return ConstantNode.forLong(c.asInt() & 0xffffffffL, graph());
-                case MOV_I2F:
-                    return ConstantNode.forFloat(java.lang.Float.intBitsToFloat(c.asInt()), graph());
-                case MOV_L2D:
-                    return ConstantNode.forDouble(java.lang.Double.longBitsToDouble(c.asLong()), graph());
-                case MOV_F2I:
-                    return ConstantNode.forInt(java.lang.Float.floatToRawIntBits(c.asFloat()), graph());
-                case MOV_D2L:
-                    return ConstantNode.forLong(java.lang.Double.doubleToRawLongBits(c.asDouble()), graph());
-            }
+        if (value.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(value.asConstant()), graph());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -44,9 +44,4 @@
         this.x = x;
         this.y = y;
     }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return DeoptimizationReason.ArithmeticException;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -34,18 +34,23 @@
         super(kind, x, y, isStrictFP);
     }
 
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        if (kind() == Kind.Float) {
+            return Constant.forFloat(x().asConstant().asFloat() + y().asConstant().asFloat());
+        } else {
+            assert kind() == Kind.Double;
+            return Constant.forDouble(x().asConstant().asDouble() + y().asConstant().asDouble());
+        }
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) {
             return graph().unique(new FloatAddNode(kind(), y(), x(), isStrictFP()));
         }
         if (x().isConstant()) {
-            if (kind() == Kind.Float) {
-                return ConstantNode.forFloat(x().asConstant().asFloat() + y().asConstant().asFloat(), graph());
-            } else {
-                assert kind() == Kind.Double;
-                return ConstantNode.forDouble(x().asConstant().asDouble() + y().asConstant().asDouble(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         } else if (y().isConstant()) {
             if (kind() == Kind.Float) {
                 float c = y().asConstant().asFloat();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -34,19 +34,20 @@
         super(kind, x, y, isStrictFP);
     }
 
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        if (kind() == Kind.Float) {
+            return Constant.forFloat(x().asConstant().asFloat() / y().asConstant().asFloat());
+        } else {
+            assert kind() == Kind.Double;
+            return Constant.forDouble(x().asConstant().asDouble() / y().asConstant().asDouble());
+        }
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && y().isConstant()) {
-            if (kind() == Kind.Float) {
-                if (y().asConstant().asFloat() != 0) {
-                    return ConstantNode.forFloat(x().asConstant().asFloat() / y().asConstant().asFloat(), graph());
-                }
-            } else {
-                assert kind() == Kind.Double;
-                if (y().asConstant().asDouble() != 0) {
-                    return ConstantNode.forDouble(x().asConstant().asDouble() / y().asConstant().asDouble(), graph());
-                }
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -34,18 +34,23 @@
         super(kind, x, y, isStrictFP);
     }
 
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        if (kind() == Kind.Float) {
+            return Constant.forFloat(x().asConstant().asFloat() * y().asConstant().asFloat());
+        } else {
+            assert kind() == Kind.Double;
+            return Constant.forDouble(x().asConstant().asDouble() * y().asConstant().asDouble());
+        }
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) {
             return graph().unique(new FloatMulNode(kind(), y(), x(), isStrictFP()));
         }
         if (x().isConstant()) {
-            if (kind() == Kind.Float) {
-                return ConstantNode.forFloat(x().asConstant().asFloat() * y().asConstant().asFloat(), graph());
-            } else {
-                assert kind() == Kind.Double;
-                return ConstantNode.forDouble(x().asConstant().asDouble() * y().asConstant().asDouble(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -34,15 +34,20 @@
         super(kind, x, y, isStrictFP);
     }
 
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        if (kind() == Kind.Float) {
+            return Constant.forFloat(x().asConstant().asFloat() % y().asConstant().asFloat());
+        } else {
+            assert kind() == Kind.Double;
+            return Constant.forDouble(x().asConstant().asDouble() % y().asConstant().asDouble());
+        }
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && y().isConstant()) {
-            if (kind() == Kind.Float) {
-                return ConstantNode.forFloat(x().asConstant().asFloat() % y().asConstant().asFloat(), graph());
-            } else {
-                assert kind() == Kind.Double;
-                return ConstantNode.forDouble(x().asConstant().asDouble() % y().asConstant().asDouble(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -34,18 +34,23 @@
         super(kind, x, y, isStrictFP);
     }
 
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        if (kind() == Kind.Float) {
+            return Constant.forFloat(x().asConstant().asFloat() - y().asConstant().asFloat());
+        } else {
+            assert kind() == Kind.Double;
+            return Constant.forDouble(x().asConstant().asDouble() - y().asConstant().asDouble());
+        }
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forFloatingKind(kind(), 0.0f, graph());
         }
         if (x().isConstant() && y().isConstant()) {
-            if (kind() == Kind.Float) {
-                return ConstantNode.forFloat(x().asConstant().asFloat() - y().asConstant().asFloat(), graph());
-            } else {
-                assert kind() == Kind.Double;
-                return ConstantNode.forDouble(x().asConstant().asDouble() - y().asConstant().asDouble(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         } else if (y().isConstant()) {
             if (kind() == Kind.Float) {
                 float c = y().asConstant().asFloat();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -41,6 +41,12 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        return Constant.forIntegerKind(kind(), inputs[0].asLong() + inputs[1].asLong(), null);
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) {
             return graph().unique(new IntegerAddNode(kind(), y(), x()));
@@ -60,12 +66,7 @@
             }
         }
         if (x().isConstant()) {
-            if (kind() == Kind.Int) {
-                return ConstantNode.forInt(x().asConstant().asInt() + y().asConstant().asInt(), graph());
-            } else {
-                assert kind() == Kind.Long;
-                return ConstantNode.forLong(x().asConstant().asLong() + y().asConstant().asLong(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         } else if (y().isConstant()) {
             long c = y().asConstant().asLong();
             if (c == 0) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -36,17 +36,18 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        return Constant.forIntegerKind(kind(), inputs[0].asLong() * inputs[1].asLong(), null);
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) {
             return graph().unique(new IntegerMulNode(kind(), y(), x()));
         }
         if (x().isConstant()) {
-            if (kind() == Kind.Int) {
-                return ConstantNode.forInt(x().asConstant().asInt() * y().asConstant().asInt(), graph());
-            } else {
-                assert kind() == Kind.Long;
-                return ConstantNode.forLong(x().asConstant().asLong() * y().asConstant().asLong(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         } else if (y().isConstant()) {
             long c = y().asConstant().asLong();
             if (c == 1) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -41,6 +41,12 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        return Constant.forIntegerKind(kind(), inputs[0].asLong() - inputs[1].asLong(), null);
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forIntegerKind(kind(), 0, graph());
@@ -80,12 +86,7 @@
             }
         }
         if (x().isConstant() && y().isConstant()) {
-            if (kind() == Kind.Int) {
-                return ConstantNode.forInt(x().asConstant().asInt() - y().asConstant().asInt(), graph());
-            } else {
-                assert kind() == Kind.Long;
-                return ConstantNode.forLong(x().asConstant().asLong() - y().asConstant().asLong(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         } else if (y().isConstant()) {
             long c = y().asConstant().asLong();
             if (c == 0) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -41,8 +41,21 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        if (kind() == Kind.Int) {
+            return Constant.forInt(inputs[0].asInt() << inputs[1].asInt());
+        } else {
+            assert kind() == Kind.Long;
+            return Constant.forLong(inputs[0].asLong() << inputs[1].asLong());
+        }
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (y().isConstant()) {
+        if (x().isConstant() && y().isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
+        } else if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
             int mask;
@@ -53,14 +66,6 @@
                 mask = 0x3f;
             }
             amount &= mask;
-            if (x().isConstant()) {
-                if (kind() == Kind.Int) {
-                    return ConstantNode.forInt(x().asConstant().asInt() << amount, graph());
-                } else {
-                    assert kind() == Kind.Long;
-                    return ConstantNode.forLong(x().asConstant().asLong() << amount, graph());
-                }
-            }
             if (amount == 0) {
                 return x();
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -52,19 +54,26 @@
         this.x = x;
     }
 
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 1;
+        switch (inputs[0].getKind()) {
+            case Int:
+                return Constant.forInt(-inputs[0].asInt());
+            case Long:
+                return Constant.forLong(-inputs[0].asLong());
+            case Float:
+                return Constant.forFloat(-inputs[0].asFloat());
+            case Double:
+                return Constant.forDouble(-inputs[0].asDouble());
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant()) {
-            switch (x().kind()) {
-                case Int:
-                    return ConstantNode.forInt(-x().asConstant().asInt(), graph());
-                case Long:
-                    return ConstantNode.forLong(-x().asConstant().asLong(), graph());
-                case Float:
-                    return ConstantNode.forFloat(-x().asConstant().asFloat(), graph());
-                case Double:
-                    return ConstantNode.forDouble(-x().asConstant().asDouble(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x.asConstant()), graph());
         }
         if (x() instanceof NegateNode) {
             return ((NegateNode) x()).x();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -43,6 +43,12 @@
         return updateStamp(StampTool.not(x().stamp()));
     }
 
+    @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 1;
+        return Constant.forIntegerKind(kind(), ~inputs[0].asLong(), null);
+    }
+
     /**
      * Creates new NegateNode instance.
      * 
@@ -57,12 +63,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant()) {
-            switch (x().kind()) {
-                case Int:
-                    return ConstantNode.forInt(~x().asConstant().asInt(), graph());
-                case Long:
-                    return ConstantNode.forLong(~x().asConstant().asLong(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant()), graph());
         }
         if (x() instanceof NotNode) {
             return ((NotNode) x()).x();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -41,6 +41,12 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        return Constant.forIntegerKind(kind(), inputs[0].asLong() | inputs[1].asLong(), null);
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return x();
@@ -49,12 +55,7 @@
             return graph().unique(new OrNode(kind(), y(), x()));
         }
         if (x().isConstant()) {
-            if (kind() == Kind.Int) {
-                return ConstantNode.forInt(x().asConstant().asInt() | y().asConstant().asInt(), graph());
-            } else {
-                assert kind() == Kind.Long;
-                return ConstantNode.forLong(x().asConstant().asLong() | y().asConstant().asLong(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         } else if (y().isConstant()) {
             if (kind() == Kind.Int) {
                 int c = y().asConstant().asInt();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -36,11 +36,24 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        if (kind() == Kind.Int) {
+            return Constant.forInt(inputs[0].asInt() >> inputs[1].asInt());
+        } else {
+            assert kind() == Kind.Long;
+            return Constant.forLong(inputs[0].asLong() >> inputs[1].asLong());
+        }
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) {
             return graph().unique(new UnsignedRightShiftNode(kind(), x(), y()));
         }
-        if (y().isConstant()) {
+        if (x().isConstant() && y().isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
+        } else if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
             int mask;
@@ -51,14 +64,6 @@
                 mask = 0x3f;
             }
             amount &= mask;
-            if (x().isConstant()) {
-                if (kind() == Kind.Int) {
-                    return ConstantNode.forInt(x().asConstant().asInt() >> amount, graph());
-                } else {
-                    assert kind() == Kind.Long;
-                    return ConstantNode.forLong(x().asConstant().asLong() >> amount, graph());
-                }
-            }
             if (amount == 0) {
                 return x();
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -41,8 +41,21 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        if (kind() == Kind.Int) {
+            return Constant.forInt(inputs[0].asInt() >>> inputs[1].asInt());
+        } else {
+            assert kind() == Kind.Long;
+            return Constant.forLong(inputs[0].asLong() >>> inputs[1].asLong());
+        }
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (y().isConstant()) {
+        if (x().isConstant() && y().isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
+        } else if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
             int mask;
@@ -53,14 +66,6 @@
                 mask = 0x3f;
             }
             amount &= mask;
-            if (x().isConstant()) {
-                if (kind() == Kind.Int) {
-                    return ConstantNode.forInt(x().asConstant().asInt() >>> amount, graph());
-                } else {
-                    assert kind() == Kind.Long;
-                    return ConstantNode.forLong(x().asConstant().asLong() >>> amount, graph());
-                }
-            }
             if (amount == 0) {
                 return x();
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -41,6 +41,12 @@
     }
 
     @Override
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 2;
+        return Constant.forIntegerKind(kind(), inputs[0].asLong() ^ inputs[1].asLong(), null);
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forIntegerKind(kind(), 0, graph());
@@ -49,12 +55,7 @@
             return graph().unique(new XorNode(kind(), y(), x()));
         }
         if (x().isConstant()) {
-            if (kind() == Kind.Int) {
-                return ConstantNode.forInt(x().asConstant().asInt() ^ y().asConstant().asInt(), graph());
-            } else {
-                assert kind() == Kind.Long;
-                return ConstantNode.forLong(x().asConstant().asLong() ^ y().asConstant().asLong(), graph());
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
         } else if (y().isConstant()) {
             if (kind() == Kind.Int) {
                 int c = y().asConstant().asInt();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -83,11 +82,6 @@
     }
 
     @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return DeoptimizationReason.NullCheckException;
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -75,11 +74,6 @@
     }
 
     @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return DeoptimizationReason.NullCheckException;
-    }
-
-    @Override
     public FrameState getDeoptimizationState() {
         return deoptState;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -130,11 +130,6 @@
     }
 
     @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return null;
-    }
-
-    @Override
     public FrameState getState() {
         if (deoptState != null) {
             assert stateAfter() == null;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -49,9 +48,4 @@
     public boolean canDeoptimize() {
         return true;
     }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return DeoptimizationReason.NullCheckException;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.java;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -95,9 +94,4 @@
     public boolean canDeoptimize() {
         return true;
     }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return DeoptimizationReason.RuntimeConstraint;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,11 +22,10 @@
  */
 package com.oracle.graal.nodes.java;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.graph.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -100,9 +100,4 @@
     public boolean canDeoptimize() {
         return true;
     }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return DeoptimizationReason.RuntimeConstraint;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -74,9 +74,4 @@
     public boolean canDeoptimize() {
         return true;
     }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return DeoptimizationReason.RuntimeConstraint;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -105,11 +105,6 @@
         deoptState = f;
     }
 
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return null;
-    }
-
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void register(Object thisObj) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Oct 02 13:28:17 2013 +0200
@@ -63,7 +63,7 @@
 
     void emitMembar(int barriers);
 
-    void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting);
+    void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting);
 
     void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Wed Oct 02 13:28:17 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Oct 02 13:28:17 2013 +0200
@@ -24,23 +24,26 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
- * This phase tries to find {@link DeoptimizeNode DeoptimizeNodes} which use the same
+ * This phase tries to find {@link AbstractDeoptimizeNode DeoptimizeNodes} which use the same
  * {@link FrameState} and merges them together.
  */
-public class DeoptimizationGroupingPhase extends Phase {
+public class DeoptimizationGroupingPhase extends BasePhase<MidTierContext> {
 
     @Override
-    protected void run(StructuredGraph graph) {
+    protected void run(StructuredGraph graph, MidTierContext context) {
         ControlFlowGraph cfg = null;
         for (FrameState fs : graph.getNodes(FrameState.class)) {
             FixedNode target = null;
-            List<DeoptimizeNode> obsoletes = null;
-            for (DeoptimizeNode deopt : fs.usages().filter(DeoptimizeNode.class)) {
+            PhiNode phi = null;
+            List<AbstractDeoptimizeNode> obsoletes = null;
+            for (AbstractDeoptimizeNode deopt : fs.usages().filter(AbstractDeoptimizeNode.class)) {
                 if (target == null) {
                     target = deopt;
                 } else {
@@ -48,34 +51,41 @@
                         cfg = ControlFlowGraph.compute(graph, true, true, false, false);
                     }
                     MergeNode merge;
-                    if (target instanceof DeoptimizeNode) {
+                    if (target instanceof AbstractDeoptimizeNode) {
                         merge = graph.add(new MergeNode());
                         EndNode firstEnd = graph.add(new EndNode());
+                        phi = graph.addWithoutUnique(new PhiNode(Kind.Int, merge));
                         merge.addForwardEnd(firstEnd);
+                        phi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getRuntime()));
                         target.predecessor().replaceFirstSuccessor(target, firstEnd);
-                        exitLoops((DeoptimizeNode) target, firstEnd, cfg);
-                        merge.setNext(target);
+
+                        exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg);
+
+                        merge.setNext(graph.add(new DynamicDeoptimizeNode(phi)));
                         obsoletes = new LinkedList<>();
+                        obsoletes.add((AbstractDeoptimizeNode) target);
                         target = merge;
                     } else {
                         merge = (MergeNode) target;
                     }
                     EndNode newEnd = graph.add(new EndNode());
                     merge.addForwardEnd(newEnd);
+                    phi.addInput(deopt.getActionAndReason(context.getRuntime()));
                     deopt.predecessor().replaceFirstSuccessor(deopt, newEnd);
                     exitLoops(deopt, newEnd, cfg);
                     obsoletes.add(deopt);
                 }
             }
             if (obsoletes != null) {
-                for (DeoptimizeNode obsolete : obsoletes) {
+                ((DynamicDeoptimizeNode) ((MergeNode) target).next()).setDeoptimizationState(fs);
+                for (AbstractDeoptimizeNode obsolete : obsoletes) {
                     obsolete.safeDelete();
                 }
             }
         }
     }
 
-    private static void exitLoops(DeoptimizeNode deopt, EndNode end, ControlFlowGraph cfg) {
+    private static void exitLoops(AbstractDeoptimizeNode deopt, EndNode end, ControlFlowGraph cfg) {
         Block block = cfg.blockFor(deopt);
         Loop loop = block.getLoop();
         while (loop != null) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java	Wed Oct 02 13:28:17 2013 +0200
@@ -25,7 +25,6 @@
 import java.util.*;
 import java.util.Map.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Oct 02 13:28:17 2013 +0200
@@ -27,7 +27,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.extended.*;
@@ -42,7 +41,7 @@
         ANALYSIS_ONLY, CREATE_FLOATING_READS
     }
 
-    public static class MemoryMapImpl implements MemoryMap<Node> {
+    public static class MemoryMapImpl extends MemoryMapNode {
 
         private IdentityHashMap<LocationIdentity, ValueNode> lastMemorySnapshot;
 
@@ -74,11 +73,6 @@
             }
         }
 
-        @Override
-        public String toString() {
-            return "Map=" + lastMemorySnapshot.toString();
-        }
-
         public boolean isEmpty() {
             if (lastMemorySnapshot.size() == 0) {
                 return true;
@@ -92,7 +86,7 @@
         }
 
         public Set<LocationIdentity> getLocations() {
-            return new HashSet<>(lastMemorySnapshot.keySet());
+            return lastMemorySnapshot.keySet();
         }
 
     }
@@ -192,7 +186,7 @@
             assert MemoryCheckpoint.TypeAssertion.correctType(node) : node;
 
             if (execmode == ExecutionMode.ANALYSIS_ONLY && node instanceof ReturnNode) {
-                node.graph().add(new MemoryState(new MemoryMapImpl(state), node));
+                ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapImpl(state)));
             }
             return state;
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.phases.common;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
+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.*;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Wed Oct 02 13:28:17 2013 +0200
@@ -77,8 +77,8 @@
     private void adjustControlSplitProbabilities() {
         HashSet<ControlSplitNode> result = new HashSet<>();
         NodeBitMap visitedNodes = new NodeBitMap(graph);
-        for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) {
-            if (n.action().doesInvalidateCompilation()) {
+        for (AbstractDeoptimizeNode n : graph.getNodes(AbstractDeoptimizeNode.class)) {
+            if (!(n instanceof DeoptimizeNode) || ((DeoptimizeNode) n).action().doesInvalidateCompilation()) {
                 findParentControlSplitNodes(result, n, visitedNodes);
             }
         }
@@ -90,7 +90,7 @@
         }
     }
 
-    private static void findParentControlSplitNodes(HashSet<ControlSplitNode> result, DeoptimizeNode n, NodeBitMap visitedNodes) {
+    private static void findParentControlSplitNodes(HashSet<ControlSplitNode> result, AbstractDeoptimizeNode n, NodeBitMap visitedNodes) {
         ArrayDeque<FixedNode> nodes = new ArrayDeque<>();
         nodes.push(n);
 
@@ -142,9 +142,9 @@
 
     private boolean verifyProbabilities() {
         if (doesNotAlwaysDeopt(graph)) {
-            for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) {
-                if (n.action().doesInvalidateCompilation() && nodeProbabilities.get(n) > 0.01) {
-                    throw new AssertionError(String.format("%s with reason %s and probability %f in graph %s", n, n.reason(), nodeProbabilities.get(n), graph));
+            for (AbstractDeoptimizeNode n : graph.getNodes(AbstractDeoptimizeNode.class)) {
+                if (nodeProbabilities.get(n) > 0.01 && (!(n instanceof DeoptimizeNode) || ((DeoptimizeNode) n).action().doesInvalidateCompilation())) {
+                    throw new AssertionError(String.format("%s with probability %f in graph %s", n, nodeProbabilities.get(n), graph));
                 }
             }
         }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Util.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Util.java	Wed Oct 02 13:28:17 2013 +0200
@@ -26,9 +26,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 
 /**
  * The {@code Util} class contains a motley collection of utility methods used throughout the
@@ -319,14 +316,6 @@
         return (short) v;
     }
 
-    public static boolean isFixed(Node n) {
-        return n instanceof FixedNode;
-    }
-
-    public static boolean isFloating(Node n) {
-        return n instanceof FloatingNode;
-    }
-
     /**
      * Creates an array of integers of length "size", in which each number from 0 to (size - 1)
      * occurs exactly once. The integers are sorted using the given comparator. This can be used to
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,9 +22,10 @@
  */
 package com.oracle.graal.replacements.amd64;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.ConvertNode.Op;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -44,6 +45,12 @@
         this.value = value;
     }
 
+    public Constant evalConst(Constant... inputs) {
+        // this node should never have been created if its input is constant
+        assert false;
+        return null;
+    }
+
     public void generate(ArithmeticLIRGenerator gen) {
         gen.setResult(this, gen.emitConvert(opcode, gen.operand(value)));
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Oct 02 13:28:17 2013 +0200
@@ -206,7 +206,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap<Node> mmap) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
@@ -238,7 +238,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap<Node> mmap) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Oct 02 13:28:17 2013 +0200
@@ -34,6 +34,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
@@ -540,7 +541,6 @@
         }
 
         new DeadCodeEliminationPhase().apply(snippetCopy);
-        new CanonicalizerPhase(true).apply(snippetCopy, context);
 
         assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders);
 
@@ -552,7 +552,7 @@
         StartNode entryPointNode = snippet.start();
         nodes = new ArrayList<>(snippet.getNodeCount());
         boolean seenReturn = false;
-        boolean containsMemoryState = false;
+        boolean containsMemoryMap = false;
         for (Node node : snippet.getNodes()) {
             if (node == entryPointNode || node == entryPointNode.stateAfter()) {
                 // Do nothing.
@@ -560,18 +560,20 @@
                 nodes.add(node);
                 if (node instanceof ReturnNode) {
                     retNode = (ReturnNode) node;
-                    for (MemoryState memstate : retNode.usages().filter(MemoryState.class).snapshot()) {
-                        this.memoryMap = memstate.getMemoryMap();
-                        memstate.safeDelete();
-                    }
+                    NodeIterable<MemoryMapNode> memstates = retNode.inputs().filter(MemoryMapNode.class);
+                    assert memstates.count() == 1;
+                    memoryMap = memstates.first();
+                    retNode.replaceFirstInput(memoryMap, null);
+                    memoryMap.safeDelete();
+
                     assert !seenReturn : "can handle only one ReturnNode";
                     seenReturn = true;
-                } else if (node instanceof MemoryState) {
-                    containsMemoryState = true;
+                } else if (node instanceof MemoryMapNode) {
+                    containsMemoryMap = true;
                 }
             }
         }
-        assert !containsMemoryState;
+        assert !containsMemoryMap;
 
         this.sideEffectNodes = curSideEffectNodes;
         this.deoptNodes = curDeoptNodes;
@@ -657,7 +659,7 @@
     /**
      * map of killing locations to memory checkpoints (nodes).
      */
-    private MemoryMap<Node> memoryMap;
+    private MemoryMapNode memoryMap;
 
     /**
      * Gets the instantiation-time bindings to this template's parameters.
@@ -751,7 +753,7 @@
         /**
          * Replaces all usages of {@code oldNode} with direct or indirect usages of {@code newNode}.
          */
-        void replace(ValueNode oldNode, ValueNode newNode, MemoryMap<Node> mmap);
+        void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap);
     }
 
     /**
@@ -761,7 +763,7 @@
     public static final UsageReplacer DEFAULT_REPLACER = new UsageReplacer() {
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap<Node> mmap) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) {
             oldNode.replaceAtUsages(newNode);
             if (mmap == null || newNode == null) {
                 return;
@@ -792,7 +794,7 @@
             return true;
         }
 
-        Set<LocationIdentity> kills = ((MemoryMapImpl) memoryMap).getLocations();
+        Set<LocationIdentity> kills = new HashSet<>(((MemoryMapImpl) memoryMap).getLocations());
 
         if (replacee instanceof MemoryCheckpoint.Single) {
             // check if some node in snippet graph also kills the same location
@@ -828,7 +830,7 @@
         return true;
     }
 
-    private class DuplicateMapper implements MemoryMap<Node> {
+    private class DuplicateMapper extends MemoryMapNode {
 
         Map<Node, Node> duplicates;
         StartNode replaceeStart;
@@ -915,7 +917,7 @@
                     returnValue = (ValueNode) duplicates.get(returnNode.result());
                 }
                 Node returnDuplicate = duplicates.get(returnNode);
-                MemoryMap<Node> mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
+                MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
                 if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
                     replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap);
                 } else {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -85,28 +85,15 @@
         gen.setResult(this, result);
     }
 
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 1;
+        return Constant.forDouble(compute(inputs[0].asDouble(), operation()));
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant()) {
-            double value = x().asConstant().asDouble();
-            switch (operation()) {
-                case ABS:
-                    return ConstantNode.forDouble(Math.abs(value), graph());
-                case SQRT:
-                    return ConstantNode.forDouble(Math.sqrt(value), graph());
-                case LOG:
-                    return ConstantNode.forDouble(Math.log(value), graph());
-                case LOG10:
-                    return ConstantNode.forDouble(Math.log10(value), graph());
-                case SIN:
-                    return ConstantNode.forDouble(Math.sin(value), graph());
-                case COS:
-                    return ConstantNode.forDouble(Math.cos(value), graph());
-                case TAN:
-                    return ConstantNode.forDouble(Math.tan(value), graph());
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
+            return ConstantNode.forPrimitive(evalConst(x().asConstant()), graph());
         }
         return this;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.truffle.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.truffle.nodes.arithmetic;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java	Wed Oct 02 13:28:17 2013 +0200
@@ -25,7 +25,6 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Wed Oct 02 13:28:17 2013 +0200
@@ -24,7 +24,6 @@
 
 import java.util.concurrent.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.truffle.substitutions;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java	Wed Oct 02 13:28:17 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.truffle.substitutions;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Oct 02 13:18:25 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Oct 02 13:28:17 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -31,6 +31,7 @@
 
 import sun.misc.*;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.api.nodes.Node.Children;
 
@@ -637,6 +638,66 @@
         p.flush();
     }
 
+    public static String printSourceAttributionTree(Node node) {
+        StringWriter out = new StringWriter();
+        printSourceAttributionTree(new PrintWriter(out), null, node, 1);
+        return out.toString();
+    }
+
+    public static void printSourceAttributionTree(OutputStream out, Node node) {
+        printSourceAttributionTree(new PrintWriter(out), null, node, 1);
+    }
+
+    private static void printSourceAttributionTree(PrintWriter p, Node parent, Node node, int level) {
+        if (node == null) {
+            return;
+        }
+        if (parent == null) {
+            // Add some preliminary information before starting with the root node
+            final SourceSection sourceSection = node.getSourceSection();
+            if (sourceSection != null) {
+                final String txt = sourceSection.getSource().getCode();
+                p.println("Full source len=(" + txt.length() + ")  txt=___" + txt + "___");
+                p.println("AST source attribution:");
+            }
+        }
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < level; i++) {
+            sb.append("| ");
+        }
+
+        if (parent != null) {
+            String childName = "";
+            NodeField[] fields = NodeClass.get(parent.getClass()).fields;
+            for (NodeField field : fields) {
+                Object value = field.loadValue(parent);
+                if (value == node) {
+                    childName = field.getName();
+                    break;
+                } else if (value instanceof Node[]) {
+                    int index = 0;
+                    for (Node arrayNode : (Node[]) value) {
+                        if (arrayNode == node) {
+                            childName = field.getName() + "[" + index + "]";
+                            break;
+                        }
+                        index++;
+                    }
+                }
+            }
+            sb.append(childName);
+        }
+
+        sb.append("  (" + node.getClass().getSimpleName() + ")  ");
+        sb.append(displaySourceAttribution(node));
+        p.println(sb.toString());
+
+        for (Node child : node.getChildren()) {
+            printSourceAttributionTree(p, node, child, level + 1);
+        }
+        p.flush();
+    }
+
     /**
      * 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.
@@ -724,4 +785,17 @@
     private static String nodeName(Node node) {
         return node.getClass().getSimpleName();
     }
+
+    private static String displaySourceAttribution(Node node) {
+        final SourceSection section = node.getSourceSection();
+        if (section != null) {
+            final String srcText = section.getCode();
+            final StringBuilder sb = new StringBuilder();
+            sb.append("source:  len=" + srcText.length());
+            sb.append(" (" + section.getCharIndex() + "," + (section.getCharEndIndex() - 1) + ")");
+            sb.append(" txt=___" + srcText + "___");
+            return sb.toString();
+        }
+        return "";
+    }
 }
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Wed Oct 02 13:18:25 2013 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Wed Oct 02 13:28:17 2013 +0200
@@ -50,6 +50,28 @@
 gpu::Ptx::cuda_cu_memcpy_dtoh_func_t gpu::Ptx::_cuda_cu_memcpy_dtoh;
 gpu::Ptx::cuda_cu_memfree_func_t gpu::Ptx::_cuda_cu_memfree;
 
+
+/*
+ * see http://en.wikipedia.org/wiki/CUDA#Supported_GPUs
+ */
+int ncores(int major, int minor) {
+    int device_type = (major << 4) + minor;
+
+    switch (device_type) {
+        case 0x10: return 8;
+        case 0x11: return 8;
+        case 0x12: return 8;
+        case 0x13: return 8;
+        case 0x20: return 32;
+        case 0x21: return 48;
+        case 0x30: return 192;
+        case 0x35: return 192;
+    default:
+        tty->print_cr("[CUDA] Warning: Unhandled device %x", device_type);
+        return 0;
+    }
+}
+
 bool gpu::Ptx::initialize_gpu() {
 
   /* Initialize CUDA driver API */
@@ -95,24 +117,7 @@
   }
 
   /* Get device attributes */
-  int minor, major, unified_addressing;
-  status = _cuda_cu_device_get_attribute(&minor, GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, _cu_device);
-
-  if (status != GRAAL_CUDA_SUCCESS) {
-    tty->print_cr("[CUDA] Failed to get minor attribute of device: %d", _cu_device);
-    return false;
-  }
-
-  status = _cuda_cu_device_get_attribute(&major, GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, _cu_device);
-
-  if (status != GRAAL_CUDA_SUCCESS) {
-    tty->print_cr("[CUDA] Failed to get major attribute of device: %d", _cu_device);
-    return false;
-  }
-
-  if (TraceGPUInteraction) {
-    tty->print_cr("[CUDA] Compatibility version of device %d: %d.%d", _cu_device, major, minor);
-  }
+  int unified_addressing;
 
   status = _cuda_cu_device_get_attribute(&unified_addressing, GRAAL_CU_DEVICE_ATTRIBUTE_UNIFIED_ADDRESSING, _cu_device);
 
@@ -139,9 +144,50 @@
     tty->print_cr("[CUDA] Using %s", device_name);
   }
 
+
   return true;
 }
 
+unsigned int gpu::Ptx::total_cores() {
+
+    int minor, major, nmp;
+    int status = _cuda_cu_device_get_attribute(&minor,
+                                               GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR,
+                                               _cu_device);
+
+    if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] Failed to get minor attribute of device: %d", _cu_device);
+        return 0;
+    }
+
+    status = _cuda_cu_device_get_attribute(&major,
+                                           GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR,
+                                           _cu_device);
+
+    if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] Failed to get major attribute of device: %d", _cu_device);
+        return 0;
+    }
+
+    status = _cuda_cu_device_get_attribute(&nmp,
+                                           GRAAL_CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
+                                           _cu_device);
+
+    if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] Failed to get numberof MPs on device: %d", _cu_device);
+        return 0;
+    }
+
+    int total = nmp * ncores(major, minor);
+
+    if (TraceGPUInteraction) {
+        tty->print_cr("[CUDA] Compatibility version of device %d: %d.%d", _cu_device, major, minor);
+        tty->print_cr("[CUDA] Number of cores: %d", total);
+    }
+    return (total);
+    
+}
+
 void *gpu::Ptx::generate_kernel(unsigned char *code, int code_len, const char *name) {
 
   struct CUmod_st * cu_module;
--- a/src/gpu/ptx/vm/gpu_ptx.hpp	Wed Oct 02 13:18:25 2013 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.hpp	Wed Oct 02 13:28:17 2013 +0200
@@ -34,6 +34,7 @@
 #define GRAAL_CU_DEVICE_ATTRIBUTE_UNIFIED_ADDRESSING        41
 #define GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR  75
 #define GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR  76
+#define GRAAL_CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT      16
 #define GRAAL_CU_JIT_MAX_REGISTERS                           0
 #define GRAAL_CU_JIT_THREADS_PER_BLOCK                       1
 #define GRAAL_CU_JIT_INFO_LOG_BUFFER                         3
@@ -73,6 +74,7 @@
  protected:
   static bool probe_linkage();
   static bool initialize_gpu();
+  static unsigned int total_cores();
   static void * generate_kernel(unsigned char *code, int code_len, const char *name);
   static bool execute_warp(int dimX, int dimY, int dimZ, address kernel, PTXKernelArguments & ka, JavaValue &ret);
   static bool execute_kernel(address kernel, PTXKernelArguments & ka, JavaValue &ret);
--- a/src/share/vm/graal/graalCompilerToGPU.cpp	Wed Oct 02 13:18:25 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToGPU.cpp	Wed Oct 02 13:28:17 2013 +0200
@@ -111,7 +111,7 @@
   HandleMark hm;
 
   if (gpu::is_available() == false || gpu::has_gpu_linkage() == false && gpu::is_initialized()) {
-    tty->print_cr("executeExternalMethodVarargs - not available / no linkage / not initialized");
+    tty->print_cr("executeParallelMethodVarargs - not available / no linkage / not initialized");
     return NULL;
   }
   jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode);
@@ -155,6 +155,14 @@
   return gpu::is_initialized();
 C2V_END
 
+C2V_VMENTRY(jint, availableProcessors, (JNIEnv *env, jobject))
+  if (gpu::is_available() == false || gpu::has_gpu_linkage() == false) {
+    tty->print_cr("deviceInit - not available / no linkage");
+    return false;
+  }
+  return gpu::available_processors();
+C2V_END
+
 C2V_VMENTRY(jboolean, deviceDetach, (JNIEnv *env, jobject))
 return true;
 C2V_END
@@ -199,6 +207,7 @@
   {CC"generateKernel",                CC"([B" STRING ")"GPUSPACE_METHOD,          FN_PTR(generateKernel)},
   {CC"deviceInit",                    CC"()Z",                                    FN_PTR(deviceInit)},
   {CC"deviceDetach",                  CC"()Z",                                    FN_PTR(deviceDetach)},
+  {CC"availableProcessors",           CC"()I",                                    FN_PTR(availableProcessors)},
   {CC"executeExternalMethodVarargs",  CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT,    FN_PTR(executeExternalMethodVarargs)},
   {CC"executeParallelMethodVarargs",  CC"(III["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeParallelMethodVarargs)},
 };
--- a/src/share/vm/runtime/gpu.cpp	Wed Oct 02 13:18:25 2013 +0200
+++ b/src/share/vm/runtime/gpu.cpp	Wed Oct 02 13:28:17 2013 +0200
@@ -81,3 +81,13 @@
     return false;
 }
 
+int gpu::available_processors() {
+    if (gpu::has_gpu_linkage()) {
+        if (gpu::get_target_il_type() == gpu::PTX) {
+            return (gpu::Ptx::total_cores());
+        }
+        // Add kernel execution functionality of other GPUs here
+    }
+    return 0;
+}
+
--- a/src/share/vm/runtime/gpu.hpp	Wed Oct 02 13:18:25 2013 +0200
+++ b/src/share/vm/runtime/gpu.hpp	Wed Oct 02 13:28:17 2013 +0200
@@ -43,6 +43,8 @@
   static void probe_gpu();
 
   static void initialize_gpu();
+
+  static int available_processors();
   
   static void * generate_kernel(unsigned char *code, int code_len, const char *name);