changeset 15182:89325b6051ea

Merge
author Matthias Grimmer <grimmer@ssw.jku.at>
date Thu, 17 Apr 2014 08:22:21 +0200
parents 5be5e917e421 (current diff) 7a9531f50cd8 (diff)
children b862cf4381ef
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlockBase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Loop.java
diffstat 128 files changed, 1110 insertions(+), 764 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Apr 16 17:55:12 2014 +0200
+++ b/.hgignore	Thu Apr 17 08:22:21 2014 +0200
@@ -5,6 +5,7 @@
 ^mx/netbeans-config.zip
 ^mx/netbeans-config-libs.zip
 ^mx/eclipse-launches
+^mx/jmh
 ^mx/currentAnnotationProcessors
 ^mx/ecj.jar
 ^mx/includes
--- a/CHANGELOG.md	Wed Apr 16 17:55:12 2014 +0200
+++ b/CHANGELOG.md	Thu Apr 17 08:22:21 2014 +0200
@@ -7,11 +7,12 @@
 * Explicit types for inputs (InputType enum).
 * Added graal.version system property to Graal enabled VM builds.
 * Transitioned to JDK 8 as minimum JDK level for Graal.
-* Added support for stack introspection
+* Added support for stack introspection.
 * ...
 
 ### Truffle
-* Support for collecting stack traces and for accessing the current frame in slow paths
+* The method CallTarget#call takes now a variable number of Object arguments.
+* Support for collecting stack traces and for accessing the current frame in slow paths.
 * Renamed CallNode to DirectCallNode.
 * Renamed TruffleRuntime#createCallNode to TruffleRuntime#createDirectCallNode.
 * Added IndirectCallNode for calls with a changing CallTarget. 
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Thu Apr 17 08:22:21 2014 +0200
@@ -25,6 +25,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.nodes.cfg.*;
 
 /**
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Thu Apr 17 08:22:21 2014 +0200
@@ -34,18 +34,18 @@
     /**
      * Adds the given compilation result as an implementation of the given method without making it
      * the default implementation.
-     * 
+     *
      * @param method a method to which the executable code is begin added
      * @param compResult the compilation result to be added
      * @param speculationLog the speculation log to be used
      * @return a reference to the compiled and ready-to-run code or null if the code installation
      *         failed
      */
-    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog);
+    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode);
 
     /**
      * Sets the given compilation result as the default implementation of the given method.
-     * 
+     *
      * @param method a method to which the executable code is begin added
      * @param compResult the compilation result to be added
      * @return a reference to the compiled and ready-to-run code or null if the code installation
@@ -55,11 +55,11 @@
 
     /**
      * Returns a disassembly of some compiled code.
-     * 
+     *
      * @param compResult some compiled code
      * @param installedCode the result of installing the code in {@code compResult} or null if the
      *            code has not yet been installed
-     * 
+     *
      * @return a disassembly. This will be of length 0 if the runtime does not support
      *         disassembling.
      */
@@ -73,7 +73,7 @@
     /**
      * Minimum size of the stack area reserved for outgoing parameters. This area is reserved in all
      * cases, even when the compiled method has no regular call instructions.
-     * 
+     *
      * @return the minimum size of the outgoing parameter area in bytes
      */
     int getMinimumOutgoingSize();
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu Apr 17 08:22:21 2014 +0200
@@ -368,7 +368,7 @@
      * starting address of the table. This type of table maybe generated when translating a
      * multi-way branch based on a key value from a dense value set (e.g. the {@code tableswitch}
      * JVM instruction).
-     * 
+     *
      * The table is indexed by the contiguous range of integers from {@link #low} to {@link #high}
      * inclusive.
      */
@@ -460,7 +460,7 @@
     private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();
     private final List<Mark> marks = new ArrayList<>();
 
-    private int frameSize = -1;
+    private int totalFrameSize = -1;
     private int customStackAreaOffset = -1;
     private int registerRestoreEpilogueOffset = -1;
 
@@ -525,18 +525,29 @@
     }
 
     /**
-     * Sets the frame size in bytes. Does not include the return address pushed onto the stack, if
-     * any.
-     * 
+     * The total frame size of the method in bytes. This includes the return address pushed onto the
+     * stack, if any.
+     *
+     * @return the frame size
+     */
+    public int getTotalFrameSize() {
+        assert totalFrameSize != -1 : "frame size not yet initialized!";
+        return totalFrameSize;
+    }
+
+    /**
+     * Sets the total frame size in bytes. This includes the return address pushed onto the stack,
+     * if any.
+     *
      * @param size the size of the frame in bytes
      */
-    public void setFrameSize(int size) {
-        frameSize = size;
+    public void setTotalFrameSize(int size) {
+        totalFrameSize = size;
     }
 
     /**
      * Sets the machine that has been generated by the compiler.
-     * 
+     *
      * @param code the machine code generated
      * @param size the size of the machine code
      */
@@ -548,7 +559,7 @@
     /**
      * Records a reference to the data section in the code section (e.g. to load an integer or
      * floating point constant).
-     * 
+     *
      * @param codePos the position in the code where the data reference occurs
      * @param data the data that is referenced
      */
@@ -559,7 +570,7 @@
 
     /**
      * Records a reference to an inlined constant in the code section (e.g. to load a constant oop).
-     * 
+     *
      * @param codePos the position in the code where the inlined constant occurs
      * @param data the data that is referenced
      */
@@ -570,7 +581,7 @@
 
     /**
      * Records a call in the code array.
-     * 
+     *
      * @param codePos the position of the call in the code array
      * @param size the size of the call instruction
      * @param target the being called
@@ -584,7 +595,7 @@
 
     /**
      * Records an exception handler for this method.
-     * 
+     *
      * @param codePos the position in the code that is covered by the handler
      * @param handlerPos the position of the handler
      */
@@ -594,7 +605,7 @@
 
     /**
      * Records an infopoint in the code array.
-     * 
+     *
      * @param codePos the position of the infopoint in the code array
      * @param debugInfo the debug info for the infopoint
      */
@@ -604,10 +615,10 @@
 
     /**
      * Records a custom infopoint in the code section.
-     * 
+     *
      * Compiler implementations can use this method to record non-standard infopoints, which are not
      * handled by the dedicated methods like {@link #recordCall}.
-     * 
+     *
      * @param infopoint the infopoint to record, usually a derived class from {@link Infopoint}
      */
     public void addInfopoint(Infopoint infopoint) {
@@ -621,7 +632,7 @@
 
     /**
      * Records an instruction mark within this method.
-     * 
+     *
      * @param codePos the position in the code that is covered by the handler
      * @param markId the identifier for this mark
      * @param references an array of other marks that this mark references
@@ -636,7 +647,7 @@
      * Allows a method to specify the offset of the epilogue that restores the callee saved
      * registers. Must be called iff the method is a callee saved method and stores callee registers
      * on the stack.
-     * 
+     *
      * @param registerRestoreEpilogueOffset the offset in the machine code where the epilogue begins
      */
     public void setRegisterRestoreEpilogueOffset(int registerRestoreEpilogueOffset) {
@@ -645,16 +656,6 @@
     }
 
     /**
-     * The frame size of the method in bytes.
-     * 
-     * @return the frame size
-     */
-    public int getFrameSize() {
-        assert frameSize != -1 : "frame size not yet initialized!";
-        return frameSize;
-    }
-
-    /**
      * @return the code offset of the start of the epilogue that restores all callee saved
      *         registers, or -1 if this is not a callee saved method
      */
@@ -664,7 +665,7 @@
 
     /**
      * Offset in bytes for the custom stack area (relative to sp).
-     * 
+     *
      * @return the offset in bytes
      */
     public int getCustomStackAreaOffset() {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Thu Apr 17 08:22:21 2014 +0200
@@ -22,41 +22,66 @@
  */
 package com.oracle.graal.api.code;
 
-import com.oracle.graal.api.meta.*;
-
 /**
  * Represents a compiled instance of a method. It may have been invalidated or removed in the
  * meantime.
  */
-public interface InstalledCode {
+public class InstalledCode {
+
+    /**
+     * Raw address of this code blob.
+     */
+    private long address;
+
+    /**
+     * Counts how often the address field was reassigned.
+     */
+    private long version;
 
     /**
-     * Returns the method (if any) to which the installed code belongs.
+     * @return the address of this code blob
      */
-    ResolvedJavaMethod getMethod();
+    public final long getAddress() {
+        return address;
+    }
+
+    /**
+     * @return the address of this code blob
+     */
+    public final long getVersion() {
+        return version;
+    }
 
     /**
      * Returns the start address of this installed code if it is {@linkplain #isValid() valid}, 0
      * otherwise.
      */
-    long getStart();
+    public long getStart() {
+        return 0;
+    }
 
     /**
      * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise.
      */
-    byte[] getCode();
+    public byte[] getCode() {
+        return null;
+    }
 
     /**
      * @return true if the code represented by this object is still valid, false otherwise (may
      *         happen due to deopt, etc.)
      */
-    boolean isValid();
+    public boolean isValid() {
+        return address != 0;
+    }
 
     /**
      * Invalidates this installed code such that any subsequent invocation will throw an
      * {@link InvalidInstalledCodeException}.
      */
-    void invalidate();
+    public void invalidate() {
+        throw new UnsupportedOperationException();
+    }
 
     /**
      * Executes the installed code with a variable number of arguments.
@@ -64,5 +89,8 @@
      * @param args the array of object arguments
      * @return the value returned by the executed code
      */
-    Object executeVarargs(Object... args) throws InvalidInstalledCodeException;
+    @SuppressWarnings("unused")
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java	Thu Apr 17 08:22:21 2014 +0200
@@ -23,7 +23,7 @@
 /**
  * Package that defines the interface between a Java application that wants to install code and the runtime.
  * The runtime provides in implementation of the {@link com.oracle.graal.api.code.CodeCacheProvider} interface.
- * The method {@link com.oracle.graal.api.code.CodeCacheProvider#addMethod(com.oracle.graal.api.meta.ResolvedJavaMethod, CompilationResult, SpeculationLog)}
+ * The method {@link com.oracle.graal.api.code.CodeCacheProvider#addMethod(com.oracle.graal.api.meta.ResolvedJavaMethod, CompilationResult, SpeculationLog, InstalledCode)}
  * can be used to install code for a given method.
  */
 package com.oracle.graal.api.code;
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Thu Apr 17 08:22:21 2014 +0200
@@ -61,7 +61,7 @@
         byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
         compResult.setTargetCode(targetCode, targetCode.length);
 
-        InstalledCode code = codeCache.addMethod(method, compResult, null);
+        InstalledCode code = codeCache.addMethod(method, compResult, null, null);
 
         DisassemblerProvider dis = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getDisassembler();
         if (dis != null) {
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Thu Apr 17 08:22:21 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.bytecode.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
@@ -42,7 +43,7 @@
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
 import com.oracle.graal.nodes.cfg.*;
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,7 +24,7 @@
 
 import java.util.*;
 
-import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.cfg.*;
 
 public class LIRBlock extends AbstractBlockBase<LIRBlock> {
 
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,10 +24,10 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
-import com.oracle.graal.nodes.cfg.*;
 
 public class LIRControlFlowGraph implements AbstractControlFlowGraph<BciBlock> {
 
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRLoop.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRLoop.java	Thu Apr 17 08:22:21 2014 +0200
@@ -23,8 +23,8 @@
 
 package com.oracle.graal.baseline;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
-import com.oracle.graal.nodes.cfg.*;
 
 public class LIRLoop extends Loop<BciBlock> {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.cfg/src/com/oracle/graal/cfg/AbstractBlock.java	Thu Apr 17 08:22:21 2014 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.cfg;
+
+import java.util.*;
+
+public interface AbstractBlock<T extends AbstractBlock<T>> {
+
+    int getId();
+
+    Loop<T> getLoop();
+
+    int getLoopDepth();
+
+    boolean isLoopHeader();
+
+    boolean isLoopEnd();
+
+    boolean isExceptionEntry();
+
+    List<T> getPredecessors();
+
+    int getPredecessorCount();
+
+    List<T> getSuccessors();
+
+    int getSuccessorCount();
+
+    int getLinearScanNumber();
+
+    void setLinearScanNumber(int linearScanNumber);
+
+    boolean isAligned();
+
+    void setAlign(boolean align);
+
+    T getDominator();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.cfg/src/com/oracle/graal/cfg/AbstractBlockBase.java	Thu Apr 17 08:22:21 2014 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.cfg;
+
+import java.util.*;
+
+public abstract class AbstractBlockBase<T extends AbstractBlock<T>> implements AbstractBlock<T> {
+
+    protected int id;
+
+    protected List<T> predecessors;
+    protected List<T> successors;
+
+    private T dominator;
+
+    private boolean align;
+    private int linearScanNumber;
+
+    protected AbstractBlockBase() {
+        this.id = AbstractControlFlowGraph.BLOCK_ID_INITIAL;
+        this.linearScanNumber = -1;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public List<T> getPredecessors() {
+        return predecessors;
+    }
+
+    public void setPredecessors(List<T> predecessors) {
+        this.predecessors = predecessors;
+    }
+
+    public List<T> getSuccessors() {
+        return successors;
+    }
+
+    public void setSuccessors(List<T> successors) {
+        this.successors = successors;
+    }
+
+    public T getDominator() {
+        return dominator;
+    }
+
+    public void setDominator(T dominator) {
+        this.dominator = dominator;
+    }
+
+    @Override
+    public String toString() {
+        return "B" + id;
+    }
+
+    public int getPredecessorCount() {
+        return getPredecessors().size();
+    }
+
+    public int getSuccessorCount() {
+        return getSuccessors().size();
+    }
+
+    public int getLinearScanNumber() {
+        return linearScanNumber;
+    }
+
+    public void setLinearScanNumber(int linearScanNumber) {
+        this.linearScanNumber = linearScanNumber;
+    }
+
+    public boolean isAligned() {
+        return align;
+    }
+
+    public void setAlign(boolean align) {
+        this.align = align;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.cfg/src/com/oracle/graal/cfg/AbstractControlFlowGraph.java	Thu Apr 17 08:22:21 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.cfg;
+
+import java.util.*;
+
+public interface AbstractControlFlowGraph<T extends AbstractBlock<T>> {
+
+    static final int BLOCK_ID_INITIAL = -1;
+    static final int BLOCK_ID_VISITED = -2;
+
+    T[] getBlocks();
+
+    Collection<Loop<T>> getLoops();
+
+    T getStartBlock();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.cfg/src/com/oracle/graal/cfg/BlockMap.java	Thu Apr 17 08:22:21 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.cfg;
+
+public class BlockMap<T> {
+
+    private final T[] data;
+
+    @SuppressWarnings("unchecked")
+    public BlockMap(AbstractControlFlowGraph<?> cfg) {
+        data = (T[]) new Object[cfg.getBlocks().length];
+    }
+
+    public T get(AbstractBlock<?> block) {
+        return data[block.getId()];
+    }
+
+    public void put(AbstractBlock<?> block, T value) {
+        data[block.getId()] = value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.cfg/src/com/oracle/graal/cfg/Loop.java	Thu Apr 17 08:22:21 2014 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.cfg;
+
+import java.util.*;
+
+public abstract class Loop<T extends AbstractBlock<T>> {
+
+    public final Loop<T> parent;
+    public final List<Loop<T>> children;
+
+    public final int depth;
+    public final int index;
+    public final T header;
+    public final List<T> blocks;
+    public final List<T> exits;
+
+    protected Loop(Loop<T> parent, int index, T header) {
+        this.parent = parent;
+        if (parent != null) {
+            this.depth = parent.depth + 1;
+            parent.children.add(this);
+        } else {
+            this.depth = 1;
+        }
+        this.index = index;
+        this.header = header;
+        this.blocks = new ArrayList<>();
+        this.children = new ArrayList<>();
+        this.exits = new ArrayList<>();
+    }
+
+    public abstract long numBackedges();
+
+    @Override
+    public String toString() {
+        return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Thu Apr 17 08:22:21 2014 +0200
@@ -25,7 +25,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.hsail.*;
@@ -63,11 +62,6 @@
     }
 
     @Override
-    public void visitSafepointNode(SafepointNode i) {
-        Debug.log("visitSafePointNode unimplemented");
-    }
-
-    @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
         assert v.stamp() instanceof ObjectStamp;
         Variable obj = newVariable(Kind.Object);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Apr 17 08:22:21 2014 +0200
@@ -675,7 +675,7 @@
     }
 
     protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) {
-        return getCodeCache().addMethod(method, compResult, null);
+        return getCodeCache().addMethod(method, compResult, null, null);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import org.junit.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Thu Apr 17 08:22:21 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.test.*;
@@ -41,7 +42,6 @@
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Apr 17 08:22:21 2014 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
@@ -127,9 +128,8 @@
      *
      * @param graph the graph to be compiled
      * @param cc the calling convention for calls to the code compiled for {@code graph}
-     * @param installedCodeOwner the method the compiled code will be
-     *            {@linkplain InstalledCode#getMethod() associated} with once installed. This
-     *            argument can be null.
+     * @param installedCodeOwner the method the compiled code will be associated with once
+     *            installed. This argument can be null.
      * @return the result of the compilation
      */
     public static <T extends CompilationResult> T compileGraph(StructuredGraph graph, Object stub, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend,
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Apr 17 08:22:21 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.alloc.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.graal.compiler.alloc.Interval.SpillState;
@@ -46,7 +47,6 @@
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.util.*;
 
 /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Thu Apr 17 08:22:21 2014 +0200
@@ -30,6 +30,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.graal.compiler.alloc.Interval.SpillState;
@@ -37,7 +38,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.util.*;
 
 /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Thu Apr 17 08:22:21 2014 +0200
@@ -28,13 +28,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.util.*;
 
 /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Apr 17 08:22:21 2014 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Thu Apr 17 08:22:21 2014 +0200
@@ -31,6 +31,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.gen.LIRGenerator.LoadConstant;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu Apr 17 08:22:21 2014 +0200
@@ -102,9 +102,8 @@
     /**
      * Emits the code for a given graph.
      *
-     * @param installedCodeOwner the method the compiled code will be
-     *            {@linkplain InstalledCode#getMethod() associated} with once installed. This
-     *            argument can be null.
+     * @param installedCodeOwner the method the compiled code will be associated with once
+     *            installed. This argument can be null.
      */
     public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Apr 17 08:22:21 2014 +0200
@@ -225,7 +225,7 @@
         Assembler masm = createAssembler(frameMap);
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame);
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
-        crb.setFrameSize(frameMap.frameSize());
+        crb.setTotalFrameSize(frameMap.totalFrameSize());
         StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
         if (deoptimizationRescueSlot != null && stub == null) {
             crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Thu Apr 17 08:22:21 2014 +0200
@@ -27,6 +27,8 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options.*;
+import static com.oracle.graal.hotspot.hsail.replacements.HSAILNewObjectSnippets.Options.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -44,6 +46,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.hsail.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -58,10 +61,9 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp;
 import com.oracle.graal.lir.hsail.HSAILMove.AtomicGetAndAddOp;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -71,9 +73,6 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
-import static com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options.*;
-import static com.oracle.graal.hotspot.hsail.replacements.HSAILNewObjectSnippets.Options.*;
-
 /**
  * HSAIL specific backend.
  */
@@ -295,7 +294,7 @@
         assert hsailCode.getDataReferences().isEmpty();
 
         // from host code
-        result.setFrameSize(hostCode.getFrameSize());
+        result.setTotalFrameSize(hostCode.getTotalFrameSize());
         result.setCustomStackAreaOffset(hostCode.getCustomStackAreaOffset());
         result.setRegisterRestoreEpilogueOffset(hostCode.getRegisterRestoreEpilogueOffset());
         result.setTargetCode(hostCode.getTargetCode(), hostCode.getTargetCodeSize());
@@ -433,7 +432,7 @@
         // save lirGen for later use by setHostGraph
         CompilationResultBuilder crb = new HSAILCompilationResultBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult,
                         (HSAILHotSpotLIRGenerationResult) lirGenRes);
-        crb.setFrameSize(frameMap.frameSize());
+        crb.setTotalFrameSize(frameMap.totalFrameSize());
         return crb;
     }
 
@@ -444,6 +443,7 @@
 
         HotSpotVMConfig config = getRuntime().getConfig();
         boolean useHSAILDeoptimization = config.useHSAILDeoptimization;
+        boolean useHSAILSafepoints = config.useHSAILSafepoints;
 
         // see what graph nodes we have to see if we are using the thread register
         // if not, we don't have to emit the code that sets that up
@@ -577,13 +577,23 @@
 
             // Aliases for d17
             RegisterValue d17_donorThreadIndex = HSAIL.d17.asValue(wordKind);
+            RegisterValue d17_safepointFlagAddrIndex = d17_donorThreadIndex;
 
             // Aliases for s34
             RegisterValue s34_deoptOccurred = HSAIL.s34.asValue(Kind.Int);
             RegisterValue s34_donorThreadIndex = s34_deoptOccurred;
 
             asm.emitLoadKernelArg(d16_deoptInfo, asm.getDeoptInfoName(), "u64");
-            asm.emitComment("// Check if a deopt has occurred and abort if true before doing any work");
+            asm.emitComment("// Check if a deopt or safepoint has occurred and abort if true before doing any work");
+
+            if (useHSAILSafepoints) {
+                // Load address of _notice_safepoints field
+                asm.emitLoad(wordKind, d17_safepointFlagAddrIndex, new HSAILAddressValue(wordKind, d16_deoptInfo, config.hsailNoticeSafepointsOffset).toAddress());
+                // Load int value from that field
+                asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(Kind.Int, d17_safepointFlagAddrIndex, 0).toAddress());
+                asm.emitCompare(Kind.Int, s34_deoptOccurred, Constant.forInt(0), "ne", false, false);
+                asm.cbr(deoptInProgressLabel);
+            }
             asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(Kind.Int, d16_deoptInfo, config.hsailDeoptOccurredOffset).toAddress());
             asm.emitCompare(Kind.Int, s34_deoptOccurred, Constant.forInt(0), "ne", false, false);
             asm.cbr(deoptInProgressLabel);
@@ -694,11 +704,11 @@
             AllocatableValue waveMathScratch1 = HSAIL.d18.asValue(wordKind);
             AllocatableValue waveMathScratch2 = HSAIL.d19.asValue(wordKind);
 
-            AllocatableValue actionAndReasonReg = HSAIL.s32.asValue(Kind.Int);
-            AllocatableValue codeBufferOffsetReg = HSAIL.s33.asValue(Kind.Int);
+            AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
+            AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
             AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int);
             AllocatableValue workidreg = HSAIL.s35.asValue(Kind.Int);
-            AllocatableValue dregOopMapReg = HSAIL.s39.asValue(Kind.Int);
+            AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int);
 
             HSAILAddress deoptNextIndexAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeoptNextIndex).toAddress();
             HSAILAddress neverRanArrayAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToNeverRanArray).toAddress();
@@ -834,7 +844,7 @@
         compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), config));
     }
 
-    private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List<DeoptimizeOp> deopts, HotSpotProviders providers, HotSpotVMConfig config) {
+    private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List<DeoptimizingOp> deopts, HotSpotProviders providers, HotSpotVMConfig config) {
         if (deopts.isEmpty()) {
             return null;
         }
@@ -848,12 +858,12 @@
         int[] keySuccessors = new int[deopts.size() + 1];
         double[] keyProbabilities = new double[deopts.size() + 1];
         int i = 0;
-        Collections.sort(deopts, new Comparator<DeoptimizeOp>() {
-            public int compare(DeoptimizeOp o1, DeoptimizeOp o2) {
+        Collections.sort(deopts, new Comparator<DeoptimizingOp>() {
+            public int compare(DeoptimizingOp o1, DeoptimizingOp o2) {
                 return o1.getCodeBufferPos() - o2.getCodeBufferPos();
             }
         });
-        for (DeoptimizeOp deopt : deopts) {
+        for (DeoptimizingOp deopt : deopts) {
             keySuccessors[i] = i;
             keyProbabilities[i] = 1.0 / deopts.size();
             keys[i] = deopt.getCodeBufferPos();
@@ -882,7 +892,7 @@
         return BeginNode.begin(vmError);
     }
 
-    private static BeginNode createHostDeoptBranch(DeoptimizeOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers, HotSpotVMConfig config) {
+    private static BeginNode createHostDeoptBranch(DeoptimizingOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers, HotSpotVMConfig config) {
         BeginNode branch = hsailFrame.graph().add(new BeginNode());
         DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(new DynamicDeoptimizeNode(reasonAndAction, speculation));
         deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config));
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java	Thu Apr 17 08:22:21 2014 +0200
@@ -26,21 +26,21 @@
 
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp;
 
 public class HSAILHotSpotLIRGenerationResult extends LIRGenerationResultBase {
 
-    private List<DeoptimizeOp> deopts = new ArrayList<>();
+    private List<DeoptimizingOp> deopts = new ArrayList<>();
 
     public HSAILHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap) {
         super(lir, frameMap);
     }
 
-    public List<DeoptimizeOp> getDeopts() {
+    public List<DeoptimizingOp> getDeopts() {
         return deopts;
     }
 
-    public void addDeopt(DeoptimizeOp deopt) {
+    public void addDeopt(DeoptimizingOp deopt) {
         deopts.add(deopt);
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Thu Apr 17 08:22:21 2014 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.asm.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.hsail.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
@@ -111,6 +112,19 @@
     }
 
     @Override
+    public void visitSafepointNode(SafepointNode i) {
+        HotSpotVMConfig config = getGen().config;
+        if (config.useHSAILSafepoints == true) {
+            LIRFrameState info = gen.state(i);
+            HSAILHotSpotSafepointOp safepoint = new HSAILHotSpotSafepointOp(info, config, this);
+            ((HSAILHotSpotLIRGenerationResult) getGen().getResult()).addDeopt(safepoint);
+            append(safepoint);
+        } else {
+            Debug.log("HSAIL safepoints turned off");
+        }
+    }
+
+    @Override
     public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
         // nop
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java	Thu Apr 17 08:22:21 2014 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.hsail;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.hsail.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hsail.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Emits a safepoint deoptimization from HSA back to CPU.
+ */
+@Opcode("SAFEPOINT")
+public class HSAILHotSpotSafepointOp extends HSAILLIRInstruction implements HSAILControlFlow.DeoptimizingOp {
+    private Constant actionAndReason;
+    @State protected LIRFrameState frameState;
+    protected int codeBufferPos = -1;
+    protected int dregOopMap = 0;
+    final int offsetToNoticeSafepoints;
+
+    public HSAILHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRBuilderTool tool) {
+        actionAndReason = tool.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(DeoptimizationAction.None, DeoptimizationReason.None, 0);
+        frameState = state;
+        offsetToNoticeSafepoints = config.hsailNoticeSafepointsOffset;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+
+        // get a unique codeBuffer position
+        // when we save our state, we will save this as well (it can be used as a key to get the
+        // debugInfo)
+        codeBufferPos = masm.position();
+
+        masm.emitComment(" /* HSAIL safepoint bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */");
+        String afterSafepointLabel = "@LAfterSafepoint_at_pos_" + codeBufferPos;
+
+        AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object);
+        AllocatableValue spAddrReg = HSAIL.d17.asValue(Kind.Object);
+        AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int);
+        masm.emitLoadKernelArg(scratch64, masm.getDeoptInfoName(), "u64");
+
+        // Build address of noticeSafepoints field
+        HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(Kind.Object, scratch64, offsetToNoticeSafepoints).toAddress();
+        masm.emitLoad(Kind.Object, spAddrReg, noticeSafepointsAddr);
+
+        // Load int value from that field
+        HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(Kind.Int, spAddrReg, 0).toAddress();
+        masm.emitLoadAcquire(scratch32, noticeSafepointsIntAddr);
+        masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false);
+        masm.cbr(afterSafepointLabel);
+
+        BytecodeFrame frame = frameState.debugInfo().frame();
+        for (int i = 0; i < frame.numLocals + frame.numStack; i++) {
+            Value val = frame.values[i];
+            if (isLegal(val) && isRegister(val)) {
+                Register reg = asRegister(val);
+                if (val.getKind() == Kind.Object) {
+                    dregOopMap |= 1 << (reg.encoding());
+                }
+            }
+        }
+
+        AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
+        AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
+        AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int);
+        masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason);
+        masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
+        masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap));
+        masm.emitJumpToLabelName(masm.getDeoptLabelName());
+
+        masm.emitString0(afterSafepointLabel + ":\n");
+
+        // now record the debuginfo
+        crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.SAFEPOINT);
+    }
+
+    public LIRFrameState getFrameState() {
+        return frameState;
+    }
+
+    public int getCodeBufferPos() {
+        return codeBufferPos;
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Thu Apr 17 08:22:21 2014 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -52,7 +53,6 @@
 import com.oracle.graal.lir.ptx.*;
 import com.oracle.graal.lir.ptx.PTXMemOp.LoadReturnAddrOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -339,7 +339,7 @@
         Assembler masm = createAssembler(frameMap);
         PTXFrameContext frameContext = new PTXFrameContext();
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
-        crb.setFrameSize(0);
+        crb.setTotalFrameSize(0);
         return crb;
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Apr 17 08:22:21 2014 +0200
@@ -174,7 +174,7 @@
         // On SPARC we always use stack frames.
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
         CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, frameContext, compilationResult);
-        crb.setFrameSize(frameMap.frameSize());
+        crb.setTotalFrameSize(frameMap.totalFrameSize());
         StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
         if (deoptimizationRescueSlot != null && stub == null) {
             crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Apr 17 08:22:21 2014 +0200
@@ -312,7 +312,7 @@
             }
 
             try (TimerCloseable b = CodeInstallationTime.start()) {
-                installedCode = installMethod(result);
+                installedCode = (HotSpotInstalledCode) installMethod(result);
                 if (!isOSR) {
                     ProfilingInfo profile = method.getProfilingInfo();
                     profile.setCompilerIRSize(StructuredGraph.class, graph.getNodeCount());
@@ -385,9 +385,9 @@
                         MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize()));
     }
 
-    private HotSpotInstalledCode installMethod(final CompilationResult compResult) {
+    private InstalledCode installMethod(final CompilationResult compResult) {
         final HotSpotCodeCacheProvider codeCache = backend.getProviders().getCodeCache();
-        HotSpotInstalledCode installedCode = null;
+        InstalledCode installedCode = null;
         try (Scope s = Debug.scope("CodeInstall", new DebugDumpScope(String.valueOf(id), true), codeCache, method)) {
             installedCode = codeCache.installMethod(method, compResult);
         } catch (Throwable e) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Thu Apr 17 08:22:21 2014 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.stack.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
@@ -35,7 +36,6 @@
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.word.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Apr 17 08:22:21 2014 +0200
@@ -1013,11 +1013,13 @@
     @HotSpotVMField(name = "ThreadShadow::_pending_failed_speculation", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingFailedSpeculationOffset;
 
     @HotSpotVMFlag(name = "UseHSAILDeoptimization") @Stable public boolean useHSAILDeoptimization;
+    @HotSpotVMFlag(name = "UseHSAILSafepoints") @Stable public boolean useHSAILSafepoints;
 
     /**
      * Offsets of Hsail deoptimization fields (defined in gpu_hsail.hpp). Used to propagate
      * exceptions from Hsail back to C++ runtime.
      */
+    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_notice_safepoints", type = "jint*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNoticeSafepointsOffset;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[0]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset0;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[1]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset1;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_occurred", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptOccurredOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Apr 17 08:22:21 2014 +0200
@@ -226,7 +226,7 @@
      * @param code the details of the installed CodeBlob are written to this object
      * @return the outcome of the installation as a {@link CodeInstallResult}.
      */
-    CodeInstallResult installCode(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog);
+    CodeInstallResult installCode(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog);
 
     /**
      * Notifies the VM of statistics for a completed compilation.
@@ -240,7 +240,7 @@
      * @param timeUnitsPerSecond the granularity of the units for the {@code time} value
      * @param installedCode the nmethod installed as a result of the compilation
      */
-    void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, HotSpotInstalledCode installedCode);
+    void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode);
 
     void printCompilationStatistics(boolean perCompiler, boolean aggregate);
 
@@ -270,9 +270,9 @@
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
-    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
-    Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    Object executeCompiledMethodVarargs(Object[] args, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
     long[] getLineNumberTable(long metaspaceMethod);
 
@@ -295,7 +295,7 @@
      */
     void reprofile(long metaspaceMethod);
 
-    void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
+    void invalidateInstalledCode(InstalledCode hotspotInstalledCode);
 
     /**
      * Collects the current values of all Graal benchmark counters, summed up over all threads.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Apr 17 08:22:21 2014 +0200
@@ -32,10 +32,10 @@
  */
 public class CompilerToVMImpl implements CompilerToVM {
 
-    private native int installCode0(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog);
+    private native int installCode0(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog);
 
     @Override
-    public CodeInstallResult installCode(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog) {
+    public CodeInstallResult installCode(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog) {
         return CodeInstallResult.getEnum(installCode0(compiledCode, code, speculationLog));
     }
 
@@ -120,7 +120,7 @@
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
     @Override
-    public native Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode);
+    public native Object executeCompiledMethodVarargs(Object[] args, InstalledCode hotspotInstalledCode);
 
     @Override
     public native long[] getLineNumberTable(long metaspaceMethod);
@@ -138,7 +138,7 @@
     public native void reprofile(long metaspaceMethod);
 
     @Override
-    public native void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
+    public native void invalidateInstalledCode(InstalledCode hotspotInstalledCode);
 
     @Override
     public native Class<?> getJavaMirror(long metaspaceKlass);
@@ -150,12 +150,12 @@
     public native void doNotInlineOrCompile(long metaspaceMethod);
 
     @Override
-    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
+    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
         return executeCompiledMethodVarargs(new Object[]{arg1, arg2, arg3}, hotspotInstalledCode);
     }
 
     public synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond,
-                    HotSpotInstalledCode installedCode);
+                    InstalledCode installedCode);
 
     public synchronized native void printCompilationStatistics(boolean perCompiler, boolean aggregate);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Thu Apr 17 08:22:21 2014 +0200
@@ -196,7 +196,7 @@
         return runtime.getConfig().runtimeCallStackSize;
     }
 
-    public HotSpotInstalledCode logOrDump(HotSpotInstalledCode installedCode, CompilationResult compResult) {
+    public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
         if (Debug.isDumpEnabled()) {
             Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
         }
@@ -206,7 +206,7 @@
         return installedCode;
     }
 
-    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
+    public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
         if (compResult.getId() == -1) {
             compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
         }
@@ -216,17 +216,21 @@
     }
 
     @Override
-    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log) {
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
         if (compResult.getId() == -1) {
             compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
         }
-        HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
-        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, hotspotMethod, compResult), code, log);
+        InstalledCode installedCode = predefinedInstalledCode;
+        if (installedCode == null) {
+            HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
+            installedCode = code;
+        }
+        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, hotspotMethod, compResult), installedCode, log);
         if (result != CodeInstallResult.OK) {
             return null;
         }
-        return logOrDump(code, compResult);
+        return logOrDump(installedCode, compResult);
     }
 
     @Override
@@ -273,7 +277,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long codeBlob = ((HotSpotInstalledCode) code).getCodeBlob();
+            long codeBlob = ((HotSpotInstalledCode) code).getAddress();
             return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Thu Apr 17 08:22:21 2014 +0200
@@ -38,7 +38,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long codeBlob = ((HotSpotInstalledCode) code).getCodeBlob();
+            long codeBlob = ((HotSpotInstalledCode) code).getAddress();
             return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Thu Apr 17 08:22:21 2014 +0200
@@ -26,41 +26,28 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.hotspot.*;
+
+import edu.umd.cs.findbugs.annotations.*;
 
 /**
  * Implementation of {@link InstalledCode} for HotSpot.
  */
-public abstract class HotSpotInstalledCode extends CompilerObject implements InstalledCode {
-
-    private static final long serialVersionUID = 156632908220561612L;
-
-    /**
-     * Raw address of this code blob.
-     */
-    private long codeBlob;
+public abstract class HotSpotInstalledCode extends InstalledCode {
 
     /**
      * Total size of the code blob.
      */
-    private int size;
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int size;
 
     /**
      * Start address of the code.
      */
-    private long codeStart;
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private long codeStart;
 
     /**
      * Size of the code.
      */
-    private int codeSize;
-
-    /**
-     * @return the address of this code blob
-     */
-    public long getCodeBlob() {
-        return codeBlob;
-    }
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int codeSize;
 
     /**
      * @return the total size of this code blob
@@ -77,13 +64,14 @@
             return null;
         }
         byte[] blob = new byte[size];
-        unsafe.copyMemory(null, codeBlob, blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size);
+        unsafe.copyMemory(null, getAddress(), blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size);
         return blob;
     }
 
     @Override
     public abstract String toString();
 
+    @Override
     public long getStart() {
         return codeStart;
     }
@@ -92,6 +80,7 @@
         return codeSize;
     }
 
+    @Override
     public byte[] getCode() {
         if (!isValid()) {
             return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Thu Apr 17 08:22:21 2014 +0200
@@ -40,8 +40,6 @@
  */
 public final class HotSpotNmethod extends HotSpotInstalledCode {
 
-    private static final long serialVersionUID = -1784683588947054103L;
-
     /**
      * This (indirect) Method* reference is safe since class redefinition preserves all methods
      * associated with nmethods in the code cache.
@@ -71,24 +69,18 @@
         return isExternal;
     }
 
-    @Override
     public ResolvedJavaMethod getMethod() {
         return method;
     }
 
     @Override
-    public boolean isValid() {
-        return getCodeBlob() != 0;
-    }
-
-    @Override
     public void invalidate() {
         runtime().getCompilerToVM().invalidateInstalledCode(this);
     }
 
     @Override
     public String toString() {
-        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getCodeBlob(), isDefault, name);
+        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getAddress(), isDefault, name);
     }
 
     protected boolean checkThreeObjectArgs() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java	Thu Apr 17 08:22:21 2014 +0200
@@ -32,8 +32,6 @@
  */
 public class HotSpotRuntimeStub extends HotSpotInstalledCode {
 
-    private static final long serialVersionUID = -6388648408298441748L;
-
     private final Stub stub;
 
     public HotSpotRuntimeStub(Stub stub) {
@@ -44,18 +42,21 @@
         return null;
     }
 
+    @Override
     public boolean isValid() {
         return true;
     }
 
+    @Override
     public void invalidate() {
     }
 
     @Override
     public String toString() {
-        return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", stub, getCodeBlob());
+        return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", stub, getAddress());
     }
 
+    @Override
     public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
         throw new GraalInternalError("Cannot call stub %s", stub);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Thu Apr 17 08:22:21 2014 +0200
@@ -161,7 +161,7 @@
                         DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, new CompilationResult(), CompilationResultBuilderFactory.Default);
         InstalledCode installedCode;
         try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) {
-            installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null);
+            installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null, null);
         }
         return installedCode;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Thu Apr 17 08:22:21 2014 +0200
@@ -95,7 +95,7 @@
 
     /**
      * Creates a new stub.
-     * 
+     *
      * @param linkage linkage details for a call to the stub
      */
     public Stub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
@@ -125,8 +125,7 @@
     }
 
     /**
-     * Gets the method the stub's code will be {@linkplain InstalledCode#getMethod() associated}
-     * with once installed. This may be null.
+     * Gets the method the stub's code will be associated with once installed. This may be null.
      */
     protected abstract ResolvedJavaMethod getInstalledCodeOwner();
 
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Thu Apr 17 08:22:21 2014 +0200
@@ -132,7 +132,11 @@
     public static final Register d18 = new Register(82, 18, "d18", CPU);
     public static final Register d19 = new Register(83, 19, "d19", CPU);
     public static final Register d20 = new Register(84, 20, "d20", CPU);
+
     public static final Register threadRegister = d20;
+    public static final Register actionAndReasonReg = s32;
+    public static final Register codeBufferOffsetReg = s33;
+    public static final Register dregOopMapReg = s39;
 
     // @formatter:off
     public static final Register[] cRegisters = {
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java	Thu Apr 17 08:22:21 2014 +0200
@@ -25,6 +25,7 @@
 import java.io.*;
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.java.decompiler.block.*;
 import com.oracle.graal.nodes.cfg.*;
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Apr 17 08:22:21 2014 +0200
@@ -30,10 +30,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.bytecode.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Thu Apr 17 08:22:21 2014 +0200
@@ -129,11 +129,17 @@
         }
     }
 
+    public interface DeoptimizingOp {
+        public LIRFrameState getFrameState();
+
+        public int getCodeBufferPos();
+    }
+
     /***
      * The ALIVE annotation is so we can get a scratch32 register that does not clobber
      * actionAndReason.
      */
-    public static class DeoptimizeOp extends ReturnOp {
+    public static class DeoptimizeOp extends ReturnOp implements DeoptimizingOp {
 
         @Alive({REG, CONST}) protected Value actionAndReason;
         @State protected LIRFrameState frameState;
@@ -173,6 +179,8 @@
             // debugInfo)
             codeBufferPos = masm.position();
 
+            masm.emitComment("/* HSAIL Deoptimization pos=" + codeBufferPos + ", bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */");
+
             // get the bitmap of $d regs that contain references
             ReferenceMap referenceMap = frameState.debugInfo().getReferenceMap();
             for (int dreg = HSAIL.d0.number; dreg <= HSAIL.d15.number; dreg++) {
@@ -181,14 +189,9 @@
                 }
             }
 
-            // here we will by convention use some never-allocated registers to pass to the epilogue
-            // deopt code
-            // todo: define these in HSAIL.java
-            // we need to pass the actionAndReason and the codeBufferPos
-
-            AllocatableValue actionAndReasonReg = HSAIL.s32.asValue(Kind.Int);
-            AllocatableValue codeBufferOffsetReg = HSAIL.s33.asValue(Kind.Int);
-            AllocatableValue dregOopMapReg = HSAIL.s39.asValue(Kind.Int);
+            AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
+            AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
+            AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int);
             masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason);
             masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
             masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap));
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Thu Apr 17 08:22:21 2014 +0200
@@ -27,7 +27,7 @@
 import java.util.*;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.cfg.*;
 
 /**
  * This class performs basic optimizations on the control flow graph after LIR generation.
@@ -49,7 +49,7 @@
     /**
      * Checks whether a block can be deleted. Only blocks with exactly one successor and an
      * unconditional branch to this successor are eligable.
-     * 
+     *
      * @param block the block checked for deletion
      * @return whether the block can be deleted
      */
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,8 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * This class optimizes moves, particularly those that result from eliminating SSA form.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Apr 17 08:22:21 2014 +0200
@@ -25,9 +25,9 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * This class implements the overall container for the LIR graph and directs its construction,
@@ -105,7 +105,7 @@
 
     /**
      * Gets the linear scan ordering of blocks as a list.
-     * 
+     *
      * @return the blocks in linear scan order
      */
     public List<? extends AbstractBlock<?>> linearScanOrder() {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu Apr 17 08:22:21 2014 +0200
@@ -29,12 +29,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-import com.oracle.graal.nodes.cfg.*;
 
 public final class LIRVerifier {
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Thu Apr 17 08:22:21 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.lir;
 
 import com.oracle.graal.asm.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.lir.StandardOp.BranchOp;
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.nodes.cfg.*;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,9 +24,9 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
 import com.oracle.graal.lir.StandardOp.NullCheck;
-import com.oracle.graal.nodes.cfg.*;
 
 public final class NullCheckOptimizer {
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Thu Apr 17 08:22:21 2014 +0200
@@ -28,12 +28,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Removes move instructions, where the destination value is already in place.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Apr 17 08:22:21 2014 +0200
@@ -29,9 +29,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * A collection of machine-independent LIR operations, as well as interfaces to be implemented for
@@ -154,7 +154,7 @@
 
         /**
          * Prunes {@code doNotSave} from the registers saved by this operation.
-         * 
+         *
          * @param doNotSave registers that should not be saved by this operation
          * @return the number of registers pruned
          * @throws UnsupportedOperationException if removal is not {@linkplain #supportsRemove()
@@ -165,7 +165,7 @@
         /**
          * Gets a map from the saved registers saved by this operation to the frame slots in which
          * they are saved.
-         * 
+         *
          * @param frameMap used to {@linkplain FrameMap#indexForStackSlot(StackSlot) convert} a
          *            virtual slot to a frame slot index
          */
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Thu Apr 17 08:22:21 2014 +0200
@@ -30,10 +30,10 @@
 import com.oracle.graal.api.code.CompilationResult.Data;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Fills in a {@link CompilationResult} as its code is being assembled.
@@ -88,8 +88,8 @@
         assert frameContext != null;
     }
 
-    public void setFrameSize(int frameSize) {
-        compilationResult.setFrameSize(frameSize);
+    public void setTotalFrameSize(int frameSize) {
+        compilationResult.setTotalFrameSize(frameSize);
     }
 
     private static final CompilationResult.Mark[] NO_REFS = {};
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Thu Apr 17 08:22:21 2014 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Thu Apr 17 08:22:21 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.loop;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Wed Apr 16 17:55:12 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-import java.util.*;
-
-public interface AbstractBlock<T extends AbstractBlock<T>> {
-
-    int getId();
-
-    Loop<T> getLoop();
-
-    int getLoopDepth();
-
-    boolean isLoopHeader();
-
-    boolean isLoopEnd();
-
-    boolean isExceptionEntry();
-
-    List<T> getPredecessors();
-
-    int getPredecessorCount();
-
-    List<T> getSuccessors();
-
-    int getSuccessorCount();
-
-    int getLinearScanNumber();
-
-    void setLinearScanNumber(int linearScanNumber);
-
-    boolean isAligned();
-
-    void setAlign(boolean align);
-
-    T getDominator();
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlockBase.java	Wed Apr 16 17:55:12 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-import java.util.*;
-
-public abstract class AbstractBlockBase<T extends AbstractBlock<T>> implements AbstractBlock<T> {
-
-    protected int id;
-
-    protected List<T> predecessors;
-    protected List<T> successors;
-
-    protected T dominator;
-
-    private boolean align;
-    private int linearScanNumber;
-
-    protected AbstractBlockBase() {
-        this.id = ControlFlowGraph.BLOCK_ID_INITIAL;
-        this.linearScanNumber = -1;
-    }
-
-    public int getId() {
-        return id;
-    }
-
-    public void setId(int id) {
-        this.id = id;
-    }
-
-    public List<T> getPredecessors() {
-        return predecessors;
-    }
-
-    public List<T> getSuccessors() {
-        return successors;
-    }
-
-    public T getDominator() {
-        return dominator;
-    }
-
-    @Override
-    public String toString() {
-        return "B" + id;
-    }
-
-    public int getPredecessorCount() {
-        return getPredecessors().size();
-    }
-
-    public int getSuccessorCount() {
-        return getSuccessors().size();
-    }
-
-    public int getLinearScanNumber() {
-        return linearScanNumber;
-    }
-
-    public void setLinearScanNumber(int linearScanNumber) {
-        this.linearScanNumber = linearScanNumber;
-    }
-
-    public boolean isAligned() {
-        return align;
-    }
-
-    public void setAlign(boolean align) {
-        this.align = align;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java	Wed Apr 16 17:55:12 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-import java.util.*;
-
-public interface AbstractControlFlowGraph<T extends AbstractBlock<T>> {
-
-    T[] getBlocks();
-
-    Collection<Loop<T>> getLoops();
-
-    T getStartBlock();
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 
@@ -70,11 +71,11 @@
     }
 
     public Block getFirstPredecessor() {
-        return predecessors.get(0);
+        return getPredecessors().get(0);
     }
 
     public Block getFirstSuccessor() {
-        return successors.get(0);
+        return getSuccessors().get(0);
     }
 
     public Block getEarliestPostDominated() {
@@ -167,10 +168,10 @@
         if (block == this) {
             return true;
         }
-        if (dominator == null) {
+        if (getDominator() == null) {
             return false;
         }
-        return dominator.isDominatedBy(block);
+        return getDominator().isDominatedBy(block);
     }
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java	Wed Apr 16 17:55:12 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-public class BlockMap<T> {
-
-    private final T[] data;
-
-    @SuppressWarnings("unchecked")
-    public BlockMap(AbstractControlFlowGraph<?> cfg) {
-        data = (T[]) new Object[cfg.getBlocks().length];
-    }
-
-    public T get(AbstractBlock<?> block) {
-        return data[block.getId()];
-    }
-
-    public void put(AbstractBlock<?> block, T value) {
-        data[block.getId()] = value;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
+
 public class CFGVerifier {
 
     public static boolean verify(ControlFlowGraph cfg) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -117,9 +118,6 @@
         }
     }
 
-    protected static final int BLOCK_ID_INITIAL = -1;
-    protected static final int BLOCK_ID_VISITED = -2;
-
     private void identifyBlock(Block block) {
         Node cur = block.getBeginNode();
         Node last;
@@ -167,16 +165,16 @@
 
         do {
             Block block = stack.get(stack.size() - 1);
-            if (block.id == BLOCK_ID_INITIAL) {
+            if (block.getId() == BLOCK_ID_INITIAL) {
                 // First time we see this block: push all successors.
                 for (Node suxNode : block.getEndNode().cfgSuccessors()) {
                     Block suxBlock = blockFor(suxNode);
-                    if (suxBlock.id == BLOCK_ID_INITIAL) {
+                    if (suxBlock.getId() == BLOCK_ID_INITIAL) {
                         stack.add(suxBlock);
                     }
                 }
-                block.id = BLOCK_ID_VISITED;
-            } else if (block.id == BLOCK_ID_VISITED) {
+                block.setId(BLOCK_ID_VISITED);
+            } else if (block.getId() == BLOCK_ID_VISITED) {
                 // Second time we see this block: All successors have been processed, so add block
                 // to postorder list.
                 stack.remove(stack.size() - 1);
@@ -192,7 +190,7 @@
         reversePostOrder = new Block[numBlocks];
         for (int i = 0; i < numBlocks; i++) {
             Block block = postOrder.get(numBlocks - i - 1);
-            block.id = i;
+            block.setId(i);
             reversePostOrder[i] = block;
         }
     }
@@ -203,32 +201,32 @@
             List<Block> predecessors = new ArrayList<>(4);
             for (Node predNode : block.getBeginNode().cfgPredecessors()) {
                 Block predBlock = nodeToBlock.get(predNode);
-                if (predBlock.id >= 0) {
+                if (predBlock.getId() >= 0) {
                     predecessors.add(predBlock);
                 }
             }
             if (block.getBeginNode() instanceof LoopBeginNode) {
                 for (LoopEndNode predNode : ((LoopBeginNode) block.getBeginNode()).orderedLoopEnds()) {
                     Block predBlock = nodeToBlock.get(predNode);
-                    if (predBlock.id >= 0) {
+                    if (predBlock.getId() >= 0) {
                         predecessors.add(predBlock);
                     }
                 }
             }
-            block.predecessors = predecessors;
+            block.setPredecessors(predecessors);
 
             List<Block> successors = new ArrayList<>(4);
             for (Node suxNode : block.getEndNode().cfgSuccessors()) {
                 Block suxBlock = nodeToBlock.get(suxNode);
-                assert suxBlock.id >= 0;
+                assert suxBlock.getId() >= 0;
                 successors.add(suxBlock);
             }
             if (block.getEndNode() instanceof LoopEndNode) {
                 Block suxBlock = nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin());
-                assert suxBlock.id >= 0;
+                assert suxBlock.getId() >= 0;
                 successors.add(suxBlock);
             }
-            block.successors = successors;
+            block.setSuccessors(successors);
         }
     }
 
@@ -315,7 +313,7 @@
     }
 
     private static void setDominator(Block block, Block dominator) {
-        block.dominator = dominator;
+        block.setDominator(dominator);
         if (dominator.dominated == null) {
             dominator.dominated = new ArrayList<>();
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/HIRLoop.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/HIRLoop.java	Thu Apr 17 08:22:21 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.cfg;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.nodes.*;
 
 public class HIRLoop extends Loop<Block> {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Loop.java	Wed Apr 16 17:55:12 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-import java.util.*;
-
-public abstract class Loop<T extends AbstractBlock<T>> {
-
-    public final Loop<T> parent;
-    public final List<Loop<T>> children;
-
-    public final int depth;
-    public final int index;
-    public final T header;
-    public final List<T> blocks;
-    public final List<T> exits;
-
-    protected Loop(Loop<T> parent, int index, T header) {
-        this.parent = parent;
-        if (parent != null) {
-            this.depth = parent.depth + 1;
-            parent.children.add(this);
-        } else {
-            this.depth = 1;
-        }
-        this.index = index;
-        this.header = header;
-        this.blocks = new ArrayList<>();
-        this.children = new ArrayList<>();
-        this.exits = new ArrayList<>();
-    }
-
-    public abstract long numBackedges();
-
-    @Override
-    public String toString() {
-        return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Thu Apr 17 08:22:21 2014 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Thu Apr 17 08:22:21 2014 +0200
@@ -28,6 +28,7 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Thu Apr 17 08:22:21 2014 +0200
@@ -29,6 +29,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
@@ -649,12 +650,7 @@
          * implies that the inputs' blocks have a total ordering via their dominance relation. So in
          * order to find the earliest block placement for this node we need to find the input block
          * that is dominated by all other input blocks.
-         *
-         * While iterating over the inputs a set of dominator blocks of the current earliest
-         * placement is maintained. When the block of an input is not within this set, it becomes
-         * the current earliest placement and the list of dominator blocks is updated.
          */
-        BitSet dominators = new BitSet(cfg.getBlocks().length);
 
         if (node.predecessor() != null) {
             throw new SchedulingError();
@@ -667,12 +663,24 @@
             } else {
                 inputEarliest = earliestBlock(input);
             }
-            if (!dominators.get(inputEarliest.getId())) {
+            if (earliest == null) {
                 earliest = inputEarliest;
-                do {
-                    dominators.set(inputEarliest.getId());
-                    inputEarliest = inputEarliest.getDominator();
-                } while (inputEarliest != null && !dominators.get(inputEarliest.getId()));
+            } else if (earliest != inputEarliest) {
+                // Find out whether earliest or inputEarliest is earlier.
+                Block a = earliest.getDominator();
+                Block b = inputEarliest;
+                while (true) {
+                    if (a == inputEarliest || b == null) {
+                        // Nothing to change, the previous earliest block is still earliest.
+                        break;
+                    } else if (b == earliest || a == null) {
+                        // New earliest is the earliest.
+                        earliest = inputEarliest;
+                        break;
+                    }
+                    a = a.getDominator();
+                    b = b.getDominator();
+                }
             }
         }
         if (earliest == null) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Thu Apr 17 08:22:21 2014 +0200
@@ -31,6 +31,7 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Thu Apr 17 08:22:21 2014 +0200
@@ -29,6 +29,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.alloc.Interval.UsePosList;
 import com.oracle.graal.compiler.gen.*;
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java	Thu Apr 17 08:22:21 2014 +0200
@@ -31,7 +31,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.amd64.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
@@ -50,22 +49,9 @@
                 AMD64MacroAssembler asm = (AMD64MacroAssembler) this.asm;
                 Register thisRegister = codeCache.getRegisterConfig().getCallingConventionRegisters(Type.JavaCall, Kind.Object)[0];
                 Register spillRegister = AMD64.r10; // TODO(mg): fix me
-                AMD64Address nMethodAddress = new AMD64Address(thisRegister, getFieldOffset("installedCode", OptimizedCallTarget.class));
-                int verifiedEntryPoint = asm.position();
-                if (config.useCompressedOops) {
-                    asm.movl(spillRegister, nMethodAddress);
-                    asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.position() - verifiedEntryPoint));
-                    AMD64HotSpotMove.decodePointer(asm, spillRegister, registers.getHeapBaseRegister(), config.getOopEncoding());
-                } else {
-                    asm.movq(spillRegister, nMethodAddress);
-                    asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.position() - verifiedEntryPoint));
-                }
                 Label doProlog = new Label();
 
-                asm.cmpq(spillRegister, 0);
-                asm.jcc(ConditionFlag.Equal, doProlog);
-
-                AMD64Address codeBlobAddress = new AMD64Address(spillRegister, getFieldOffset("codeBlob", HotSpotInstalledCode.class));
+                AMD64Address codeBlobAddress = new AMD64Address(thisRegister, getFieldOffset("address", InstalledCode.class));
                 asm.movq(spillRegister, codeBlobAddress);
                 asm.cmpq(spillRegister, 0);
                 asm.jcc(ConditionFlag.Equal, doProlog);
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Thu Apr 17 08:22:21 2014 +0200
@@ -154,7 +154,7 @@
         public static final Method METHOD;
         static {
             try {
-                METHOD = RootCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class);
+                METHOD = OptimizedCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class);
             } catch (NoSuchMethodException | SecurityException e) {
                 throw new GraalInternalError(e);
             }
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java	Thu Apr 17 08:22:21 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.truffle.hotspot;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 import static com.oracle.graal.truffle.OptimizedCallTargetLog.*;
 
@@ -53,31 +54,29 @@
     }
 
     public boolean isOptimized() {
-        return installedCode != null || installedCodeTask != null;
+        return isValid() || installedCodeTask != null;
+    }
+
+    @Override
+    public Object call(Object... args) {
+        return callBoundary(args);
     }
 
-    @CompilerDirectives.SlowPath
-    @Override
-    public Object call(Object[] args) {
-        return CompilerDirectives.inInterpreter() ? callHelper(args) : executeHelper(args);
+    @TruffleCallBoundary
+    private Object callBoundary(Object[] args) {
+        if (CompilerDirectives.inInterpreter()) {
+            return compiledCallFallback(args);
+        } else {
+            // We come here from compiled code (i.e., we have been inlined).
+            return executeHelper(args);
+        }
     }
 
-    private Object callHelper(Object[] args) {
-        if (installedCode != null && installedCode.isValid()) {
+    private Object compiledCallFallback(Object[] args) {
+        if (isValid()) {
             reinstallCallMethodShortcut();
         }
-        if (TruffleCallTargetProfiling.getValue()) {
-            callCount++;
-        }
-        if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, installedCode != null)) {
-            try {
-                return installedCode.executeVarargs(new Object[]{this, args});
-            } catch (InvalidInstalledCodeException ex) {
-                return compiledCodeInvalidated(args);
-            }
-        } else {
-            return interpreterCall(args);
-        }
+        return interpreterCall(args);
     }
 
     private static void reinstallCallMethodShortcut() {
@@ -87,17 +86,21 @@
         HotSpotTruffleRuntime.installOptimizedCallTargetCallMethod();
     }
 
-    private Object compiledCodeInvalidated(Object[] args) {
-        invalidate(null, null, "Compiled code invalidated");
-        return call(args);
+    @Override
+    public void invalidate() {
+        runtime().getCompilerToVM().invalidateInstalledCode(this);
+    }
+
+    @Override
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        return runtime().getCompilerToVM().executeCompiledMethodVarargs(args, this);
     }
 
     @Override
     protected void invalidate(Node oldNode, Node newNode, CharSequence reason) {
-        InstalledCode m = this.installedCode;
-        if (m != null) {
+        if (isValid()) {
             CompilerAsserts.neverPartOfCompilation();
-            installedCode = null;
+            invalidate();
             compilationProfile.reportInvalidated();
             logOptimizedInvalidated(this, oldNode, newNode, reason);
         }
@@ -117,15 +120,16 @@
     private Object interpreterCall(Object[] args) {
         CompilerAsserts.neverPartOfCompilation();
         compilationProfile.reportInterpreterCall();
+        if (TruffleCallTargetProfiling.getValue()) {
+            callCount++;
+        }
 
         if (compilationEnabled && compilationPolicy.shouldCompile(compilationProfile)) {
-            InstalledCode code = compile();
-            if (code != null && code.isValid()) {
-                this.installedCode = code;
+            compile();
+            if (isValid()) {
                 try {
-                    return code.executeVarargs(new Object[]{this, args});
+                    return executeVarargs(new Object[]{this, args});
                 } catch (InvalidInstalledCodeException ex) {
-                    return compiledCodeInvalidated(args);
                 }
             }
         }
@@ -135,7 +139,7 @@
     private boolean isCompiling() {
         Future<InstalledCode> codeTask = this.installedCodeTask;
         if (codeTask != null) {
-            if (codeTask.isCancelled()) {
+            if (codeTask.isCancelled() || codeTask.isDone()) {
                 installedCodeTask = null;
                 return false;
             }
@@ -145,20 +149,14 @@
     }
 
     @Override
-    public InstalledCode compile() {
-        if (isCompiling()) {
-            if (installedCodeTask.isDone()) {
-                return receiveInstalledCode();
-            }
-            return null;
-        } else {
+    public void compile() {
+        if (!isCompiling()) {
             performInlining();
             logOptimizingQueued(this);
             this.installedCodeTask = compiler.compile(this);
             if (!TruffleBackgroundCompilation.getValue()) {
-                return receiveInstalledCode();
+                receiveInstalledCode();
             }
-            return null;
         }
     }
 
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Thu Apr 17 08:22:21 2014 +0200
@@ -26,7 +26,6 @@
 import static com.oracle.graal.compiler.GraalCompiler.*;
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -37,7 +36,6 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
@@ -178,24 +176,18 @@
     public static void installOptimizedCallTargetCallMethod() {
         Providers providers = getGraalProviders();
         MetaAccessProvider metaAccess = providers.getMetaAccess();
-        CodeCacheProvider codeCache = providers.getCodeCache();
-        ResolvedJavaMethod resolvedCallMethod = metaAccess.lookupJavaMethod(getCallMethod());
-        CompilationResult compResult = compileMethod(resolvedCallMethod);
-        try (Scope s = Debug.scope("CodeInstall", codeCache, resolvedCallMethod)) {
-            codeCache.setDefaultMethod(resolvedCallMethod, compResult);
+        ResolvedJavaType type = metaAccess.lookupJavaType(HotSpotOptimizedCallTarget.class);
+        for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+            if (method.getAnnotation(TruffleCallBoundary.class) != null) {
+                CompilationResult compResult = compileMethod(method);
+                CodeCacheProvider codeCache = providers.getCodeCache();
+                try (Scope s = Debug.scope("CodeInstall", codeCache, method)) {
+                    codeCache.setDefaultMethod(method, compResult);
+                }
+            }
         }
     }
 
-    private static Method getCallMethod() {
-        Method method;
-        try {
-            method = HotSpotOptimizedCallTarget.class.getDeclaredMethod("call", new Class[]{Object[].class});
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-        return method;
-    }
-
     private static CompilationResultBuilderFactory getOptimizedCallTargetInstrumentationFactory(String arch, ResolvedJavaMethod method) {
         for (OptimizedCallTargetInstrumentationFactory factory : ServiceLoader.loadInstalled(OptimizedCallTargetInstrumentationFactory.class)) {
             if (factory.getArchitecture().equals(arch)) {
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/substitutions/HotSpotOptimizedCallTargetSubstitutions.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/substitutions/HotSpotOptimizedCallTargetSubstitutions.java	Thu Apr 17 08:22:21 2014 +0200
@@ -23,20 +23,9 @@
 package com.oracle.graal.truffle.hotspot.substitutions;
 
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.truffle.*;
 import com.oracle.graal.truffle.hotspot.*;
-import com.oracle.graal.truffle.nodes.asserts.*;
 
 @ClassSubstitution(HotSpotOptimizedCallTarget.class)
 public class HotSpotOptimizedCallTargetSubstitutions {
 
-    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
-    public static native Object callHelper(OptimizedCallTarget target, Object[] args);
-
-    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
-    public static native Object interpreterCall(OptimizedCallTarget target, Object[] args);
-
-    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
-    public static native Object compiledCodeInvalidated(OptimizedCallTarget target, Object[] args);
 }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Thu Apr 17 08:22:21 2014 +0200
@@ -64,7 +64,7 @@
     protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, Object[] arguments) {
         Assumptions assumptions = new Assumptions(true);
         StructuredGraph actual = partialEval(root, arguments, assumptions, true);
-        InstalledCode result = truffleCompiler.compileMethodHelper(actual, assumptions, root.toString(), getSpeculationLog());
+        InstalledCode result = truffleCompiler.compileMethodHelper(actual, assumptions, root.toString(), getSpeculationLog(), null);
         StructuredGraph expected = parseForComparison(methodName);
         removeFrameStates(actual);
         Assert.assertEquals(getCanonicalGraphString(expected, true, true), getCanonicalGraphString(actual, true, true));
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Thu Apr 17 08:22:21 2014 +0200
@@ -59,6 +59,11 @@
         this.name = name;
     }
 
+    @Override
+    public String toString() {
+        return String.format("CompilationProfile(callCount=%d/%d, callAndLoopCount=%d/%d)", callCount, compilationCallThreshold, callAndLoopCount, compilationCallAndLoopThreshold);
+    }
+
     public Map<String, Object> getDebugProperties() {
         Map<String, Object> properties = new LinkedHashMap<>();
         String callsThreshold = String.format("%7d/%5d", getCallCount(), getCompilationCallThreshold());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Thu Apr 17 08:22:21 2014 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.truffle;
 
 import java.lang.ref.*;
-import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.truffle.api.impl.*;
@@ -31,7 +30,13 @@
 
 public final class OptimizedAssumption extends AbstractAssumption {
 
-    List<WeakReference<InstalledCode>> dependentInstalledCode;
+    private static class Entry {
+        WeakReference<InstalledCode> installedCode;
+        long version;
+        Entry next;
+    }
+
+    private Entry first;
 
     public OptimizedAssumption(String name) {
         super(name);
@@ -47,25 +52,26 @@
     @Override
     public synchronized void invalidate() {
         if (isValid) {
-            if (dependentInstalledCode != null) {
-                for (WeakReference<InstalledCode> installedCodeReference : dependentInstalledCode) {
-                    InstalledCode installedCode = installedCodeReference.get();
-                    if (installedCode != null) {
-                        installedCode.invalidate();
-                    }
+            Entry e = first;
+            while (e != null) {
+                InstalledCode installedCode = e.installedCode.get();
+                if (installedCode != null && installedCode.getVersion() == e.version) {
+                    installedCode.invalidate();
                 }
-                dependentInstalledCode = null;
+                e = e.next;
             }
+            first = null;
             isValid = false;
         }
     }
 
     public synchronized void registerInstalledCode(InstalledCode installedCode) {
         if (isValid) {
-            if (dependentInstalledCode == null) {
-                dependentInstalledCode = new ArrayList<>();
-            }
-            dependentInstalledCode.add(new WeakReference<>(installedCode));
+            Entry e = new Entry();
+            e.installedCode = new WeakReference<>(installedCode);
+            e.version = installedCode.getVersion();
+            e.next = first;
+            first = e;
         } else {
             installedCode.invalidate();
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Apr 17 08:22:21 2014 +0200
@@ -33,17 +33,15 @@
 import com.oracle.graal.debug.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
 
 /**
  * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
  */
-public abstract class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, ReplaceObserver {
+public abstract class OptimizedCallTarget extends InstalledCode implements RootCallTarget, LoopCountReceiver, ReplaceObserver {
 
     protected static final PrintStream OUT = TTY.out().out();
 
-    protected InstalledCode installedCode;
     protected boolean compilationEnabled;
     protected int callCount;
     protected boolean inliningPerformed;
@@ -52,8 +50,16 @@
     private OptimizedCallTarget splitSource;
     private final AtomicInteger callSitesKnown = new AtomicInteger(0);
 
+    private final RootNode rootNode;
+
+    public final RootNode getRootNode() {
+        return rootNode;
+    }
+
     public OptimizedCallTarget(RootNode rootNode, int invokeCounter, int compilationThreshold, boolean compilationEnabled, CompilationPolicy compilationPolicy) {
-        super(rootNode);
+        this.rootNode = rootNode;
+        this.rootNode.adoptChildren();
+        this.rootNode.setCallTarget(this);
         this.compilationEnabled = compilationEnabled;
         this.compilationPolicy = compilationPolicy;
         this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter, rootNode.toString());
@@ -62,6 +68,15 @@
         }
     }
 
+    protected final Object callProxy(VirtualFrame frame) {
+        try {
+            return getRootNode().execute(frame);
+        } finally {
+            // this assertion is needed to keep the values from being cleared as non-live locals
+            assert frame != null && this != null;
+        }
+    }
+
     public final int getKnownCallSiteCount() {
         return callSitesKnown.get();
     }
@@ -84,8 +99,8 @@
 
     @Override
     public String toString() {
-        String superString = super.toString();
-        if (installedCode != null) {
+        String superString = rootNode.toString();
+        if (isValid()) {
             superString += " <compiled>";
         }
         if (splitSource != null) {
@@ -99,9 +114,9 @@
     }
 
     @Override
-    public abstract Object call(Object[] args);
+    public abstract Object call(Object... args);
 
-    public abstract InstalledCode compile();
+    public abstract void compile();
 
     public final Object callInlined(Object[] arguments) {
         if (CompilerDirectives.inInterpreter()) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java	Thu Apr 17 08:22:21 2014 +0200
@@ -266,7 +266,7 @@
             }
 
             int nodeCount = OptimizedCallUtils.countNonTrivialNodes(callTarget, true);
-            String comment = callTarget.installedCode == null ? " int" : "";
+            String comment = callTarget.isValid() ? "" : " int";
             comment += callTarget.compilationEnabled ? "" : " fail";
             OUT.printf("%-50s | %10d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, nodeCount, nodeCount, callTarget.getCompilationProfile().getInvalidationCount(), comment);
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Apr 17 08:22:21 2014 +0200
@@ -201,7 +201,7 @@
                         }
 
                         StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
-                        if (inlineGraph == null && !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers())) {
+                        if (inlineGraph == null && !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().canBeInlined()) {
                             inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, false);
                         }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Thu Apr 17 08:22:21 2014 +0200
@@ -264,9 +264,10 @@
     }
 
     private boolean shouldInline(final MethodCallTargetNode methodCallTargetNode) {
-        return (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) &&
+        boolean result = (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && methodCallTargetNode.targetMethod().canBeInlined() &&
                         !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null &&
                         methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null &&
                         !methodCallTargetNode.targetMethod().getDeclaringClass().equals(stringBuilderClass);
+        return result;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallBoundary.java	Thu Apr 17 08:22:21 2014 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface TruffleCallBoundary {
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Apr 17 08:22:21 2014 +0200
@@ -151,18 +151,14 @@
 
         long timePartialEvaluationFinished = System.nanoTime();
         int nodeCountPartialEval = graph.getNodeCount();
-        InstalledCode compiledMethod = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog());
+        InstalledCode compiledMethod = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog(), compilable);
         long timeCompilationFinished = System.nanoTime();
         int nodeCountLowered = graph.getNodeCount();
 
-        if (compiledMethod == null) {
+        if (!compiledMethod.isValid()) {
             throw new BailoutException("Could not install method, code cache is full!");
         }
 
-        if (!compiledMethod.isValid()) {
-            return null;
-        }
-
         if (TraceTruffleCompilation.getValue()) {
             byte[] code = compiledMethod.getCode();
             int calls = OptimizedCallUtils.countCalls(compilable);
@@ -188,7 +184,7 @@
         return sourceSection != null ? sourceSection.toString() : "n/a";
     }
 
-    public InstalledCode compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog) {
+    public InstalledCode compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode) {
         try (Scope s = Debug.scope("TruffleFinal")) {
             Debug.dump(graph, "After TruffleTier");
         } catch (Throwable e) {
@@ -224,7 +220,7 @@
 
         InstalledCode installedCode;
         try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); TimerCloseable a = CodeInstallationTime.start()) {
-            installedCode = providers.getCodeCache().addMethod(graph.method(), result, speculationLog);
+            installedCode = providers.getCodeCache().addMethod(graph.method(), result, speculationLog, predefinedInstalledCode);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Thu Apr 17 08:22:21 2014 +0200
@@ -26,6 +26,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Thu Apr 17 08:22:21 2014 +0200
@@ -30,7 +30,7 @@
 
 /**
  * <h3>Creating a Root Node</h3>
- * 
+ *
  * <p>
  * A Truffle root node is the entry point into a Truffle tree that represents a guest language
  * method. It contains a {@link RootNode#execute(VirtualFrame)} method that can return a
@@ -38,9 +38,9 @@
  * must however never be called directly. Instead, the Truffle runtime must be used to create a
  * {@link CallTarget} object from a root node using the
  * {@link TruffleRuntime#createCallTarget(RootNode)} method. This call target object can then be
- * executed using the {@link CallTarget#call()} method or one of its overloads.
+ * executed using the {@link CallTarget#call(Object...)} method or one of its overloads.
  * </p>
- * 
+ *
  * <p>
  * The next part of the Truffle API introduction is at
  * {@link com.oracle.truffle.api.test.ChildNodeTest}.
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Thu Apr 17 08:22:21 2014 +0200
@@ -27,9 +27,7 @@
 /**
  * Represents the target of a call.
  */
-public abstract class CallTarget {
-
-    public static final Object[] NO_ARGUMENTS = new Object[0];
+public interface CallTarget {
 
     /**
      * Calls this target as a root method..
@@ -37,11 +35,5 @@
      * @param arguments passed arguments as an object array
      * @return the return result of the call
      */
-    public abstract Object call(Object[] arguments);
-
-    public final Object call() {
-        return call(NO_ARGUMENTS);
-    }
-
-    public abstract void setNeedsMaterializedFrame();
+    Object call(Object... arguments);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Thu Apr 17 08:22:21 2014 +0200
@@ -24,38 +24,13 @@
  */
 package com.oracle.truffle.api;
 
-import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
 /**
  * Represents the target of a call to a {@link RootNode}, i.e., to another tree of nodes. Instances
  * of this class can be created using {@link TruffleRuntime#createCallTarget(RootNode)}.
  */
-public abstract class RootCallTarget extends CallTarget {
-
-    private final RootNode rootNode;
-
-    public RootCallTarget(RootNode function) {
-        this.rootNode = function;
-        this.rootNode.adoptChildren();
-        this.rootNode.setCallTarget(this);
-    }
+public interface RootCallTarget extends CallTarget {
 
-    @Override
-    public String toString() {
-        return rootNode.toString();
-    }
-
-    public final RootNode getRootNode() {
-        return rootNode;
-    }
-
-    protected final Object callProxy(VirtualFrame frame) {
-        try {
-            return getRootNode().execute(frame);
-        } finally {
-            // this assertion is needed to keep the values from being cleared as non-live locals
-            assert frame != null && this != null;
-        }
-    }
+    RootNode getRootNode();
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Wed Apr 16 17:55:12 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Thu Apr 17 08:22:21 2014 +0200
@@ -25,7 +25,6 @@
 package com.oracle.truffle.api.impl;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
@@ -33,22 +32,28 @@
  * This is an implementation-specific class. Do not use or instantiate it. Instead, use
  * {@link TruffleRuntime#createCallTarget(RootNode)} to create a {@link RootCallTarget}.
  */
-public class DefaultCallTarget extends RootCallTarget {
+public class DefaultCallTarget implements RootCallTarget {
+
+    private final RootNode rootNode;
 
-    @CompilationFinal protected boolean needsMaterializedFrame = true;
-
-    protected DefaultCallTarget(RootNode function) {
-        super(function);
+    public DefaultCallTarget(RootNode function) {
+        this.rootNode = function;
+        this.rootNode.adoptChildren();
+        this.rootNode.setCallTarget(this);
     }
 
     @Override
-    public Object call(Object[] args) {
-        VirtualFrame frame = new DefaultVirtualFrame(getRootNode().getFrameDescriptor(), args);
-        return callProxy(frame);
+    public String toString() {
+        return rootNode.toString();
+    }
+
+    public final RootNode getRootNode() {
+        return rootNode;
     }
 
     @Override
-    public void setNeedsMaterializedFrame() {
-        needsMaterializedFrame = true;
+    public Object call(Object... args) {
+        VirtualFrame frame = new DefaultVirtualFrame(getRootNode().getFrameDescriptor(), args);
+        return getRootNode().execute(frame);
     }
 }
--- a/make/linux/makefiles/buildtree.make	Wed Apr 16 17:55:12 2014 +0200
+++ b/make/linux/makefiles/buildtree.make	Thu Apr 17 08:22:21 2014 +0200
@@ -258,6 +258,10 @@
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
+	echo "$(call gamma-path,altsrc,gpu/ptx/vm) \\"; \
+	echo "$(call gamma-path,commonsrc,gpu/ptx/vm)" \\; \
+	echo "$(call gamma-path,altsrc,gpu/hsail/vm) \\"; \
+	echo "$(call gamma-path,commonsrc,gpu/hsail/vm) \\"; \
 	echo "$(call gamma-path,altsrc,gpu) \\"; \
 	echo "$(call gamma-path,commonsrc,gpu)"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
--- a/make/linux/makefiles/vm.make	Wed Apr 16 17:55:12 2014 +0200
+++ b/make/linux/makefiles/vm.make	Thu Apr 17 08:22:21 2014 +0200
@@ -185,8 +185,10 @@
 
 GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/graal)
 GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/ptx/vm)
+GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/hsail/vm)
 GRAAL_PATHS += $(HS_COMMON_SRC)/share/vm/graal
 GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/ptx/vm
+GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/hsail/vm
 
 # Include dirs per type.
 Src_Dirs/CORE      := $(CORE_PATHS)
--- a/mx/mx_graal.py	Wed Apr 16 17:55:12 2014 +0200
+++ b/mx/mx_graal.py	Thu Apr 17 08:22:21 2014 +0200
@@ -1404,7 +1404,16 @@
             f.write(json.dumps(results))
 
 def jmh(args):
-    """run the JMH_BENCHMARKS"""
+    """run the JMH_BENCHMARKS
+
+    The benchmarks are running with the default VM.
+    You can override this with an explicit option.
+    For example:
+
+        mx jmh -server ...
+
+    Will force the benchmarks to be run with the server VM.
+"""
 
     # TODO: add option for `mvn clean package'
 
@@ -1413,7 +1422,7 @@
     benchmarks = [b for b in benchmarksAndJsons if not b.startswith('{')]
     jmhArgJsons = [b for b in benchmarksAndJsons if b.startswith('{')]
 
-    jmhArgs = {'-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'}
+    jmhArgs = {'-rff' : join(_graal_home, 'mx', 'jmh', 'jmh.out'), '-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'}
 
     # e.g. '{"-wi" : 20}'
     for j in jmhArgJsons:
@@ -1427,18 +1436,54 @@
             mx.abort('error parsing JSON input: {}"\n{}'.format(j, e))
 
     jmhPath = mx.get_env('JMH_BENCHMARKS', None)
-    if not jmhPath or not exists(jmhPath):
-        mx.abort("$JMH_BENCHMARKS not properly defined: " + str(jmhPath))
+    if not jmhPath:
+        probe = join(dirname(_graal_home), 'java-benchmarks')
+        if exists(probe):
+            jmhPath = probe
+
+    if not jmhPath:
+        mx.abort("Please set the JMH_BENCHMARKS environment variable to point to the java-benchmarks workspace")
+    if not exists(jmhPath):
+        mx.abort("The directory denoted by the JMH_BENCHMARKS environment variable does not exist: " + jmhPath)
+    mx.log('Using benchmarks in ' + jmhPath)
 
-    def _blackhole(x):
-        mx.logv(x[:-1])
+    timestamp = mx.TimeStampFile(join(_graal_home, 'mx', 'jmh', jmhPath.replace(os.sep, '_') + '.timestamp'))
+    buildJmh = False
+    jmhTree = []
+    for root, dirnames, filenames in os.walk(jmhPath):
+        if root == jmhPath:
+            for n in ['.hg', '.metadata']:
+                if n in dirnames:
+                    dirnames.remove(n)
+        jmhTree.append(os.path.relpath(root, jmhPath) + ':')
+        jmhTree = jmhTree + filenames
+        jmhTree.append('')
 
+        files = [join(root, f) for f in filenames]
+        if timestamp.isOlderThan(files):
+            buildJmh = True
 
-    env = os.environ.copy()
-    env['JAVA_HOME'] = _jdk(vmToCheck='graal')
-    env['MAVEN_OPTS'] = '-graal'
-    mx.log("Building benchmarks...")
-    mx.run(['mvn', 'package'], cwd=jmhPath, out=_blackhole, env=env)
+    if not buildJmh:
+        with open(timestamp.path) as fp:
+            oldJmhTree = fp.read().split('\n')
+            if oldJmhTree != jmhTree:
+                import difflib
+                diff = difflib.unified_diff(oldJmhTree, jmhTree)
+                mx.log("Need to rebuild JMH due to change in JMH directory tree indicated by this diff:")
+                mx.log('\n'.join(diff))
+                buildJmh = True
+
+    if buildJmh:
+        def _blackhole(x):
+            mx.logv(x[:-1])
+        env = os.environ.copy()
+        env['JAVA_HOME'] = _jdk(vmToCheck='graal')
+        env['MAVEN_OPTS'] = '-graal'
+        mx.log("Building benchmarks...")
+        mx.run(['mvn', 'package'], cwd=jmhPath, out=_blackhole, env=env)
+        timestamp.touch()
+        with open(timestamp.path, 'w') as fp:
+            fp.write('\n'.join(jmhTree))
 
     matchedSuites = set()
     numBench = [0]
--- a/mx/projects	Wed Apr 16 17:55:12 2014 +0200
+++ b/mx/projects	Thu Apr 17 08:22:21 2014 +0200
@@ -283,7 +283,7 @@
 # graal.lir
 project@com.oracle.graal.lir@subDir=graal
 project@com.oracle.graal.lir@sourceDirs=src
-project@com.oracle.graal.lir@dependencies=com.oracle.graal.asm,com.oracle.graal.nodes
+project@com.oracle.graal.lir@dependencies=com.oracle.graal.nodes,com.oracle.graal.asm
 project@com.oracle.graal.lir@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir@javaCompliance=1.8
 project@com.oracle.graal.lir@workingSets=Graal,LIR
@@ -373,7 +373,7 @@
 # graal.nodes
 project@com.oracle.graal.nodes@subDir=graal
 project@com.oracle.graal.nodes@sourceDirs=src
-project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements
+project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements,com.oracle.graal.cfg
 project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.nodes@javaCompliance=1.8
 project@com.oracle.graal.nodes@annotationProcessors=com.oracle.graal.replacements.verifier
@@ -499,6 +499,14 @@
 project@com.oracle.graal.java@javaCompliance=1.8
 project@com.oracle.graal.java@workingSets=Graal,Java
 
+# graal.cfg
+project@com.oracle.graal.cfg@subDir=graal
+project@com.oracle.graal.cfg@sourceDirs=src
+project@com.oracle.graal.cfg@dependencies=
+project@com.oracle.graal.cfg@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.cfg@javaCompliance=1.8
+project@com.oracle.graal.cfg@workingSets=Graal,Java
+
 # graal.baseline
 project@com.oracle.graal.baseline@subDir=graal
 project@com.oracle.graal.baseline@sourceDirs=src
@@ -737,7 +745,7 @@
 # graal.truffle.hotspot.amd64
 project@com.oracle.graal.truffle.hotspot.amd64@subDir=graal
 project@com.oracle.graal.truffle.hotspot.amd64@sourceDirs=src
-project@com.oracle.graal.truffle.hotspot.amd64@dependencies=com.oracle.graal.truffle.hotspot,com.oracle.graal.hotspot.amd64
+project@com.oracle.graal.truffle.hotspot.amd64@dependencies=com.oracle.graal.truffle.hotspot,com.oracle.graal.asm.amd64
 project@com.oracle.graal.truffle.hotspot.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.truffle.hotspot.amd64@javaCompliance=1.8
 project@com.oracle.graal.truffle.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor
--- a/src/cpu/x86/vm/graalCodeInstaller_x86.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/cpu/x86/vm/graalCodeInstaller_x86.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+#include "precompiled.hpp"
 #include "compiler/disassembler.hpp"
 #include "runtime/javaCalls.hpp"
 #include "graal/graalEnv.hpp"
--- a/src/gpu/hsail/vm/gpu_hsail.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/gpu/hsail/vm/gpu_hsail.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -71,6 +71,7 @@
 };
 
 void * Hsail::_device_context = NULL;
+jint   Hsail::_notice_safepoints = false;
 
 Hsail::okra_create_context_func_t  Hsail::_okra_create_context;
 Hsail::okra_create_kernel_func_t   Hsail::_okra_create_kernel;
@@ -122,6 +123,18 @@
 
 static Stats kernelStats;
 
+//static jint in_kernel = 0;
+
+void Hsail::notice_safepoints() {
+  _notice_safepoints = true;
+//  if (TraceGPUInteraction) {
+//    tty->print_cr("[HSAIL] Notice safepoint in_kernel=%d", in_kernel);
+//  }
+}
+
+void Hsail::ignore_safepoints() {
+  _notice_safepoints = false;
+}
 
 void Hsail::register_heap() {
   // After the okra functions are set up and the heap is initialized, register the java heap with HSA
@@ -137,7 +150,7 @@
                                                       jobject donor_threads, jint allocBytesPerWorkitem))
 
   ResourceMark rm;
-  jlong nmethodValue = HotSpotInstalledCode::codeBlob(kernel_handle);
+  jlong nmethodValue = InstalledCode::address(kernel_handle);
   if (nmethodValue == 0) {
     SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
   }
@@ -203,8 +216,7 @@
 }
 
 
-
-jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oops_save,
+jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oops_save, 
                                                 jobject donor_threads, int allocBytesPerWorkitem, TRAPS) {
   ResourceMark rm(THREAD);
   objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args);
@@ -258,6 +270,9 @@
 
   // This object sets up the kernel arguments
   HSAILKernelArguments hka((address) kernel, mh->signature(), argsArray, mh->is_static(), e);
+  if (TraceGPUInteraction) {
+    tty->print_cr("[HSAIL] range=%d", dimX);
+  }
 
   // if any object passed was null, throw an exception here
   // doing this means the kernel code can avoid null checks on the object parameters.
@@ -273,8 +288,12 @@
   // Run the kernel
   bool success = false;
   {
-    TraceTime t1("execute kernel", TraceGPUInteraction);
+    TraceTime t("execute kernel", TraceGPUInteraction);
+
+    //in_kernel = 1;
+    // Run the kernel
     success = _okra_execute_with_range(kernel, dimX);
+    //in_kernel = 0;
   }
 
   // fix up any tlab tops that overflowed
@@ -297,17 +316,23 @@
   }
 
   if (UseHSAILDeoptimization) {
+    kernelStats.incDeopts();
     // check if any workitem requested a deopt
     // currently we only support at most one such workitem
     int deoptcode = e->deopt_occurred();
-    if (deoptcode != 0) {
-      if (deoptcode != 1) {
+    if (deoptcode != 1) {
+      if (deoptcode == 0) {
+        if (TraceGPUInteraction && _notice_safepoints != 0) {
+          tty->print_cr("[HSAIL] observed safepoint during kernel");
+        }
+      } else {
         // error condition detected in deopt code
         char msg[200];
         sprintf(msg, "deopt error detected, slot for workitem %d was not empty", -1 * (deoptcode + 1));
         guarantee(deoptcode == 1, msg);
       }
-      kernelStats.incDeopts();
+    } else {
+
       {
         TraceTime t3("handle deoptimizing workitems", TraceGPUInteraction);
         if (TraceGPUInteraction) {
@@ -402,48 +427,47 @@
           tty->print_cr("[HSAIL] Deoptimizing to host completed for %d workitems", count_deoptimized);
         }
       }
-
-      {
-        TraceTime t3("handle never-rans", TraceGPUInteraction);
+    }
 
-        // Handle any never_ran workitems if there were any
-        int count_never_ran = 0;
-        bool handleNeverRansHere = true;
-        // turn off verbose trace stuff for javacall arg setup
-        bool savedTraceGPUInteraction = TraceGPUInteraction;
-        TraceGPUInteraction = false;
-        jboolean *never_ran_array = e->never_ran_array();
-        if (handleNeverRansHere) {
-          for (int k = 0; k < dimX; k++) {
-            if (never_ran_array[k]) {
-              // run it as a javaCall
-              KlassHandle methKlass = mh->method_holder();
-              Thread* THREAD = Thread::current();
-              JavaValue result(T_VOID);
-              JavaCallArguments javaArgs;
-              // re-resolve the args_handle here
-              objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args);
-              // This object sets up the javaCall arguments
-              // the way argsArray is set up, this should work for instance methods as well
-              // (the receiver will be the first oop pushed)
-              HSAILJavaCallArguments hjca(&javaArgs, k, mh->signature(), resolvedArgsArray, mh->is_static());
-              if (mh->is_static()) {
-                JavaCalls::call_static(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD);
-              } else {
-                JavaCalls::call_virtual(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD);
-              }
-              count_never_ran++;
+    // Handle any never_ran workitems if there were any
+    {
+      TraceTime t("handle never-rans ", TraceGPUInteraction);
+      int count_never_ran = 0;
+      bool handleNeverRansHere = true;
+      // turn off verbose trace stuff for javacall arg setup
+      bool savedTraceGPUInteraction = TraceGPUInteraction;
+      TraceGPUInteraction = false;
+      jboolean *never_ran_array = e->never_ran_array();
+      if (handleNeverRansHere) {
+        for (int k = 0; k < dimX; k++) {
+          if (never_ran_array[k]) {
+            // run it as a javaCall
+            KlassHandle methKlass = mh->method_holder();
+            Thread* THREAD = Thread::current();
+            JavaValue result(T_VOID);
+            JavaCallArguments javaArgs;
+            // re-resolve the args_handle here
+            objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args);
+            // This object sets up the javaCall arguments
+            // the way argsArray is set up, this should work for instance methods as well
+            // (the receiver will be the first oop pushed)
+            HSAILJavaCallArguments hjca(&javaArgs, k, mh->signature(), resolvedArgsArray, mh->is_static());
+            if (mh->is_static()) {
+              JavaCalls::call_static(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD);
+            } else {
+              JavaCalls::call_virtual(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD);
             }
+            count_never_ran++;
           }
-          TraceGPUInteraction = savedTraceGPUInteraction;
-          if (TraceGPUInteraction) {
-            tty->print_cr("%d workitems never ran, have been run via JavaCall", count_never_ran);
-            showRanges(never_ran_array, dimX);
-          }
-        } // end of never-ran handling
-      }
+        }
+        TraceGPUInteraction = savedTraceGPUInteraction;
+        if (TraceGPUInteraction) {
+          tty->print_cr("%d workitems never ran, have been run via JavaCall", count_never_ran);
+          showRanges(never_ran_array, dimX);
+        }
+      } // end of never-ran handling
     }
-    
+
     FREE_C_HEAP_ARRAY(jboolean, e->never_ran_array(), mtInternal);
     delete e;
   }
@@ -547,7 +571,7 @@
   LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap);
   // if we made it this far, real success
 
-  gpu::initialized_gpu("Okra");
+  Gpu::initialized_gpu(new Hsail());
 
   return true;
 GPU_END
--- a/src/gpu/hsail/vm/gpu_hsail.hpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/gpu/hsail/vm/gpu_hsail.hpp	Thu Apr 17 08:22:21 2014 +0200
@@ -27,11 +27,9 @@
 
 #include "utilities/exceptions.hpp"
 #include "graal/graalEnv.hpp"
-// #include "graal/graalCodeInstaller.hpp"
 #include "gpu_hsail_Frame.hpp"
 
-class Hsail {
-  friend class gpu;
+class Hsail : public Gpu {
 
   public:
   class HSAILKernelDeoptimization {
@@ -58,6 +56,7 @@
   class HSAILDeoptimizationInfo : public ResourceObj {
     friend class VMStructs;
    private:
+    jint* _notice_safepoints;
     jint _deopt_occurred;
     jint _deopt_next_index;
     JavaThread** _donor_threads;
@@ -67,12 +66,12 @@
     HSAILKernelDeoptimization _deopt_save_states[MAX_DEOPT_SAVE_STATES_SIZE];
 
     inline HSAILDeoptimizationInfo() {
+      _notice_safepoints = &Hsail::_notice_safepoints;
       _deopt_occurred = 0;
       _deopt_next_index = 0;
     }
 
     inline jint deopt_occurred() {
-      // Check that hsail did not write in the wrong place
       return _deopt_occurred;
     }
     inline jint num_deopts() { return _deopt_next_index; }
@@ -102,8 +101,8 @@
   static void getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, size_t tlabMinHsail);
 
   static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oopsSave,
-                                                  jobject donorThreads, int allocBytesPerWorkitem, TRAPS);
-
+                                                  jobject donor_threads, int allocBytesPerWorkitem, TRAPS);
+  
   static void register_heap();
 
   static GraalEnv::CodeInstallResult install_code(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations);
@@ -113,6 +112,11 @@
   // Registers the implementations for the native methods in HSAILHotSpotBackend
   static bool register_natives(JNIEnv* env);
 
+  virtual const char* name() { return "HSAIL"; }
+
+  virtual void notice_safepoints();
+  virtual void ignore_safepoints();
+
 #if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
   typedef unsigned long long CUdeviceptr;
 #else
@@ -149,5 +153,8 @@
   
 protected:
   static void* _device_context;
+
+  // true if safepoints are activated
+  static jint _notice_safepoints;
 };
 #endif // GPU_HSAIL_HPP
--- a/src/gpu/hsail/vm/vmStructs_hsail.hpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp	Thu Apr 17 08:22:21 2014 +0200
@@ -41,6 +41,7 @@
   nonstatic_field(Hsail::HSAILKernelDeoptimization, _actionAndReason,                           jint)                                 \
   nonstatic_field(Hsail::HSAILKernelDeoptimization, _first_frame,                               HSAILFrame)                           \
                                                                                                                                       \
+  nonstatic_field(Hsail::HSAILDeoptimizationInfo, _notice_safepoints,                      jint*)                                     \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_occurred,                         jint)                                      \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_next_index,                       jint)                                      \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _donor_threads,                          JavaThread**)                              \
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -271,7 +271,7 @@
     tty->print_cr("[CUDA] Success: Created context for device: %d", _cu_device);
   }
 
-  gpu::initialized_gpu(device_name);
+  Gpu::initialized_gpu(new Ptx());
 
   return true;
 GPU_END
--- a/src/gpu/ptx/vm/gpu_ptx.hpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.hpp	Thu Apr 17 08:22:21 2014 +0200
@@ -93,7 +93,7 @@
 
 #define GRAAL_SUPPORTED_COMPUTE_CAPABILITY_VERSION 3.0
 
-class Ptx {
+class Ptx : public Gpu {
   friend class PtxCall;
 
 private:
@@ -120,6 +120,9 @@
   static int ncores(int major, int minor);
 
 public:
+
+  virtual const char* name() { return "PTX"; }
+
   // Registers the implementations for the native methods in PTXHotSpotBackend
   static bool register_natives(JNIEnv* env);
 
--- a/src/os/bsd/vm/gpu_bsd.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/os/bsd/vm/gpu_bsd.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -27,7 +27,7 @@
 #include "hsail/vm/gpu_hsail.hpp"
 #include "utilities/ostream.hpp"
 
-jobject gpu::probe_gpus(JNIEnv* env) {
+jobject Gpu::probe_gpus(JNIEnv* env) {
 #ifdef __APPLE__
   /*
    * Let the CUDA driver initialization be the gate to GPU for now, pending
--- a/src/os/linux/vm/gpu_linux.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/os/linux/vm/gpu_linux.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -38,7 +38,7 @@
 
 #define PCI_DRIVER_NAME_START_POS 255
 
-jobject gpu::probe_gpus(JNIEnv* env) {
+jobject Gpu::probe_gpus(JNIEnv* env) {
   bool hsail = false;
   bool ptx = false;
 
--- a/src/os/windows/vm/gpu_windows.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/os/windows/vm/gpu_windows.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -27,7 +27,7 @@
 #include "hsail/vm/gpu_hsail.hpp"
 #include "utilities/ostream.hpp"
 
-jobject gpu::probe_gpus(JNIEnv* env) {
+jobject Gpu::probe_gpus(JNIEnv* env) {
   // TODO: add detection of PTX/NVidia
   if (Hsail::register_natives(env)) {
     return env->NewStringUTF("HSAIL");
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Apr 17 08:22:21 2014 +0200
@@ -230,6 +230,7 @@
   do_klass(CompilationResult_Site_klass,          com_oracle_graal_api_code_CompilationResult_Site,             Opt) \
   do_klass(ExternalCompilationResult_klass,       com_oracle_graal_gpu_ExternalCompilationResult,               Opt) \
   do_klass(InfopointReason_klass,                 com_oracle_graal_api_code_InfopointReason,                    Opt) \
+  do_klass(InstalledCode_klass,                   com_oracle_graal_api_code_InstalledCode,                      Opt) \
   do_klass(code_Register_klass,                   com_oracle_graal_api_code_Register,                           Opt) \
   do_klass(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Opt) \
   do_klass(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Apr 17 08:22:21 2014 +0200
@@ -347,6 +347,7 @@
   template(com_oracle_graal_api_code_CompilationResult_Infopoint,    "com/oracle/graal/api/code/CompilationResult$Infopoint")         \
   template(com_oracle_graal_api_code_CompilationResult_Site,         "com/oracle/graal/api/code/CompilationResult$Site")              \
   template(com_oracle_graal_api_code_InfopointReason,                "com/oracle/graal/api/code/InfopointReason")                     \
+  template(com_oracle_graal_api_code_InstalledCode,                  "com/oracle/graal/api/code/InstalledCode")                       \
   template(com_oracle_graal_api_code_BytecodeFrame,                  "com/oracle/graal/api/code/BytecodeFrame")                       \
   template(com_oracle_graal_api_code_BytecodePosition,               "com/oracle/graal/api/code/BytecodePosition")                    \
   template(com_oracle_graal_api_code_DebugInfo,                      "com/oracle/graal/api/code/DebugInfo")                           \
--- a/src/share/vm/code/nmethod.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/code/nmethod.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -1330,7 +1330,7 @@
   // Java wrapper is no longer alive. Here we need to clear out this weak
   // reference to the dead object.
   if (_graal_installed_code != NULL) {
-    HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0);
+    InstalledCode::set_address(_graal_installed_code, 0);
     _graal_installed_code = NULL;
   }
 #endif
@@ -1510,8 +1510,8 @@
   }
 #ifdef GRAAL
   if (_graal_installed_code != NULL) {
-    // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely.
-    HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0);
+    // Break the link between nmethod and InstalledCode such that the nmethod can subsequently be flushed safely.
+    InstalledCode::set_address(_graal_installed_code, 0);
   }
 #endif
 
@@ -1738,7 +1738,7 @@
 #ifdef GRAAL
   // Follow Graal method
   if (_graal_installed_code != NULL) {
-    if (HotSpotNmethod::isDefault(_graal_installed_code)) {
+    if (_graal_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_graal_installed_code)) {
       if (!is_alive->do_object_b(_graal_installed_code)) {
         _graal_installed_code = NULL;
       }
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -455,8 +455,7 @@
 
   _code = (arrayOop) CompilationResult::targetCode(comp_result);
   _code_size = CompilationResult::targetCodeSize(comp_result);
-  // The frame size we get from the target method does not include the return address, so add one word for it here.
-  _total_frame_size = CompilationResult::frameSize(comp_result) + HeapWordSize;  // FIXME this is an x86-ism
+  _total_frame_size = CompilationResult::totalFrameSize(comp_result);
   _custom_stack_area_offset = CompilationResult::customStackAreaOffset(comp_result);
 
   // Pre-calculate the constants section size.  This is required for PC-relative addressing.
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -210,6 +210,7 @@
 #undef set_boolean
 #undef set_int
 #undef set_long
+#undef set_address
 
 C2V_END
 
@@ -530,15 +531,16 @@
     assert(cb == NULL, "should be");
   } else {
     if (!installed_code_handle.is_null()) {
-      assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type");
-      HotSpotInstalledCode::set_codeBlob(installed_code_handle, (jlong) cb);
+      assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
+      InstalledCode::set_address(installed_code_handle, (jlong) cb);
+      InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
       oop comp_result = HotSpotCompiledCode::comp(compiled_code_handle);
       if (comp_result->is_a(ExternalCompilationResult::klass())) {
         if (TraceGPUInteraction) {
           tty->print_cr("installCode0: ExternalCompilationResult");
         }
         HotSpotInstalledCode::set_codeStart(installed_code_handle, ExternalCompilationResult::entryPoint(comp_result));
-      } else {
+      } else if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
         HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
         HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
         HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
@@ -560,8 +562,10 @@
     stats->_standard.update(timer, processedBytecodes);
   }
   Handle installed_code_handle = JNIHandles::resolve(installed_code);
-  stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle);
-  stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle);
+  if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
+    stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle);
+    stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle);
+  }
 
   if (CITimeEach) {
     methodHandle method = asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hotspot_method));
@@ -633,7 +637,7 @@
   ResourceMark rm;
   HandleMark hm;
 
-  jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode);
+  jlong nmethodValue = InstalledCode::address(hotspotInstalledCode);
   if (nmethodValue == 0L) {
     THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
   }
@@ -724,14 +728,14 @@
 
 
 C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jobject hotspotInstalledCode))
-  jlong nativeMethod = HotSpotInstalledCode::codeBlob(hotspotInstalledCode);
+  jlong nativeMethod = InstalledCode::address(hotspotInstalledCode);
   nmethod* m = (nmethod*)nativeMethod;
   if (m != NULL && !m->is_not_entrant()) {
     m->mark_for_deoptimization();
     VM_Deoptimize op;
     VMThread::execute(&op);
   }
-  HotSpotInstalledCode::set_codeBlob(hotspotInstalledCode, 0);
+  InstalledCode::set_address(hotspotInstalledCode, 0);
 C2V_END
 
 C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv *env, jobject, jlong metaspace_klass))
@@ -753,7 +757,7 @@
 
 C2V_ENTRY(jobject, getGPUs, (JNIEnv *env, jobject))
 #if defined(TARGET_OS_FAMILY_bsd) || defined(TARGET_OS_FAMILY_linux) || defined(TARGET_OS_FAMILY_windows)
-  return gpu::probe_gpus(env);
+  return Gpu::probe_gpus(env);
 #else
   return env->NewStringUTF("");
 #endif
@@ -1040,7 +1044,7 @@
 #define RESOLVED_METHOD       "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;"
 #define HS_COMPILED_CODE      "Lcom/oracle/graal/hotspot/HotSpotCompiledCode;"
 #define HS_CONFIG             "Lcom/oracle/graal/hotspot/HotSpotVMConfig;"
-#define HS_INSTALLED_CODE     "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;"
+#define INSTALLED_CODE        "Lcom/oracle/graal/api/code/InstalledCode;"
 #define NODE_CLASS            "Lcom/oracle/graal/graph/NodeClass;"
 #define HS_STACK_FRAME_REF    "Lcom/oracle/graal/hotspot/HotSpotStackFrameReference;"
 #define METASPACE_KLASS       "J"
@@ -1080,17 +1084,17 @@
   {CC"getMaxCallTargetOffset",                       CC"(J)J",                                                         FN_PTR(getMaxCallTargetOffset)},
   {CC"getMetaspaceMethod",                           CC"("CLASS"I)"METASPACE_METHOD,                                   FN_PTR(getMetaspaceMethod)},
   {CC"initializeConfiguration",                      CC"("HS_CONFIG")V",                                               FN_PTR(initializeConfiguration)},
-  {CC"installCode0",                                 CC"("HS_COMPILED_CODE HS_INSTALLED_CODE SPECULATION_LOG")I",      FN_PTR(installCode0)},
-  {CC"notifyCompilationStatistics",                  CC"(I"HS_RESOLVED_METHOD"ZIJJ"HS_INSTALLED_CODE")V",              FN_PTR(notifyCompilationStatistics)},
+  {CC"installCode0",                                 CC"("HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I",         FN_PTR(installCode0)},
+  {CC"notifyCompilationStatistics",                  CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V",                 FN_PTR(notifyCompilationStatistics)},
   {CC"printCompilationStatistics",                   CC"(ZZ)V",                                                        FN_PTR(printCompilationStatistics)},
   {CC"resetCompilationStatistics",                   CC"()V",                                                          FN_PTR(resetCompilationStatistics)},
   {CC"disassembleCodeBlob",                          CC"(J)"STRING,                                                    FN_PTR(disassembleCodeBlob)},
-  {CC"executeCompiledMethodVarargs",                 CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT,                          FN_PTR(executeCompiledMethodVarargs)},
+  {CC"executeCompiledMethodVarargs",                 CC"(["OBJECT INSTALLED_CODE")"OBJECT,                             FN_PTR(executeCompiledMethodVarargs)},
   {CC"getLineNumberTable",                           CC"("METASPACE_METHOD")[J",                                       FN_PTR(getLineNumberTable)},
   {CC"getLocalVariableTableStart",                   CC"("METASPACE_METHOD")J",                                        FN_PTR(getLocalVariableTableStart)},
   {CC"getLocalVariableTableLength",                  CC"("METASPACE_METHOD")I",                                        FN_PTR(getLocalVariableTableLength)},
   {CC"reprofile",                                    CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
-  {CC"invalidateInstalledCode",                      CC"("HS_INSTALLED_CODE")V",                                       FN_PTR(invalidateInstalledCode)},
+  {CC"invalidateInstalledCode",                      CC"("INSTALLED_CODE")V",                                          FN_PTR(invalidateInstalledCode)},
   {CC"getJavaMirror",                                CC"("METASPACE_KLASS")"CLASS,                                     FN_PTR(getJavaMirror)},
   {CC"readUnsafeKlassPointer",                       CC"("OBJECT")J",                                                  FN_PTR(readUnsafeKlassPointer)},
   {CC"collectCounters",                              CC"()[J",                                                         FN_PTR(collectCounters)},
--- a/src/share/vm/graal/graalEnv.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/graal/graalEnv.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -515,7 +515,7 @@
       // (Put nm into the task handle *before* publishing to the Java heap.)
       if (task != NULL)  task->set_code(nm);
 
-      if (HotSpotNmethod::isDefault(installed_code())) {
+      if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) {
         if (entry_bci == InvocationEntryBci) {
           if (TieredCompilation) {
             // If there is an old version we're done with it
--- a/src/share/vm/graal/graalGlobals.hpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/graal/graalGlobals.hpp	Thu Apr 17 08:22:21 2014 +0200
@@ -88,6 +88,9 @@
   product(bool, UseHSAILDeoptimization, true,                               \
           "Code gen and runtime support for deoptimizing HSAIL kernels")    \
                                                                             \
+  product(bool, UseHSAILSafepoints, true,                                   \
+          "Code gen and runtime support for safepoints in HSAIL kernels")   \
+                                                                            \
   product(bool, GPUOffload, false,                                          \
           "Offload execution to GPU whenever possible")                     \
                                                                             \
--- a/src/share/vm/graal/graalJavaAccess.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -63,7 +63,7 @@
 
 void graal_compute_offsets() {
   COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD)
-  guarantee(HotSpotInstalledCode::_codeBlob_offset == sizeof(oopDesc), "codeBlob must be first field!");
+  guarantee(InstalledCode::_address_offset == sizeof(oopDesc), "codeBlob must be first field!");
 }
 
 #define EMPTY0
--- a/src/share/vm/graal/graalJavaAccess.hpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Apr 17 08:22:21 2014 +0200
@@ -49,7 +49,7 @@
 
 #define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field)                \
   start_class(HotSpotResolvedObjectType)                                                                                                                       \
-    oop_field(HotSpotResolvedObjectType, javaClass, "Ljava/lang/Class;")                                                                                      \
+    oop_field(HotSpotResolvedObjectType, javaClass, "Ljava/lang/Class;")                                                                                       \
   end_class                                                                                                                                                    \
   start_class(HotSpotResolvedJavaMethod)                                                                                                                       \
     oop_field(HotSpotResolvedJavaMethod, name, "Ljava/lang/String;")                                                                                           \
@@ -59,8 +59,11 @@
   start_class(HotSpotJavaType)                                                                                                                                 \
     oop_field(HotSpotJavaType, name, "Ljava/lang/String;")                                                                                                     \
   end_class                                                                                                                                                    \
+  start_class(InstalledCode)                                                                                                                                   \
+    long_field(InstalledCode, address)                                                                                                                         \
+    long_field(InstalledCode, version)                                                                                                                         \
+  end_class                                                                                                                                                    \
   start_class(HotSpotInstalledCode)                                                                                                                            \
-    long_field(HotSpotInstalledCode, codeBlob)                                                                                                                 \
     int_field(HotSpotInstalledCode, size)                                                                                                                      \
     long_field(HotSpotInstalledCode, codeStart)                                                                                                                \
     int_field(HotSpotInstalledCode, codeSize)                                                                                                                  \
@@ -113,7 +116,7 @@
     long_field(ExternalCompilationResult, entryPoint)                                                                                                          \
   end_class                                                                                                                                                    \
   start_class(CompilationResult)                                                                                                                               \
-    int_field(CompilationResult, frameSize)                                                                                                                    \
+    int_field(CompilationResult, totalFrameSize)                                                                                                               \
     int_field(CompilationResult, customStackAreaOffset)                                                                                                        \
     oop_field(CompilationResult, targetCode, "[B")                                                                                                             \
     oop_field(CompilationResult, assumptions, "Lcom/oracle/graal/api/code/Assumptions;")                                                                       \
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -1485,7 +1485,10 @@
 #ifdef GRAAL
         oop installedCode = nm->graal_installed_code();
         if (installedCode != NULL) {
-          oop installedCodeName = HotSpotNmethod::name(installedCode);
+          oop installedCodeName = NULL;
+          if (installedCode->is_a(HotSpotNmethod::klass())) {
+            installedCodeName = HotSpotNmethod::name(installedCode);
+          }
           if (installedCodeName != NULL) {
             tty->print(" (Graal: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName));
           } else {
--- a/src/share/vm/runtime/gpu.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/runtime/gpu.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -26,11 +26,24 @@
 #include "runtime/gpu.hpp"
 #include "runtime/handles.hpp"
 
-int gpu::_initialized_gpus = 0;
+int  Gpu::_initialized_gpus_count = 0;
+Gpu* Gpu::_initialized_gpus[MAX_GPUS];
 
-void gpu::initialized_gpu(const char* name) {
-    _initialized_gpus++;
-    if (TraceGPUInteraction) {
-      tty->print_cr("[GPU] registered initialization of %s (total initialized: %d)", name, _initialized_gpus);
+void Gpu::initialized_gpu(Gpu* gpu) {
+  // GPUs are always initialized on the same thread so no need for locking
+  guarantee(_initialized_gpus_count < MAX_GPUS, "oob");
+  if (TraceGPUInteraction) {
+    tty->print_cr("[GPU] registered initialization of %s (total initialized: %d)", gpu->name(), _initialized_gpus);
+  }
+  _initialized_gpus[_initialized_gpus_count++] = gpu;
+}
+
+void Gpu::safepoint_event(SafepointEvent event) {
+  for (int i = 0; i < _initialized_gpus_count; i++) {
+    if (event == SafepointBegin) {
+      _initialized_gpus[i]->notice_safepoints();
+    } else {
+      _initialized_gpus[i]->ignore_safepoints();
     }
+  }
 }
--- a/src/share/vm/runtime/gpu.hpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/runtime/gpu.hpp	Thu Apr 17 08:22:21 2014 +0200
@@ -29,21 +29,41 @@
 #include "oops/symbol.hpp"
 #include "utilities/array.hpp"
 
+#define MAX_GPUS 2
+
 // Defines the interface to the graphics processor(s).
-class gpu : AllStatic {
+class Gpu {
  private:
-  static int _initialized_gpus;  // number of initialize GPU devices
+  static int _initialized_gpus_count;
+  static Gpu* _initialized_gpus[MAX_GPUS];
 
  public:
 
   // Notification of a GPU device that has been initialized.
-  static void initialized_gpu(const char* name);
+  static void initialized_gpu(Gpu* gpu);
 
   // Gets a comma separated list of supported GPU architecture names.
   static jobject probe_gpus(JNIEnv* env);
   
   // Gets the number of GPU devices that have been initialized.
-  static int initialized_gpus() { return _initialized_gpus; }
+  static int initialized_gpus() { return _initialized_gpus_count; }
+
+  enum SafepointEvent {
+    SafepointBegin,
+    SafepointEnd
+  };
+
+  // Called when a safepoint has been activated.
+  static void safepoint_event(SafepointEvent event);
+
+  // Name of this GPU
+  virtual const char* name() = 0;
+
+  // Called when a safepoint has been activated.
+  virtual void notice_safepoints() {};
+
+  // Called when a safepoint has been deactivated.
+  virtual void ignore_safepoints() {};
 };
 
 #endif // SHARE_VM_RUNTIME_GPU_HPP
--- a/src/share/vm/runtime/javaCalls.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -412,7 +412,7 @@
     if (nm->is_alive()) {
       ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point());
       oop graalInstalledCode = nm->graal_installed_code();
-      if (graalInstalledCode != NULL && HotSpotNmethod::isExternal(graalInstalledCode)) {
+      if (graalInstalledCode != NULL && graalInstalledCode->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isExternal(graalInstalledCode)) {
         entry_point = GraalCompiler::instance()->get_external_deopt_i2c_entry();
       } else {
       entry_point = method->adapter()->get_i2c_entry();
--- a/src/share/vm/runtime/safepoint.cpp	Wed Apr 16 17:55:12 2014 +0200
+++ b/src/share/vm/runtime/safepoint.cpp	Thu Apr 17 08:22:21 2014 +0200
@@ -39,6 +39,7 @@
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"
+#include "runtime/gpu.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/osThread.hpp"
@@ -205,6 +206,12 @@
     os::make_polling_page_unreadable();
   }
 
+#ifdef GRAAL
+  if (UseHSAILSafepoints) {
+    Gpu::safepoint_event(Gpu::SafepointBegin);
+  }
+#endif
+  
   // Consider using active_processor_count() ... but that call is expensive.
   int ncpus = os::processor_count() ;
 
@@ -438,6 +445,12 @@
   // Remove safepoint check from interpreter
   Interpreter::ignore_safepoints();
 
+#ifdef GRAAL
+  if (UseHSAILSafepoints) {
+    Gpu::safepoint_event(Gpu::SafepointEnd);
+  }
+#endif
+
   {
     MutexLocker mu(Safepoint_lock);