changeset 15482:a250a512434d

HSAIL: support for object values in stack slots at deoptimization points Contributed-by: Tom Deneau <tom.deneau@amd.com>
author Doug Simon <doug.simon@oracle.com>
date Fri, 02 May 2014 21:58:28 +0200
parents 09d721bcffe2
children 2e56c2096ac5
files graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/ForceDeoptSubstitutions.java graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DVec3.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptBase.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany20000Test.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany5000Test.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany99999Test.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptManyBase.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost20000Test.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost5000Test.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost99999Test.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMostBase.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptSingle100Test.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptSingle20000Test.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillBoundsCatchOneTest.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillBoundsCatchTest.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java src/gpu/hsail/vm/gpu_hsail.cpp src/gpu/hsail/vm/gpu_hsail.hpp src/gpu/hsail/vm/gpu_hsail_Frame.hpp src/gpu/hsail/vm/vmStructs_hsail.hpp src/share/vm/runtime/vmStructs.cpp
diffstat 36 files changed, 1511 insertions(+), 350 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Fri May 02 21:58:28 2014 +0200
@@ -190,16 +190,9 @@
         emitString("st_spill_" + getArgTypeFromKind(kind) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSizeFromKind(kind)) + ";");
     }
 
-    /**
-     * The mapping to stack slots is always relative to the beginning of the spillseg.
-     * HSAIL.getStackOffset returns the positive version of the originally negative offset. Then we
-     * back up from that by the argSize in bytes. This ensures that slots of different size do not
-     * overlap, even though we have converted from negative to positive offsets.
-     */
     public static String mapStackSlot(Value reg, int argSize) {
-        long offset = HSAIL.getStackOffset(reg);
-        int argSizeBytes = argSize / 8;
-        return "[%spillseg]" + "[" + (offset - argSizeBytes) + "]";
+        long startOffset = HSAIL.getStackOffsetStart(reg, argSize);
+        return "[%spillseg]" + "[" + startOffset + "]";
     }
 
     public void cbr(String target1) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/ForceDeoptSubstitutions.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test.infra;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.api.meta.*;
+
+@ClassSubstitution(GraalKernelTester.class)
+class ForceDeoptSubstitutions {
+
+    /**
+     * Allows us to force a non-exception throwing deopt from java code.
+     */
+    @MethodSubstitution
+    public static int forceDeopt(int x) {
+        DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        // will never get here but keep the compiler happy
+        return x * x;
+    }
+
+    @MethodSubstitution
+    public static double forceDeopt(double x) {
+        DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        // will never get here but keep the compiler happy
+        return x * x;
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Fri May 02 21:58:28 2014 +0200
@@ -50,8 +50,18 @@
 
 public abstract class GraalKernelTester extends KernelTester {
 
+    private static boolean substitutionsInstalled;
+
+    private static synchronized void installSubstitutions() {
+        if (!substitutionsInstalled) {
+            getHSAILBackend().getProviders().getReplacements().registerSubstitutions(ForceDeoptSubstitutions.class);
+            substitutionsInstalled = true;
+        }
+    }
+
     public GraalKernelTester() {
         super(getHSAILBackend().isDeviceInitialized());
+        installSubstitutions();
     }
 
     protected static HSAILHotSpotBackend getHSAILBackend() {
@@ -193,4 +203,14 @@
             super.testGeneratedHsailUsingLambdaMethod();
         }
     }
+
+    // used for forcing a deoptimization
+    public static int forceDeopt(int x) {
+        return x * x;
+    }
+
+    public static double forceDeopt(double x) {
+        return x * x;
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DVec3.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.compiler.hsail.test;
+
+/**
+ * A simple 3 element Vector object used in some junit tests.
+ */
+public class DVec3 {
+
+    public DVec3(double x, double y, double z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    public double x;
+    public double y;
+    public double z;
+
+    public static DVec3 add(DVec3 a, DVec3 b) {
+        return new DVec3(a.x + b.x, a.y + b.y, a.z + b.z);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof DVec3)) {
+            return false;
+        }
+        DVec3 oth = (DVec3) other;
+        return (oth.x == x && oth.y == y && oth.z == z);
+    }
+
+    @Override
+    public String toString() {
+        return ("DVec3[" + x + ", " + y + ", " + z + "]");
+    }
+
+    @Override
+    public int hashCode() {
+        return (int) (x + y + z);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptBase.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import java.util.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Base class for testing deopt when objects are in stack slots.
+ */
+public abstract class ObjSpillDeoptBase extends GraalKernelTester {
+
+    abstract int getSize();
+
+    int loopcount = 5;
+    int objcount = 20;
+    @Result double[] out = new double[getSize()];
+    @Result double[] aux = new double[getSize()];
+    DVec3[] in = new DVec3[objcount];
+
+    public void doCompute(int gid, boolean causeDeopt) {
+        int idx = gid * 2 + 7;
+        DVec3 v0 = in[(idx++) % objcount];
+        DVec3 v1 = in[(idx++) % objcount];
+        DVec3 v2 = in[(idx++) % objcount];
+        DVec3 v3 = in[(idx++) % objcount];
+        DVec3 v4 = in[(idx++) % objcount];
+        DVec3 v5 = in[(idx++) % objcount];
+        DVec3 v6 = in[(idx++) % objcount];
+        DVec3 v7 = in[(idx++) % objcount];
+        DVec3 v8 = in[(idx++) % objcount];
+        DVec3 v9 = in[(idx++) % objcount];
+        idx += gid;
+        DVec3 v10 = in[(idx++) % objcount];
+        DVec3 v11 = in[(idx++) % objcount];
+        DVec3 v12 = in[(idx++) % objcount];
+        DVec3 v13 = in[(idx++) % objcount];
+        DVec3 v14 = in[(idx++) % objcount];
+        DVec3 v15 = in[(idx++) % objcount];
+        DVec3 v16 = in[(idx++) % objcount];
+        DVec3 v17 = in[(idx++) % objcount];
+        DVec3 v18 = in[(idx++) % objcount];
+        DVec3 v19 = in[(idx++) % objcount];
+        double sum = 0.0;
+        double sum1 = 0.0;
+        double sum2 = 0.0;
+        for (int i = 0; i < loopcount; i++) {
+            sum1 += v0.x + v1.y + v2.z + v3.x + v4.y + v5.z + v6.x + v7.y + v8.z + v9.x + i;
+            sum2 += v10.y + v11.z + v12.x + v13.y + v14.z + v15.x + v16.y + v17.z + v18.x + v19.y - i;
+            sum += sum1 - sum2 + i;
+            aux[gid] += sum1 + 1.2345;
+        }
+        if (causeDeopt) {
+            aux[gid] += forceDeopt(sum1);
+        }
+        out[gid] += sum;
+    }
+
+    @Override
+    public void runTest() {
+        Arrays.fill(out, -1.0);
+        for (int i = 0; i < objcount; i++) {
+            in[i] = new DVec3(i / 10f, (i + 1) / 10f, (i + 2) / 10f);
+        }
+        dispatchMethodKernel(getSize());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany20000Test.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests deopt with objects in stack slots, with many items deopting.
+ */
+public class ObjSpillDeoptMany20000Test extends ObjSpillDeoptManyBase {
+
+    @Override
+    int getSize() {
+        return 20000;
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany5000Test.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests deopt with objects in stack slots, with many items deopting.
+ */
+public class ObjSpillDeoptMany5000Test extends ObjSpillDeoptManyBase {
+
+    @Override
+    int getSize() {
+        return 5000;
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany99999Test.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests deopt with objects in stack slots, with many items deopting.
+ */
+public class ObjSpillDeoptMany99999Test extends ObjSpillDeoptManyBase {
+
+    @Override
+    int getSize() {
+        return 99999;
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptManyBase.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+/**
+ * Base class for testing deopt with objects in stack slots, with many items deopting.
+ */
+public abstract class ObjSpillDeoptManyBase extends ObjSpillDeoptBase {
+
+    public void run(int gid) {
+        boolean causeDeopt = (gid < 4096 && gid % 512 == 1);
+        doCompute(gid, causeDeopt);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost20000Test.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests deopt with objects in stack slots, with most items deopting.
+ */
+public class ObjSpillDeoptMost20000Test extends ObjSpillDeoptMostBase {
+
+    @Override
+    int getSize() {
+        return 20000;
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost5000Test.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests deopt with objects in stack slots, with most items deopting.
+ */
+public class ObjSpillDeoptMost5000Test extends ObjSpillDeoptMostBase {
+
+    @Override
+    int getSize() {
+        return 5000;
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost99999Test.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests deopt with objects in stack slots, with most items deopting.
+ */
+public class ObjSpillDeoptMost99999Test extends ObjSpillDeoptMostBase {
+
+    @Override
+    int getSize() {
+        return 99999;
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMostBase.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+/**
+ * Base class for testing deopt with objects in stack slots.
+ */
+public abstract class ObjSpillDeoptMostBase extends ObjSpillDeoptBase {
+
+    public void run(int gid) {
+        boolean causeDeopt = (gid % 500 != 1);
+        doCompute(gid, causeDeopt);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptSingle100Test.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests deopt with objects in stack slots, one item deopting.
+ */
+public class ObjSpillDeoptSingle100Test extends ObjSpillDeoptBase {
+
+    final int size = 100;
+
+    @Override
+    int getSize() {
+        return size;
+    }
+
+    public void run(int gid) {
+        boolean causeDeopt = (gid == size / 2);
+        doCompute(gid, causeDeopt);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptSingle20000Test.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests deopt with objects in stack slots, one item deopting.
+ */
+public class ObjSpillDeoptSingle20000Test extends ObjSpillDeoptBase {
+
+    final int size = 20000;
+
+    @Override
+    int getSize() {
+        return size;
+    }
+
+    public void run(int gid) {
+        boolean causeDeopt = (gid == size / 2);
+        doCompute(gid, causeDeopt);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillBoundsCatchOneTest.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests the spilling of double variables into memory with deopt
+ */
+public class StaticDoubleSpillBoundsCatchOneTest extends GraalKernelTester {
+
+    static final int size = 100;
+    private double[] in = new double[size * 400];
+    @Result public double[] out = new double[size * 400];
+    @Result public double[] aux = new double[2];
+
+    public static void run(double[] out, double[] in, double[] aux, int gid) {
+        int id = gid;
+        int step = 20;
+        double sum0;
+        double sum1;
+        double sum2;
+        double sum3;
+        double sum4;
+        double sum5;
+        double sum6;
+        double sum7;
+        double sum8;
+        double sum9;
+        double sum10;
+        double sum11;
+        double sum12;
+        double sum13;
+        double sum14;
+        double sum15;
+        double sum16;
+        double sum17;
+        double sum18;
+        double sum19;
+        sum0 = sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = sum7 = sum8 = sum9 = 0;
+        sum10 = sum11 = sum12 = sum13 = sum14 = sum15 = sum16 = sum17 = sum18 = sum19 = 0;
+        try {
+            for (int i = 0; i < size; i += step) {
+                sum0 += in[i + 0];
+                sum1 += in[i + 1];
+                sum2 += in[i + 2];
+                sum3 += in[i + 3];
+                sum4 += in[i + 4];
+                sum5 += in[i + 5];
+                sum6 += in[i + 6];
+                sum7 += in[i + 7];
+                sum8 += in[i + 8];
+                sum9 += in[i + 9];
+                sum10 += in[i + 0];
+                sum11 += in[i + 1];
+                sum12 += in[i + 2];
+                sum13 += in[i + 3];
+                sum14 += in[i + 4];
+                sum15 += in[i + 5];
+                sum16 += in[i + 6];
+                sum17 += in[i + 7];
+                sum18 += in[i + 8];
+                sum19 += in[i + 9];
+
+                if (id == size / 2) {
+                    aux[id] = sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7 + sum8 + sum9 + sum10 + sum11 + sum12 + sum13 + sum14 + sum15 + sum16;
+                }
+            }
+        } catch (ArrayIndexOutOfBoundsException e) {
+            aux[0] += sum1 + sum2;
+        }
+
+        out[id * step + 0] = sum0;
+        out[id * step + 1] = sum1;
+        out[id * step + 2] = sum2;
+        out[id * step + 3] = sum3;
+        out[id * step + 4] = sum4;
+        out[id * step + 5] = sum5;
+        out[id * step + 6] = sum6;
+        out[id * step + 7] = sum7;
+        out[id * step + 8] = sum8;
+        out[id * step + 9] = sum9;
+        out[id * step + 10] = sum10;
+        out[id * step + 11] = sum11;
+        out[id * step + 12] = sum12;
+        out[id * step + 13] = sum13;
+        out[id * step + 14] = sum14;
+        out[id * step + 15] = sum15;
+        out[id * step + 16] = sum16;
+        out[id * step + 17] = sum17;
+        out[id * step + 18] = sum18;
+        out[id * step + 19] = sum19;
+    }
+
+    @Override
+    public void runTest() {
+        /**
+         * Call it for a range, specifying testmethod args (but not the fields it uses or the gid
+         * argument).
+         * 
+         */
+        Arrays.fill(out, -1f);
+        for (int i = 0; i < size; i++) {
+            in[i] = i + 1;
+        }
+        dispatchMethodKernel(size, out, in, aux);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillBoundsCatchTest.java	Fri May 02 21:58:28 2014 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests the spilling of double variables into memory with deopt
+ */
+public class StaticDoubleSpillBoundsCatchTest extends GraalKernelTester {
+
+    static final int size = 100;
+    private double[] in = new double[size * 400];
+    @Result public double[] out = new double[size * 400];
+    @Result public double[] aux = new double[size];
+
+    public static void run(double[] out, double[] in, double[] aux, int gid) {
+        int id = gid;
+        int step = 20;
+        double sum0;
+        double sum1;
+        double sum2;
+        double sum3;
+        double sum4;
+        double sum5;
+        double sum6;
+        double sum7;
+        double sum8;
+        double sum9;
+        double sum10;
+        double sum11;
+        double sum12;
+        double sum13;
+        double sum14;
+        double sum15;
+        double sum16;
+        double sum17;
+        double sum18;
+        double sum19;
+        sum0 = sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = sum7 = sum8 = sum9 = 0;
+        sum10 = sum11 = sum12 = sum13 = sum14 = sum15 = sum16 = sum17 = sum18 = sum19 = 0;
+        try {
+            for (int i = 0; i < size; i += step) {
+                sum0 += in[i + 0];
+                sum1 += in[i + 1];
+                sum2 += in[i + 2];
+                sum3 += in[i + 3];
+                sum4 += in[i + 4];
+                sum5 += in[i + 5];
+                sum6 += in[i + 6];
+                sum7 += in[i + 7];
+                sum8 += in[i + 8];
+                sum9 += in[i + 9];
+                sum10 += in[i + 0];
+                sum11 += in[i + 1];
+                sum12 += in[i + 2];
+                sum13 += in[i + 3];
+                sum14 += in[i + 4];
+                sum15 += in[i + 5];
+                sum16 += in[i + 6];
+                sum17 += in[i + 7];
+                sum18 += in[i + 8];
+                sum19 += in[i + 9];
+
+                if (id > size / 2) {
+                    aux[id + 10] += sum1 + sum2;
+                    // + sum3 + sum4 + sum5 + sum6 + sum7 + sum8 + sum9 + sum10 + sum11 + sum12 +
+                    // sum13 + sum14 + sum15 + sum16;
+                }
+            }
+        } catch (ArrayIndexOutOfBoundsException e) {
+            aux[id] += sum1 + sum2;
+        }
+
+        out[id * step + 0] = sum0;
+        out[id * step + 1] = sum1;
+        out[id * step + 2] = sum2;
+        out[id * step + 3] = sum3;
+        out[id * step + 4] = sum4;
+        out[id * step + 5] = sum5;
+        out[id * step + 6] = sum6;
+        out[id * step + 7] = sum7;
+        out[id * step + 8] = sum8;
+        out[id * step + 9] = sum9;
+        out[id * step + 10] = sum10;
+        out[id * step + 11] = sum11;
+        out[id * step + 12] = sum12;
+        out[id * step + 13] = sum13;
+        out[id * step + 14] = sum14;
+        out[id * step + 15] = sum15;
+        out[id * step + 16] = sum16;
+        out[id * step + 17] = sum17;
+        out[id * step + 18] = sum18;
+        out[id * step + 19] = sum19;
+    }
+
+    @Override
+    public void runTest() {
+        /**
+         * Call it for a range, specifying testmethod args (but not the fields it uses or the gid
+         * argument).
+         * 
+         */
+        Arrays.fill(out, -1f);
+        Arrays.fill(aux, 0f);
+        for (int i = 0; i < size; i++) {
+            in[i] = i + 1;
+        }
+        dispatchMethodKernel(size, out, in, aux);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java	Fri May 02 21:58:28 2014 +0200
@@ -113,13 +113,14 @@
          * argument).
          * 
          */
-        Arrays.fill(out, 0f);
-        Arrays.fill(in, 0f);
+        Arrays.fill(out, -1f);
+        for (int i = 0; i < size; i++) {
+            in[i] = i + 1;
+        }
         dispatchMethodKernel(size, out, in);
     }
 
     @Test
-    @Ignore("until stack slots are supported in deopt")
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java	Fri May 02 21:58:28 2014 +0200
@@ -88,7 +88,6 @@
     }
 
     @Test
-    @Ignore("until stack slots are supported in deopt")
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Fri May 02 21:58:28 2014 +0200
@@ -37,20 +37,10 @@
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.hsail.*;
-import com.oracle.graal.lir.hsail.HSAILArithmetic.ConvertOp;
-import com.oracle.graal.lir.hsail.HSAILArithmetic.Op1Stack;
+import com.oracle.graal.lir.hsail.HSAILArithmetic.Op1Reg;
 import com.oracle.graal.lir.hsail.HSAILArithmetic.Op2Reg;
-import com.oracle.graal.lir.hsail.HSAILArithmetic.Op2Stack;
-import com.oracle.graal.lir.hsail.HSAILArithmetic.ShiftOp;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.CompareBranchOp;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.FloatCondMoveOp;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.ReturnOp;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.StrategySwitchOp;
-import com.oracle.graal.lir.hsail.HSAILMove.LeaOp;
-import com.oracle.graal.lir.hsail.HSAILMove.MembarOp;
-import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp;
-import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.*;
+import com.oracle.graal.lir.hsail.HSAILMove.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -262,16 +252,16 @@
             case Int:
                 // Note: The Int case also handles the negation of shorts, bytes, and chars because
                 // Java treats these types as ints at the bytecode level.
-                append(new Op1Stack(INEG, result, input));
+                append(new Op1Reg(INEG, result, input));
                 break;
             case Long:
-                append(new Op1Stack(LNEG, result, input));
+                append(new Op1Reg(LNEG, result, input));
                 break;
             case Double:
-                append(new Op1Stack(DNEG, result, input));
+                append(new Op1Reg(DNEG, result, input));
                 break;
             case Float:
-                append(new Op1Stack(FNEG, result, input));
+                append(new Op1Reg(FNEG, result, input));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -293,10 +283,10 @@
             case Int:
                 // Note: The Int case also covers other primitive integral types smaller than an int
                 // (char, byte, short) because Java treats these types as ints.
-                append(new Op1Stack(INOT, result, input));
+                append(new Op1Reg(INOT, result, input));
                 break;
             case Long:
-                append(new Op1Stack(LNOT, result, input));
+                append(new Op1Reg(LNOT, result, input));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -309,16 +299,16 @@
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(IADD, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Stack(LADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(LADD, result, a, loadNonConst(b)));
                 break;
             case Float:
-                append(new Op2Stack(FADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(FADD, result, a, loadNonConst(b)));
                 break;
             case Double:
-                append(new Op2Stack(DADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(DADD, result, a, loadNonConst(b)));
                 break;
             case Object:
                 throw GraalInternalError.shouldNotReachHere();
@@ -334,19 +324,19 @@
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(IADD, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Stack(LADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(LADD, result, a, loadNonConst(b)));
                 break;
             case Float:
-                append(new Op2Stack(FADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(FADD, result, a, loadNonConst(b)));
                 break;
             case Double:
-                append(new Op2Stack(DADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(DADD, result, a, loadNonConst(b)));
                 break;
             case Object:
-                append(new Op2Stack(OADD, result, a, loadNonConst(b)));
+                append(new Op2Reg(OADD, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -359,16 +349,16 @@
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
+                append(new Op2Reg(ISUB, result, a, loadNonConst(b)));
                 break;
             case Float:
-                append(new Op2Stack(FSUB, result, a, loadNonConst(b)));
+                append(new Op2Reg(FSUB, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Stack(LSUB, result, a, loadNonConst(b)));
+                append(new Op2Reg(LSUB, result, a, loadNonConst(b)));
                 break;
             case Double:
-                append(new Op2Stack(DSUB, result, a, loadNonConst(b)));
+                append(new Op2Reg(DSUB, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -418,16 +408,16 @@
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IDIV, result, a, loadNonConst(b)));
+                append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Stack(LDIV, result, a, loadNonConst(b)));
+                append(new Op2Reg(LDIV, result, a, loadNonConst(b)));
                 break;
             case Float:
-                append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
+                append(new Op2Reg(FDIV, result, a, loadNonConst(b)));
                 break;
             case Double:
-                append(new Op2Stack(DDIV, result, a, loadNonConst(b)));
+                append(new Op2Reg(DDIV, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -441,16 +431,16 @@
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IREM, result, a, loadNonConst(b)));
+                append(new Op2Reg(IREM, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Stack(LREM, result, a, loadNonConst(b)));
+                append(new Op2Reg(LREM, result, a, loadNonConst(b)));
                 break;
             case Float:
-                append(new Op2Stack(FREM, result, a, loadNonConst(b)));
+                append(new Op2Reg(FREM, result, a, loadNonConst(b)));
                 break;
             case Double:
-                append(new Op2Stack(DREM, result, a, loadNonConst(b)));
+                append(new Op2Reg(DREM, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -473,10 +463,10 @@
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IAND, result, a, loadNonConst(b)));
+                append(new Op2Reg(IAND, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Stack(LAND, result, a, loadNonConst(b)));
+                append(new Op2Reg(LAND, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -489,10 +479,10 @@
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IOR, result, a, loadNonConst(b)));
+                append(new Op2Reg(IOR, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Stack(LOR, result, a, loadNonConst(b)));
+                append(new Op2Reg(LOR, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -505,10 +495,10 @@
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
+                append(new Op2Reg(IXOR, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Stack(LXOR, result, a, loadNonConst(b)));
+                append(new Op2Reg(LXOR, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -720,7 +710,7 @@
     @Override
     public Value emitMathAbs(Value input) {
         Variable result = newVariable(input.getPlatformKind());
-        append(new Op1Stack(ABS, result, input));
+        append(new Op1Reg(ABS, result, input));
         return result;
     }
 
@@ -732,7 +722,7 @@
      */
     public Value emitMathCeil(Value input) {
         Variable result = newVariable(input.getPlatformKind());
-        append(new Op1Stack(CEIL, result, input));
+        append(new Op1Reg(CEIL, result, input));
         return result;
     }
 
@@ -744,7 +734,7 @@
      */
     public Value emitMathFloor(Value input) {
         Variable result = newVariable(input.getPlatformKind());
-        append(new Op1Stack(FLOOR, result, input));
+        append(new Op1Reg(FLOOR, result, input));
         return result;
     }
 
@@ -756,7 +746,7 @@
      */
     public Value emitMathRint(Value input) {
         Variable result = newVariable(input.getPlatformKind());
-        append(new Op1Stack(RINT, result, input));
+        append(new Op1Reg(RINT, result, input));
         return result;
     }
 
@@ -769,7 +759,7 @@
     @Override
     public Value emitMathSqrt(Value input) {
         Variable result = newVariable(input.getPlatformKind());
-        append(new Op1Stack(SQRT, result, input));
+        append(new Op1Reg(SQRT, result, input));
         return result;
     }
 
--- a/graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java	Fri May 02 21:58:28 2014 +0200
@@ -43,6 +43,8 @@
     private long entryPoint;
     private StructuredGraph hostGraph;
 
+    private int[] oopMapArray;
+
     /**
      * Set the address for the point of entry to the external compilation result.
      * 
@@ -75,4 +77,13 @@
     public StructuredGraph getHostGraph() {
         return hostGraph;
     }
+
+    public void setOopMapArray(int[] arr) {
+        oopMapArray = arr;
+    }
+
+    public int[] getOopMapArray() {
+        return oopMapArray;
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Fri May 02 21:58:28 2014 +0200
@@ -66,7 +66,6 @@
 import com.oracle.graal.lir.hsail.HSAILMove.AtomicReadAndAddOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -145,7 +144,21 @@
      */
     public HotSpotNmethod compileAndInstallKernel(Method method) {
         ResolvedJavaMethod javaMethod = getProviders().getMetaAccess().lookupJavaMethod(method);
-        return installKernel(javaMethod, compileKernel(javaMethod, true));
+        HotSpotNmethod nm = installKernel(javaMethod, compileKernel(javaMethod, true));
+        try (Scope s = Debug.scope("HostCodeGen")) {
+            if (Debug.isLogEnabled()) {
+                DisassemblerProvider dis = getRuntime().getHostBackend().getDisassembler();
+                if (dis != null) {
+                    String disasm = dis.disassemble(nm);
+                    Debug.log("host code generated for %s%n%s", javaMethod, disasm);
+                } else {
+                    Debug.log("host code disassembler is null");
+                }
+            }
+        } catch (Throwable e) {
+            throw Debug.handle(e);
+        }
+        return nm;
     }
 
     /**
@@ -274,7 +287,8 @@
             }
         }
 
-        HotSpotNmethod code = new HotSpotNmethod(javaMethod, hsailCode.getName(), false, true);
+        HSAILHotSpotNmethod code = new HSAILHotSpotNmethod(javaMethod, hsailCode.getName(), false, true);
+        code.setOopMapArray(hsailCode.getOopMapArray());
         HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(getTarget(), javaMethod, compilationResult);
         CodeInstallResult result = getRuntime().getCompilerToVM().installCode(compiled, code, null);
         if (result != CodeInstallResult.OK) {
@@ -359,11 +373,16 @@
         if (!deviceInitialized) {
             throw new GraalInternalError("Cannot execute GPU kernel if device is not initialized");
         }
-        Object[] oopsSaveArea = new Object[maxDeoptIndex * 16];
-        return executeKernel0(kernel, jobSize, args, oopsSaveArea, donorThreadPool.get().getThreads(), HsailAllocBytesPerWorkitem.getValue());
+        int[] oopMapArray = ((HSAILHotSpotNmethod) kernel).getOopMapArray();
+        int saveAreaCounts = OopMapArrayBuilder.getSaveAreaCounts(oopMapArray);
+        int numDRegs = (saveAreaCounts >> 8) & 0xff;
+        int numStackSlots = (saveAreaCounts >> 16);
+        // pessimistically assume that any of the DRegs or stackslots could be oops
+        Object[] oopsSaveArea = new Object[maxDeoptIndex * (numDRegs + numStackSlots)];
+        return executeKernel0(kernel, jobSize, args, oopsSaveArea, donorThreadPool.get().getThreads(), HsailAllocBytesPerWorkitem.getValue(), oopMapArray);
     }
 
-    private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave, Thread[] donorThreads, int allocBytesPerWorkitem)
+    private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave, Thread[] donorThreads, int allocBytesPerWorkitem, int[] oopMapArray)
                     throws InvalidInstalledCodeException;
 
     /**
@@ -419,6 +438,22 @@
         }
     }
 
+    static class HSAILHotSpotNmethod extends HotSpotNmethod {
+        private int[] oopMapArray;
+
+        HSAILHotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault, boolean isExternal) {
+            super(method, name, isDefault, isExternal);
+        }
+
+        void setOopMapArray(int[] array) {
+            oopMapArray = array;
+        }
+
+        int[] getOopMapArray() {
+            return oopMapArray;
+        }
+    }
+
     @Override
     protected Assembler createAssembler(FrameMap frameMap) {
         return new HSAILHotSpotAssembler(getTarget());
@@ -686,10 +721,54 @@
         asm.emitString(spillsegStringFinal, spillsegDeclarationPosition);
         // Emit the epilogue.
 
-        // TODO: keep track of whether we need it
+        int numSRegs = 0;
+        int numDRegs = 0;
+        int numStackSlotBytes = 0;
         if (useHSAILDeoptimization) {
+            // get the union of registers and stack slots needed to be saved at the infopoints
+            // while doing this compute the highest register in each category
+            HSAILHotSpotRegisterConfig hsailRegConfig = (HSAILHotSpotRegisterConfig) regConfig;
+            Set<Register> infoUsedRegs = new TreeSet<>();
+            Set<StackSlot> infoUsedStackSlots = new HashSet<>();
+            List<Infopoint> infoList = crb.compilationResult.getInfopoints();
+            for (Infopoint info : infoList) {
+                BytecodeFrame frame = info.debugInfo.frame();
+                while (frame != null) {
+                    for (int i = 0; i < frame.numLocals + frame.numStack; i++) {
+                        Value val = frame.values[i];
+                        if (isLegal(val)) {
+                            if (isRegister(val)) {
+                                Register reg = asRegister(val);
+                                infoUsedRegs.add(reg);
+                                if (hsailRegConfig.isAllocatableSReg(reg)) {
+                                    numSRegs = Math.max(numSRegs, reg.encoding + 1);
+                                } else if (hsailRegConfig.isAllocatableDReg(reg)) {
+                                    numDRegs = Math.max(numDRegs, reg.encoding + 1);
+                                }
+                            } else if (isStackSlot(val)) {
+                                StackSlot slot = asStackSlot(val);
+                                Kind slotKind = slot.getKind();
+                                int slotSizeBytes = (slotKind.isObject() ? 8 : slotKind.getByteCount());
+                                int slotOffsetMax = HSAIL.getStackOffsetStart(slot, slotSizeBytes * 8) + slotSizeBytes;
+                                numStackSlotBytes = Math.max(numStackSlotBytes, slotOffsetMax);
+                                infoUsedStackSlots.add(slot);
+                            }
+                        }
+                    }
+                    frame = frame.caller();
+                }
+            }
+
+            // round up numSRegs to even number so dregs start on aligned boundary
+            numSRegs += (numSRegs & 1);
+
+            // numStackSlots is the number of 8-byte locations used for stack variables
+            int numStackSlots = (numStackSlotBytes + 7) / 8;
+
             final int offsetToDeoptSaveStates = config.hsailSaveStatesOffset0;
-            final int sizeofKernelDeopt = config.hsailSaveStatesOffset1 - config.hsailSaveStatesOffset0;
+            final int sizeofKernelDeoptHeader = config.hsailKernelDeoptimizationHeaderSize;
+            final int bytesPerSaveArea = 4 * numSRegs + 8 * numDRegs + 8 * numStackSlots;
+            final int sizeofKernelDeopt = sizeofKernelDeoptHeader + bytesPerSaveArea;
             final int offsetToNeverRanArray = config.hsailNeverRanArrayOffset;
             final int offsetToDeoptNextIndex = config.hsailDeoptNextIndexOffset;
             final int offsetToDeoptimizationWorkItem = config.hsailDeoptimizationWorkItem;
@@ -708,7 +787,6 @@
             AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
             AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int);
             AllocatableValue workidreg = HSAIL.s35.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();
@@ -769,8 +847,6 @@
             // Now scratch64 is the _deopt_info._first_frame
             HSAILAddress pcStoreAddr = new HSAILAddressValue(Kind.Int, waveMathScratch1, offsetToFramePc).toAddress();
             HSAILAddress regCountsAddr = new HSAILAddressValue(Kind.Int, waveMathScratch1, offsetToNumSaves).toAddress();
-            HSAILAddress dregOopMapAddr = new HSAILAddressValue(Kind.Int, waveMathScratch1, offsetToNumSaves + 2).toAddress();
-
             asm.emitComment("// store deopting workitem");
             asm.emitWorkItemAbsId(scratch32);
             asm.emitStore(Kind.Int, scratch32, workItemAddr);
@@ -778,58 +854,61 @@
             asm.emitStore(Kind.Int, actionAndReasonReg, actionReasonStoreAddr);
             asm.emitComment("// store PC");
             asm.emitStore(Kind.Int, codeBufferOffsetReg, pcStoreAddr);
-            asm.emitComment("// store regCounts");
-            asm.emitStore(Kind.Short, Constant.forInt(32 + (16 << 8) + (0 << 16)), regCountsAddr);
-            asm.emitComment("// store dreg ref map bits");
-            asm.emitStore(Kind.Short, dregOopMapReg, dregOopMapAddr);
+
+            asm.emitComment("// store regCounts (" + numSRegs + " $s registers and " + numDRegs + " $d registers" + numStackSlots + " stack slots)");
+            asm.emitStore(Kind.Int, Constant.forInt(numSRegs + (numDRegs << 8) + (numStackSlots << 16)), regCountsAddr);
 
-            // get the union of registers needed to be saved at the infopoints
-            boolean[] infoUsedRegs = new boolean[HSAIL.threadRegister.number + 1];
-            List<Infopoint> infoList = crb.compilationResult.getInfopoints();
-            for (Infopoint info : infoList) {
-                BytecodeFrame frame = info.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);
-                        infoUsedRegs[reg.number] = true;
-                    }
+            // loop thru the usedValues storing each of the registers that are used.
+            // we always store in a fixed location, even if some registers are skipped
+            asm.emitComment("// store used regs");
+            for (Register reg : infoUsedRegs) {
+                if (hsailRegConfig.isAllocatableSReg(reg)) {
+                    // 32 bit registers
+                    Kind kind = Kind.Int;
+                    int ofst = offsetToSaveArea + reg.encoding * 4;
+                    HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress();
+                    AllocatableValue regValue = reg.asValue(kind);
+                    asm.emitStore(kind, regValue, addr);
+                } else if (hsailRegConfig.isAllocatableDReg(reg)) {
+                    // 64 bit registers
+                    Kind kind = Kind.Long;
+                    // d reg ofst starts past the 32 sregs
+                    int ofst = offsetToSaveArea + (numSRegs * 4) + reg.encoding * 8;
+                    HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress();
+                    AllocatableValue regValue = reg.asValue(kind);
+                    asm.emitStore(kind, regValue, addr);
+                } else {
+                    throw GraalInternalError.unimplemented();
                 }
             }
 
-            // loop storing each of the 32 s registers that are used by infopoints
-            // we always store in a fixed location, even if some registers are not stored
-            asm.emitComment("// store used s regs");
-            int ofst = offsetToSaveArea;
-            for (Register sreg : HSAIL.sRegisters) {
-                if (infoUsedRegs[sreg.number]) {
-                    Kind kind = Kind.Int;
+            // loop thru the usedStackSlots creating instructions to save in the save area
+            if (numStackSlotBytes > 0) {
+                asm.emitComment("// store stack slots (uses " + numStackSlotBytes + " bytes)");
+                for (StackSlot slot : infoUsedStackSlots) {
+                    asm.emitComment("// store " + slot);
+                    Kind kind = slot.getKind();
+                    int sizeInBits = (kind.isObject() || kind.getByteCount() == 8 ? 64 : 32);
+                    int ofst = offsetToSaveArea + (numSRegs * 4) + (numDRegs * 8) + HSAIL.getStackOffsetStart(slot, sizeInBits);
                     HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress();
-                    AllocatableValue sregValue = sreg.asValue(kind);
-                    asm.emitStore(kind, sregValue, addr);
+                    if (sizeInBits == 64) {
+                        asm.emitSpillLoad(kind, scratch64, slot);
+                        asm.emitStore(kind, scratch64, addr);
+                    } else {
+                        asm.emitSpillLoad(kind, scratch32, slot);
+                        asm.emitStore(kind, scratch32, addr);
+                    }
                 }
-                ofst += 4;
             }
 
-            // loop storing each of the 16 d registers that are used by infopoints
-            asm.emitComment("// store used d regs");
-            for (Register dreg : HSAIL.dRegisters) {
-                if (infoUsedRegs[dreg.number]) {
-                    Kind kind = Kind.Long;
-                    HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress();
-                    AllocatableValue dregValue = dreg.asValue(kind);
-                    asm.emitStore(kind, dregValue, addr);
-                }
-                ofst += 8;
-            }
-
-            // for now, ignore saving the spill variables but that would come here
-
             asm.emitString0(labelExit + ":\n");
 
             // and emit the return
             crb.frameContext.leave(crb);
             asm.exit();
+            // build the oopMap Array
+            int[] oopMapArray = new OopMapArrayBuilder().build(infoList, numSRegs, numDRegs, numStackSlots, hsailRegConfig);
+            ((ExternalCompilationResult) crb.compilationResult).setOopMapArray(oopMapArray);
         } else {
             // Deoptimization is explicitly off, so emit simple return
             asm.emitString0(asm.getDeoptLabelName() + ":\n");
@@ -841,10 +920,115 @@
 
         ExternalCompilationResult compilationResult = (ExternalCompilationResult) crb.compilationResult;
         HSAILHotSpotLIRGenerationResult lirGenRes = ((HSAILCompilationResultBuilder) crb).lirGenRes;
-        compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), config));
+        compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), config, numSRegs, numDRegs));
     }
 
-    private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List<DeoptimizingOp> deopts, HotSpotProviders providers, HotSpotVMConfig config) {
+    private static class OopMapArrayBuilder {
+        // oopMapArray struct
+        // int bytesPerSaveArea; (not strictly part of oopsmap but convenient to put here)
+        // int intsPerInfopoint;
+        static final int SAVEAREACOUNTS_OFST = 0;
+        static final int INTSPERINFOPOINT_OFST = 1;
+        static final int HEADERSIZE = 2;
+        // for each infopoint:
+        // int deoptId
+        // one or more ints of bits for the oopmap
+
+        private int[] array;
+        private int intsPerInfopoint;
+
+        int[] build(List<Infopoint> infoList, int numSRegs, int numDRegs, int numStackSlots, HSAILHotSpotRegisterConfig hsailRegConfig) {
+            // we are told that infoList is always sorted
+            // each infoPoint can have a different oopMap
+
+            // since numStackSlots is the number of 8-byte stack slots used, it is an upper limit on
+            // the number of oop stack slots
+            int bitsPerInfopoint = numDRegs + numStackSlots;
+            int intsForBits = (bitsPerInfopoint + 31) / 32;
+            int numInfopoints = infoList.size();
+            intsPerInfopoint = intsForBits + 1;  // +1 for the pcoffset
+            int arraySize = HEADERSIZE + (numInfopoints * intsPerInfopoint);
+            array = new int[arraySize];
+            array[INTSPERINFOPOINT_OFST] = intsPerInfopoint;
+            // compute saveAreaCounts
+            int saveAreaCounts = (numSRegs & 0xff) + (numDRegs << 8) + (numStackSlots << 16);
+            array[SAVEAREACOUNTS_OFST] = saveAreaCounts;
+
+            // loop thru the infoList
+            int infoIndex = 0;
+            for (Infopoint info : infoList) {
+                setOopMapPcOffset(infoIndex, info.pcOffset);
+                BytecodeFrame frame = info.debugInfo.frame();
+                while (frame != null) {
+                    for (int i = 0; i < frame.numLocals + frame.numStack; i++) {
+                        Value val = frame.values[i];
+                        if (isLegal(val)) {
+                            if (isRegister(val)) {
+                                Register reg = asRegister(val);
+                                if (val.getKind().isObject()) {
+                                    assert (hsailRegConfig.isAllocatableDReg(reg));
+                                    int bitIndex = reg.encoding();
+                                    setOopMapBit(infoIndex, bitIndex);
+                                }
+                            } else if (isStackSlot(val)) {
+                                StackSlot slot = asStackSlot(val);
+                                if (val.getKind().isObject()) {
+                                    assert (HSAIL.getStackOffsetStart(slot, 64) % 8 == 0);
+                                    int bitIndex = numDRegs + HSAIL.getStackOffsetStart(slot, 64) / 8;
+                                    setOopMapBit(infoIndex, bitIndex);
+                                }
+                            }
+                        }
+                    }
+                    frame = frame.caller();
+                }
+                infoIndex++;
+            }
+            try (Scope s = Debug.scope("CodeGen")) {
+                if (Debug.isLogEnabled()) {
+                    Debug.log("numSRegs=%d, numDRegs=%d, numStackSlots=%d", numSRegs, numDRegs, numStackSlots);
+                    // show infopoint oopmap details
+                    for (infoIndex = 0; infoIndex < infoList.size(); infoIndex++) {
+                        String infoString = "Infopoint " + infoIndex + ", pcOffset=" + getOopMapPcOffset(infoIndex) + ",   oopmap=";
+                        for (int i = 0; i < intsForBits; i++) {
+                            infoString += (i != 0 ? ", " : "") + Integer.toHexString(getOopMapBitsAsInt(infoIndex, i));
+                        }
+                        Debug.log(infoString);
+                    }
+                }
+            } catch (Throwable e) {
+                throw Debug.handle(e);
+            }
+
+            return array;
+        }
+
+        private void setOopMapPcOffset(int infoIndex, int pcOffset) {
+            int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint;
+            array[arrIndex] = pcOffset;
+        }
+
+        private int getOopMapPcOffset(int infoIndex) {
+            int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint;
+            return array[arrIndex];
+        }
+
+        private void setOopMapBit(int infoIndex, int bitIndex) {
+            int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint + 1 + bitIndex / 32;
+            array[arrIndex] |= (1 << (bitIndex % 32));
+        }
+
+        private int getOopMapBitsAsInt(int infoIndex, int intIndex) {
+            int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint + 1 + intIndex;
+            return array[arrIndex];
+        }
+
+        public static int getSaveAreaCounts(int[] array) {
+            return array[SAVEAREACOUNTS_OFST];
+        }
+    }
+
+    private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List<DeoptimizingOp> deopts, HotSpotProviders providers, HotSpotVMConfig config, int numSRegs, int numDRegs) {
         if (deopts.isEmpty()) {
             return null;
         }
@@ -868,7 +1052,7 @@
             keyProbabilities[i] = 1.0 / deopts.size();
             keys[i] = deopt.getCodeBufferPos();
             assert keys[i] >= 0;
-            branches[i] = createHostDeoptBranch(deopt, hsailFrame, reasonAndAction, speculation, providers, config);
+            branches[i] = createHostDeoptBranch(deopt, hsailFrame, reasonAndAction, speculation, providers, config, numSRegs, numDRegs);
 
             i++;
         }
@@ -892,34 +1076,35 @@
         return BeginNode.begin(vmError);
     }
 
-    private static BeginNode createHostDeoptBranch(DeoptimizingOp 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, int numSRegs, int numDRegs) {
         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));
+        deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config, numSRegs, numDRegs));
         branch.setNext(deoptimization);
         return branch;
     }
 
-    private static FrameState createFrameState(BytecodeFrame lowLevelFrame, ParameterNode hsailFrame, HotSpotProviders providers, HotSpotVMConfig config) {
+    private static FrameState createFrameState(BytecodeFrame lowLevelFrame, ParameterNode hsailFrame, HotSpotProviders providers, HotSpotVMConfig config, int numSRegs, int numDRegs) {
         StructuredGraph hostGraph = hsailFrame.graph();
         ValueNode[] locals = new ValueNode[lowLevelFrame.numLocals];
         for (int i = 0; i < lowLevelFrame.numLocals; i++) {
-            locals[i] = getNodeForValueFromFrame(lowLevelFrame.getLocalValue(i), hsailFrame, hostGraph, providers, config);
+            locals[i] = getNodeForValueFromFrame(lowLevelFrame.getLocalValue(i), hsailFrame, hostGraph, providers, config, numSRegs, numDRegs);
         }
         List<ValueNode> stack = new ArrayList<>(lowLevelFrame.numStack);
         for (int i = 0; i < lowLevelFrame.numStack; i++) {
-            stack.add(getNodeForValueFromFrame(lowLevelFrame.getStackValue(i), hsailFrame, hostGraph, providers, config));
+            stack.add(getNodeForValueFromFrame(lowLevelFrame.getStackValue(i), hsailFrame, hostGraph, providers, config, numSRegs, numDRegs));
         }
         ValueNode[] locks = new ValueNode[lowLevelFrame.numLocks];
         MonitorIdNode[] monitorIds = new MonitorIdNode[lowLevelFrame.numLocks];
         for (int i = 0; i < lowLevelFrame.numLocks; i++) {
             HotSpotMonitorValue lockValue = (HotSpotMonitorValue) lowLevelFrame.getLockValue(i);
-            locks[i] = getNodeForValueFromFrame(lockValue, hsailFrame, hostGraph, providers, config);
+            locks[i] = getNodeForValueFromFrame(lockValue, hsailFrame, hostGraph, providers, config, numSRegs, numDRegs);
             monitorIds[i] = getMonitorIdForHotSpotMonitorValueFromFrame(lockValue, hsailFrame, hostGraph);
         }
         FrameState frameState = hostGraph.add(new FrameState(lowLevelFrame.getMethod(), lowLevelFrame.getBCI(), locals, stack, locks, monitorIds, lowLevelFrame.rethrowException, false));
         if (lowLevelFrame.caller() != null) {
-            frameState.setOuterFrameState(createFrameState(lowLevelFrame.caller(), hsailFrame, providers, config));
+            frameState.setOuterFrameState(createFrameState(lowLevelFrame.caller(), hsailFrame, providers, config, numSRegs, numDRegs));
         }
         return frameState;
     }
@@ -932,21 +1117,23 @@
         throw GraalInternalError.unimplemented();
     }
 
-    private static ValueNode getNodeForValueFromFrame(Value localValue, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config) {
+    private static ValueNode getNodeForValueFromFrame(Value localValue, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config, int numSRegs,
+                    int numDRegs) {
         ValueNode valueNode;
         if (localValue instanceof Constant) {
             valueNode = ConstantNode.forConstant((Constant) localValue, providers.getMetaAccess(), hostGraph);
         } else if (localValue instanceof VirtualObject) {
             throw GraalInternalError.unimplemented();
         } else if (localValue instanceof StackSlot) {
-            throw GraalInternalError.unimplemented();
+            StackSlot slot = (StackSlot) localValue;
+            valueNode = getNodeForStackSlotFromFrame(slot, localValue.getKind(), hsailFrame, hostGraph, providers, config, numSRegs, numDRegs);
         } else if (localValue instanceof HotSpotMonitorValue) {
             HotSpotMonitorValue hotSpotMonitorValue = (HotSpotMonitorValue) localValue;
-            return getNodeForValueFromFrame(hotSpotMonitorValue.getOwner(), hsailFrame, hostGraph, providers, config);
+            return getNodeForValueFromFrame(hotSpotMonitorValue.getOwner(), hsailFrame, hostGraph, providers, config, numSRegs, numDRegs);
         } else if (localValue instanceof RegisterValue) {
             RegisterValue registerValue = (RegisterValue) localValue;
             int regNumber = registerValue.getRegister().number;
-            valueNode = getNodeForRegisterFromFrame(regNumber, localValue.getKind(), hsailFrame, hostGraph, providers, config);
+            valueNode = getNodeForRegisterFromFrame(regNumber, localValue.getKind(), hsailFrame, hostGraph, providers, config, numSRegs);
         } else if (Value.ILLEGAL.equals(localValue)) {
             valueNode = null;
         } else {
@@ -955,20 +1142,18 @@
         return valueNode;
     }
 
-    private static ValueNode getNodeForRegisterFromFrame(int regNumber, Kind valueKind, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config) {
+    private static ValueNode getNodeForRegisterFromFrame(int regNumber, Kind valueKind, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config,
+                    int numSRegs) {
         ValueNode valueNode;
         LocationNode location;
+        int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long);
+        int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int);
         if (regNumber >= HSAIL.s0.number && regNumber <= HSAIL.s31.number) {
-            int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int);
             long offset = config.hsailFrameSaveAreaOffset + intSize * (regNumber - HSAIL.s0.number);
             location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
         } else if (regNumber >= HSAIL.d0.number && regNumber <= HSAIL.d15.number) {
-            int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long);
-            long offset = config.hsailFrameSaveAreaOffset + longSize * (regNumber - HSAIL.d0.number);
-            LocationNode numSRegsLocation = ConstantLocationNode.create(FINAL_LOCATION, Kind.Byte, config.hsailFrameNumSRegOffset, hostGraph);
-            ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8)));
-            numSRegs = SignExtendNode.convert(numSRegs, StampFactory.forKind(Kind.Byte));
-            location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4);
+            long offset = config.hsailFrameSaveAreaOffset + intSize * numSRegs + longSize * (regNumber - HSAIL.d0.number);
+            location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
         } else {
             throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber);
         }
@@ -976,4 +1161,18 @@
         return valueNode;
     }
 
+    private static ValueNode getNodeForStackSlotFromFrame(StackSlot slot, Kind valueKind, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config,
+                    int numSRegs, int numDRegs) {
+        int slotSizeInBits = (valueKind == Kind.Object ? 64 : valueKind.getByteCount() * 8);
+        if ((slotSizeInBits == 32) || (slotSizeInBits == 64)) {
+            int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long);
+            int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int);
+            long offset = config.hsailFrameSaveAreaOffset + (intSize * numSRegs) + (longSize * numDRegs) + HSAIL.getStackOffsetStart(slot, slotSizeInBits);
+            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
+            ValueNode valueNode = hostGraph.unique(new FloatingReadNode(hsailFrame, location, null, StampFactory.forKind(valueKind)));
+            return valueNode;
+        } else {
+            throw GraalInternalError.shouldNotReachHere("unsupported stack slot kind: " + valueKind);
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java	Fri May 02 21:58:28 2014 +0200
@@ -194,6 +194,14 @@
         throw new UnsupportedOperationException();
     }
 
+    public boolean isAllocatableSReg(Register reg) {
+        return (reg.number >= HSAIL.s0.number && reg.number <= HSAIL.s31.number);
+    }
+
+    public boolean isAllocatableDReg(Register reg) {
+        return (reg.number >= HSAIL.d0.number && reg.number <= HSAIL.d15.number);
+    }
+
     public HSAILHotSpotRegisterConfig() {
 
     }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java	Fri May 02 21:58:28 2014 +0200
@@ -22,8 +22,6 @@
  */
 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.*;
@@ -42,7 +40,6 @@
     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) {
@@ -77,23 +74,10 @@
         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");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri May 02 21:58:28 2014 +0200
@@ -1022,8 +1022,6 @@
      * 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;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_never_ran_array", type = "jboolean *", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNeverRanArrayOffset;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_next_index", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptNextIndexOffset;
@@ -1035,7 +1033,10 @@
 
     @HotSpotVMField(name = "HSAILFrame::_pc_offset", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailFramePcOffset;
     @HotSpotVMField(name = "HSAILFrame::_num_s_regs", type = "jbyte", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailFrameNumSRegOffset;
-    @HotSpotVMField(name = "HSAILFrame::_save_area[0]", type = "jlong", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailFrameSaveAreaOffset;
+    @HotSpotVMField(name = "HSAILFrame::_num_d_regs", type = "jbyte", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailFrameNumDRegOffset;
+    @HotSpotVMConstant(name = "sizeof(HSAILFrame)") @Stable public int hsailFrameSaveAreaOffset;
+    @HotSpotVMConstant(name = "sizeof(Hsail::HSAILKernelDeoptimization)") @Stable public int hsailKernelDeoptimizationHeaderSize;
+    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[0]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset0;
 
     /**
      * Mark word right shift to get identity hash code.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Fri May 02 21:58:28 2014 +0200
@@ -36,7 +36,7 @@
  * instance to be anything but weak. This is due to the fact that HotSpot does not treat nmethods as
  * strong GC roots.
  */
-public final class HotSpotNmethod extends HotSpotInstalledCode {
+public class HotSpotNmethod extends HotSpotInstalledCode {
 
     /**
      * This (indirect) Method* reference is safe since class redefinition preserves all methods
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Fri May 02 21:58:28 2014 +0200
@@ -136,7 +136,6 @@
     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 = {
@@ -178,10 +177,16 @@
         return -(((StackSlot) reg).getRawOffset());
     }
 
-    public static String mapStackSlot(Value reg) {
-        StackSlot s = (StackSlot) reg;
-        long offset = -s.getRawOffset();
-        return "[%spillseg]" + "[" + offset + "]";
+    /**
+     * The mapping to stack slots is always relative to the beginning of the spillseg.
+     * {@link #getStackOffset(Value)} returns the positive version of the originally negative
+     * offset. Then we back up from that by {@code argSize} in bytes. This ensures that slots of
+     * different size do not overlap, even though we have converted from negative to positive
+     * offsets.
+     */
+    public static int getStackOffsetStart(Value reg, int argSize) {
+        int argSizeInBytes = argSize / 8;
+        return getStackOffset(reg) - argSizeInBytes;
     }
 
     public static String mapRegister(Value arg) {
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Fri May 02 21:58:28 2014 +0200
@@ -108,7 +108,7 @@
         private final String from;
         private final String to;
         @Def({REG}) protected AllocatableValue result;
-        @Use({REG, STACK}) protected AllocatableValue x;
+        @Use({REG}) protected AllocatableValue x;
 
         public ConvertOp(AllocatableValue result, AllocatableValue x, String to, String from) {
             this.from = from;
@@ -123,52 +123,10 @@
         }
     }
 
-    public static class Op1Stack extends HSAILLIRInstruction {
-        @Opcode private final HSAILArithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
-
-        public Op1Stack(HSAILArithmetic opcode, Value result, Value x) {
-            this.opcode = opcode;
-            this.result = result;
-            this.x = x;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            emit(crb, masm, opcode, result, x, null);
-        }
-    }
-
-    public static class Op2Stack extends HSAILLIRInstruction {
+    public static class Op1Reg extends HSAILLIRInstruction {
         @Opcode private final HSAILArithmetic opcode;
         @Def({REG, HINT}) protected Value result;
         @Use({REG, CONST}) protected Value x;
-        @Alive({REG, CONST}) protected Value y;
-
-        public Op2Stack(HSAILArithmetic opcode, Value result, Value x, Value y) {
-            this.opcode = opcode;
-            this.result = result;
-            this.x = x;
-            this.y = y;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            emit(crb, masm, opcode, result, x, y, null);
-        }
-
-        @Override
-        public void verify() {
-            super.verify();
-            verifyKind(opcode, result, x, y);
-        }
-    }
-
-    public static class Op1Reg extends HSAILLIRInstruction {
-        @Opcode private final HSAILArithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG}) protected Value x;
 
         public Op1Reg(HSAILArithmetic opcode, Value result, Value x) {
             this.opcode = opcode;
@@ -185,7 +143,7 @@
     public static class Op2Reg extends HSAILLIRInstruction {
         @Opcode private final HSAILArithmetic opcode;
         @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
+        @Use({REG, CONST}) protected Value x;
         @Alive({REG, CONST}) protected Value y;
 
         public Op2Reg(HSAILArithmetic opcode, Value result, Value x, Value y) {
@@ -207,35 +165,10 @@
         }
     }
 
-    public static class Op2RegCommutative extends HSAILLIRInstruction {
-        @Opcode private final HSAILArithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
-        @Use({REG, CONST}) protected Value y;
-
-        public Op2RegCommutative(HSAILArithmetic opcode, Value result, Value x, Value y) {
-            this.opcode = opcode;
-            this.result = result;
-            this.x = x;
-            this.y = y;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        protected void verify() {
-            super.verify();
-            verifyKind(opcode, result, x, y);
-        }
-    }
-
     public static class ShiftOp extends HSAILLIRInstruction {
         @Opcode private final HSAILArithmetic opcode;
         @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
+        @Use({REG, CONST}) protected Value x;
         @Alive({REG, CONST}) protected Value y;
 
         public ShiftOp(HSAILArithmetic opcode, Value result, Value x, Value y) {
@@ -295,7 +228,7 @@
 
     /**
      * Emits the HSAIL code for an arithmetic operation taking one input parameter.
-     * 
+     *
      * @param crb the CompilationResultBuilder
      * @param masm the HSAIL assembler
      * @param opcode the opcode of the arithmetic operation
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Fri May 02 21:58:28 2014 +0200
@@ -50,8 +50,8 @@
     public static class CompareOp extends HSAILLIRInstruction {
 
         @Opcode private final HSAILCompare opcode;
-        @Use({REG, STACK, CONST}) protected Value x;
-        @Use({REG, STACK, CONST}) protected Value y;
+        @Use({REG, CONST}) protected Value x;
+        @Use({REG, CONST}) protected Value y;
         @Def({REG}) protected Value z;
         private final Condition condition;
         public boolean unordered = false;
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Fri May 02 21:58:28 2014 +0200
@@ -146,7 +146,6 @@
         protected MetaAccessProvider metaAccessProvider;
         protected String emitName;
         protected int codeBufferPos = -1;
-        protected int dregOopMap = 0;
 
         public DeoptimizeOp(Value actionAndReason, LIRFrameState frameState, String emitName, MetaAccessProvider metaAccessProvider) {
             super(Value.ILLEGAL);   // return with no ret value
@@ -181,20 +180,10 @@
 
             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++) {
-                if (referenceMap.getRegister(dreg) == Kind.Object) {
-                    dregOopMap |= 1 << (dreg - HSAIL.d0.number);
-                }
-            }
-
             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());
 
             // now record the debuginfo
@@ -305,10 +294,10 @@
 
         @Opcode protected final HSAILCompare opcode;
         @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value trueValue;
-        @Use({REG, STACK, CONST}) protected Value falseValue;
-        @Use({REG, STACK, CONST}) protected Value left;
-        @Use({REG, STACK, CONST}) protected Value right;
+        @Use({REG, CONST}) protected Value trueValue;
+        @Use({REG, CONST}) protected Value falseValue;
+        @Use({REG, CONST}) protected Value left;
+        @Use({REG, CONST}) protected Value right;
         protected final Condition condition;
 
         public CondMoveOp(HSAILCompare opcode, Variable left, Variable right, Variable result, Condition condition, Value trueValue, Value falseValue) {
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Fri May 02 11:04:51 2014 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Fri May 02 21:58:28 2014 +0200
@@ -63,29 +63,6 @@
     }
 
     @Opcode("MOVE")
-    public static class SpillMoveOp extends AbstractMoveOp {
-
-        @Def({REG, STACK}) protected AllocatableValue result;
-        @Use({REG, STACK, CONST}) protected Value input;
-
-        public SpillMoveOp(Kind moveKind, AllocatableValue result, Value input) {
-            super(moveKind);
-            this.result = result;
-            this.input = input;
-        }
-
-        @Override
-        public Value getInput() {
-            return input;
-        }
-
-        @Override
-        public AllocatableValue getResult() {
-            return result;
-        }
-    }
-
-    @Opcode("MOVE")
     public static class MoveToRegOp extends AbstractMoveOp {
 
         @Def({REG, HINT}) protected AllocatableValue result;
--- a/src/gpu/hsail/vm/gpu_hsail.cpp	Fri May 02 11:04:51 2014 -0700
+++ b/src/gpu/hsail/vm/gpu_hsail.cpp	Fri May 02 21:58:28 2014 +0200
@@ -67,7 +67,7 @@
 JNINativeMethod Hsail::HSAIL_methods[] = {
   {CC"initialize",       CC"()Z",                               FN_PTR(Hsail::initialize)},
   {CC"generateKernel",   CC"([B" STRING ")J",                   FN_PTR(Hsail::generate_kernel)},
-  {CC"executeKernel0",   CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT"["JLTHREAD"I)Z",  FN_PTR(Hsail::execute_kernel_void_1d)},
+  {CC"executeKernel0",   CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT"["JLTHREAD"I[I)Z",  FN_PTR(Hsail::execute_kernel_void_1d)},
 };
 
 void * Hsail::_device_context = NULL;
@@ -147,7 +147,7 @@
 }
 
 GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args, jobject oops_save,
-                                                      jobject donor_threads, jint allocBytesPerWorkitem))
+                                                      jobject donor_threads, jint allocBytesPerWorkitem, jobject oop_map_array))
 
   ResourceMark rm;
   jlong nmethodValue = InstalledCode::address(kernel_handle);
@@ -163,7 +163,7 @@
     SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
   }
 
-  return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, oops_save, donor_threads, allocBytesPerWorkitem, CHECK_0);
+return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, oops_save, donor_threads, allocBytesPerWorkitem, oop_map_array, CHECK_0);
 GPU_END
 
 static void showRanges(jboolean *a, int len) {
@@ -215,9 +215,139 @@
   tty->print_cr("(%p, %p, %p), siz=%ld, free=%ld (%f%%)", start, top, end, tlabSize, tlabFree, freePct);
 }
 
+class OopSaver : public StackObj {
+private:
+  objArrayOop _oopsSaveArray;
+  typeArrayOop _oopMapArray;
+  jobject  _oops_save;
+  jobject _oop_map_array;
+  int _last_pcoffset;
+  int _last_idx;
+  int _saveAreaCounts;
 
-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) {
+  enum {
+    SAVEAREACOUNTS_OFST=0,
+    SPAN_OFST=1,
+    HEADERSIZE=2
+  }; 
+  int mapPcOffsetToIndex(int pcOffset) {
+    if (pcOffset == _last_pcoffset) {
+      return _last_idx;
+    }
+    int span = _oopMapArray->int_at(SPAN_OFST);
+    for (int idx = HEADERSIZE; idx < _oopMapArray->length(); idx += span) {
+      int ofst = _oopMapArray->int_at(idx);
+      if (ofst == pcOffset) {
+        _last_pcoffset = pcOffset;
+        _last_idx = idx + 1;
+        return _last_idx;
+      }
+    }
+  }
+
+public:
+  OopSaver(jobject oops_save, jobject oop_map_array) {
+    _oops_save = oops_save;
+    _oop_map_array = oop_map_array;
+    _last_pcoffset = -1;
+    _saveAreaCounts = getSaveAreaCounts(oop_map_array);
+    resolveArrays();
+  }
+ 
+  void resolveArrays() {
+    _oopsSaveArray = (objArrayOop) JNIHandles::resolve(_oops_save);
+    _oopMapArray = (typeArrayOop) JNIHandles::resolve(_oop_map_array);
+  }
+
+  void * getOopForBit(HSAILFrame * hsailFrame, int bit) {
+    assert(isOop(hsailFrame, bit), "");
+    void *oop;
+    if (bit < hsailFrame->num_d_regs()) {
+      // d register
+      oop = (void*) hsailFrame->get_d_reg(bit);
+    } else {
+      // stack slot
+      int stackOffset = (bit - hsailFrame->num_d_regs()) * 8;  // 8 bytes per stack slot
+      oop = (void *) hsailFrame->get_stackslot64(stackOffset);
+    }
+    return oop;
+  }
+
+  void putOopForBit(HSAILFrame * hsailFrame, int bit, void *oop) {
+    assert(isOop(hsailFrame, bit), "");
+    if (bit < hsailFrame->num_d_regs()) {
+      // d register
+      hsailFrame->put_d_reg(bit, (jlong) oop);
+    } else {
+      // stack slot
+      int stackOffset = (bit - hsailFrame->num_d_regs()) * 8;  // 8 bytes per stack slot
+      hsailFrame->put_stackslot64(stackOffset, (jlong) oop);
+    }
+  }
+
+  void saveOopsFromFrame(HSAILFrame * hsailFrame, int deoptSlot){
+    // as used, no need to resolve arrays on each call
+    int oopsPerDeopt = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots();
+
+    // handle the dregister and stackSlot based oops
+    for (int bit = 0; bit < oopsPerDeopt; bit++) {
+      if (isOop(hsailFrame, bit)) {
+        void* saved_oop = getOopForBit(hsailFrame, bit);
+        int saveArrayIndex = deoptSlot * oopsPerDeopt + bit;
+        _oopsSaveArray->obj_at_put(saveArrayIndex, (oop) saved_oop);
+      }
+    }
+  }
+
+  void restoreOopsToFrame(HSAILFrame * hsailFrame, int deoptSlot, int workitem){
+    // need to re-resolve on each restore
+    resolveArrays();
+    int oopsPerDeopt = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots();
+
+    // handle the dregister and stackSlot based oops
+    for (int bit = 0; bit < oopsPerDeopt; bit++) {
+      if (isOop(hsailFrame, bit)) {
+        // the dregister or stack slot at this bit is an oop, retrieve it from array and put back in frame
+        int saveArrayIndex = deoptSlot * oopsPerDeopt + bit;
+        void * newValue = (void *) _oopsSaveArray->obj_at(saveArrayIndex);
+        void * oldValue = getOopForBit(hsailFrame, bit);
+        assert((oldValue != 0 ? newValue != 0 : newValue == 0), "bad dregValue retrieved");
+        if (newValue != oldValue) {
+          if (TraceGPUInteraction) {
+            int numDRegs = hsailFrame->num_d_regs();
+            const char *name = (bit < numDRegs ? "$d" : "stk");
+            int num = (bit < numDRegs ? bit : bit - numDRegs);
+            tty->print_cr("oop moved for %s%d, workitem %d, slot %d, old=%p, new=%p",
+                          name, num, workitem, deoptSlot, oldValue, newValue);
+          }
+          putOopForBit(hsailFrame, bit, newValue);
+        }
+      }
+    }
+  }
+
+  bool isOop(HSAILFrame * hsailFrame, int bit){
+    // re-resolve on each access
+    resolveArrays();
+    if (bit > hsailFrame->num_d_regs() + hsailFrame->num_stack_slots()) {
+      return false;
+    }
+    int pcOffset = hsailFrame->pc_offset();
+    int bits_int_idx = mapPcOffsetToIndex(pcOffset) + (bit / 32);
+    int bitpos = bit % 32;
+    int bits = _oopMapArray->int_at(bits_int_idx);
+    return ((bits & (1 << bitpos)) != 0);
+  }
+
+  static int getSaveAreaCounts(jobject oopMapArrayObject) {
+    typeArrayOop oopMapArray = (typeArrayOop) JNIHandles::resolve(oopMapArrayObject);
+    return oopMapArray->int_at(SAVEAREACOUNTS_OFST);
+  }
+
+};
+
+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, jobject oop_map_array, TRAPS) {
   ResourceMark rm(THREAD);
   objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args);
 
@@ -260,9 +390,16 @@
   // Reset the kernel arguments
   _okra_clearargs(kernel);
 
+  // get how many bytes per deopt save area are required
+  int saveAreaCounts = OopSaver::getSaveAreaCounts(oop_map_array);
+  int numSRegs = saveAreaCounts & 0xff;
+  int numDRegs = (saveAreaCounts >> 8) & 0xff;
+  int numStackSlots = (saveAreaCounts >> 16);
+  int bytesPerSaveArea = numSRegs * 4 + (numDRegs + numStackSlots) * 8;
+
   HSAILDeoptimizationInfo* e;
   if (UseHSAILDeoptimization) {
-    e = new (ResourceObj::C_HEAP, mtInternal) HSAILDeoptimizationInfo();
+    e = new (MAX_DEOPT_SLOTS, bytesPerSaveArea) HSAILDeoptimizationInfo(MAX_DEOPT_SLOTS, bytesPerSaveArea);
     e->set_never_ran_array(NEW_C_HEAP_ARRAY(jboolean, dimX, mtInternal));
     memset(e->never_ran_array(), 0, dimX * sizeof(jboolean));
     e->set_donor_threads(donorThreads);
@@ -318,7 +455,6 @@
   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 != 1) {
       if (deoptcode == 0) {
@@ -337,40 +473,30 @@
         TraceTime t3("handle deoptimizing workitems", TraceGPUInteraction);
         if (TraceGPUInteraction) {
           tty->print_cr("deopt happened.");
-          HSAILKernelDeoptimization * pdeopt = &e->_deopt_save_states[0];
+          HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(0);
           tty->print_cr("first deopter was workitem %d", pdeopt->workitem());
         }
 
         // Before handling any deopting workitems, save the pointers from
         // the hsail frames in oops_save so they get adjusted by any
         // GC. Need to do this before leaving thread_in_vm mode.
+        OopSaver oopSaver(oops_save, oop_map_array);
         // resolve handle only needed once here (not exiting vm mode)
-        objArrayOop oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save);
+        oopSaver.resolveArrays();
 
         // since slots are allocated from the beginning, we know how far to look
-        assert(e->num_deopts() < MAX_DEOPT_SAVE_STATES_SIZE, "deopt save state overflow");
+        assert(e->num_deopts() < e->num_slots(), "deopt save state overflow");
         for (int k = 0; k < e->num_deopts(); k++) {
-          HSAILKernelDeoptimization * pdeopt = &e->_deopt_save_states[k];
-          jint workitem = pdeopt->workitem();
-          if (workitem != -1) {
-            // this is a workitem that deopted
-            HSAILFrame *hsailFrame = pdeopt->first_frame();
-            int dregOopMap = hsailFrame->dreg_oops_map();
-            for (int bit = 0; bit < 16; bit++) {
-              if ((dregOopMap & (1 << bit)) != 0) {
-                // the dregister at this bit is an oop, save it in the array
-                int index = k * 16 + bit;
-                void* saved_oop = (void*) hsailFrame->get_d_reg(bit);
-                oopsSaveArray->obj_at_put(index, (oop) saved_oop);
-              }
-            }
-          }
+          HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(k);
+          assert (pdeopt->workitem() >= 0, "bad workitem in deopt");
+          // this is a workitem that deopted
+          oopSaver.saveOopsFromFrame(pdeopt->first_frame(), k);
         }
 
         // Handle any deopting workitems.
         int count_deoptimized = 0;
         for (int k = 0; k < e->num_deopts(); k++) {
-          HSAILKernelDeoptimization * pdeopt = &e->_deopt_save_states[k];
+          HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(k);
 
           jint workitem = pdeopt->workitem();
           if (workitem != -1) {
@@ -378,25 +504,8 @@
             HSAILFrame *hsailFrame = pdeopt->first_frame();
 
             // update the hsailFrame from the oopsSaveArray
-            // re-resolve the handle
-            oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save);
-
-            int dregOopMap = hsailFrame->dreg_oops_map();
-            for (int bit = 0; bit < 16; bit++) {
-              if ((dregOopMap & (1 << bit)) != 0) {
-                // the dregister at this bit is an oop, retrieve it from array and put back in frame
-                int index = k * 16 + bit;
-                void * dregValue = (void *) oopsSaveArray->obj_at(index);
-                void * oldDregValue = (void *) hsailFrame->get_d_reg(bit);
-                assert((oldDregValue != 0 ? dregValue != 0 : dregValue == 0), "bad dregValue retrieved");
-                if (TraceGPUInteraction) {
-                  if (dregValue != oldDregValue) {
-                    tty->print_cr("oop moved for $d%d, workitem %d, slot %d, old=%p, new=%p", bit, workitem, k, oldDregValue, dregValue);
-                  }
-                }
-                hsailFrame->put_d_reg(bit, (jlong) dregValue);
-              }
-            }
+            // will re-resolve the handles each time
+            oopSaver.restoreOopsToFrame(hsailFrame, k, workitem);
 
             JavaValue result(T_VOID);
             JavaCallArguments javaArgs;
@@ -410,12 +519,19 @@
             javaArgs.push_int(myActionReason);
             javaArgs.push_oop((oop) NULL);
             if (TraceGPUInteraction) {
-              int dregOopMap = hsailFrame->dreg_oops_map();
-              tty->print_cr("[HSAIL] Deoptimizing to host for workitem=%d (slot=%d) with deoptId=%d, frame=" INTPTR_FORMAT ", actionAndReason=%d, dregOopMap=%04x", workitem, k, deoptId, hsailFrame, myActionReason, dregOopMap);
-              // show the registers containing references
-              for (int bit = 0; bit < 16; bit++) {
-                if ((dregOopMap & (1 << bit)) != 0) {
-                  tty->print_cr("  oop $d%d = %p", bit, hsailFrame->get_d_reg(bit));
+              tty->print_cr("[HSAIL] Deoptimizing to host for workitem=%d (slot=%d) with deoptId=%d, frame=" INTPTR_FORMAT ", actionAndReason=%d", workitem, k, deoptId, hsailFrame, myActionReason);
+              // show the $d registers or stack slots containing references
+              int maxOopBits = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots();
+              for (int bit = 0; bit < maxOopBits; bit++) {
+                if (oopSaver.isOop(hsailFrame, bit)) {
+                  if (bit < hsailFrame->num_d_regs()) {
+                    // show $d reg oop
+                    tty->print_cr("  oop $d%d = %p", bit, oopSaver.getOopForBit(hsailFrame, bit));
+                  } else {
+                    // show stack slot oop
+                    int stackOffset = (bit - hsailFrame->num_d_regs()) * 8;  // 8 bytes per stack slot
+                    tty->print_cr("  oop stk:%d = %p", stackOffset, oopSaver.getOopForBit(hsailFrame, bit));
+                  }
                 }
               }
             }
@@ -461,7 +577,7 @@
           }
         }
         TraceGPUInteraction = savedTraceGPUInteraction;
-        if (TraceGPUInteraction) {
+        if (TraceGPUInteraction && (count_never_ran > 0)) {
           tty->print_cr("%d workitems never ran, have been run via JavaCall", count_never_ran);
           showRanges(never_ran_array, dimX);
         }
--- a/src/gpu/hsail/vm/gpu_hsail.hpp	Fri May 02 11:04:51 2014 -0700
+++ b/src/gpu/hsail/vm/gpu_hsail.hpp	Fri May 02 21:58:28 2014 +0200
@@ -51,7 +51,8 @@
   };
 
 // 8 compute units * 40 waves per cu * wavesize 64
-#define MAX_DEOPT_SAVE_STATES_SIZE    (8 * 40 * 64)
+// TODO: query the device to get this number
+#define MAX_DEOPT_SLOTS    (8 * 40 * 64)
 
   class HSAILDeoptimizationInfo : public ResourceObj {
     friend class VMStructs;
@@ -61,14 +62,23 @@
     jint _deopt_next_index;
     JavaThread** _donor_threads;
     jboolean * _never_ran_array;
+    jint _num_slots;
+    jint _bytesPerSaveArea;
+    jint _deopt_span;
 
    public:
-    HSAILKernelDeoptimization _deopt_save_states[MAX_DEOPT_SAVE_STATES_SIZE];
+    HSAILKernelDeoptimization _deopt_save_states[1];  // number and size of these can vary per kernel
 
-    inline HSAILDeoptimizationInfo() {
+    inline HSAILDeoptimizationInfo(int numSlots, int bytesPerSaveArea) {
       _notice_safepoints = &Hsail::_notice_safepoints;
       _deopt_occurred = 0;
       _deopt_next_index = 0;
+      _num_slots = numSlots;
+      _bytesPerSaveArea = bytesPerSaveArea;
+      _deopt_span = sizeof(HSAILKernelDeoptimization) + bytesPerSaveArea;
+      if (TraceGPUInteraction) {
+        tty->print_cr("HSAILDeoptimizationInfo allocated, %d slots of size %d, total size = 0x%lx bytes", _num_slots, _deopt_span, (_num_slots * _deopt_span + sizeof(HSAILDeoptimizationInfo)));
+      }
     }
 
     inline jint deopt_occurred() {
@@ -78,6 +88,23 @@
     inline jboolean *never_ran_array() { return _never_ran_array; }
     inline void  set_never_ran_array(jboolean *p) { _never_ran_array = p; }
     inline void  set_donor_threads(JavaThread **threads) { _donor_threads = threads; }
+    inline jint num_slots() {return _num_slots;}
+
+    inline HSAILKernelDeoptimization * get_deopt_save_state(int slot) {
+      // use _deopt_span to index into _deopt_states
+      char *p = (char *) _deopt_save_states;
+      p += _deopt_span * slot;
+      return (HSAILKernelDeoptimization *) p;
+    }
+
+    void * operator new (size_t hdrSize, int numSlots, int bytesPerSaveArea) {
+      size_t totalSizeBytes = hdrSize + numSlots * (sizeof(HSAILKernelDeoptimization) + bytesPerSaveArea);
+      return NEW_C_HEAP_ARRAY(char, totalSizeBytes, mtInternal);
+    }
+
+    void operator delete (void *ptr) {
+      FREE_C_HEAP_ARRAY(char, ptr, mtInternal);
+    }
   };
 
 
@@ -93,7 +120,7 @@
 
   // static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args);
   JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv *env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, jobject oopsSave,
-                                                   jobject donorThreads, int allocBytesPerWorkitem);
+                                                   jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array);
 
   // static native void getThreadPointers(Object[] donorThreads, long[] threadPointersOut);
   JNIEXPORT static void get_thread_pointers(JNIEnv *env, jclass, jobject donor_threads_handle, jobject thread_ptrs_handle);
@@ -101,8 +128,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 donor_threads, int allocBytesPerWorkitem, TRAPS);
-  
+                                                  jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS);
+
   static void register_heap();
 
   static GraalEnv::CodeInstallResult install_code(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations);
--- a/src/gpu/hsail/vm/gpu_hsail_Frame.hpp	Fri May 02 11:04:51 2014 -0700
+++ b/src/gpu/hsail/vm/gpu_hsail_Frame.hpp	Fri May 02 21:58:28 2014 +0200
@@ -5,39 +5,44 @@
 #include "code/debugInfo.hpp"
 #include "code/location.hpp"
 
-// maximum registers that could be saved for now
-#define MAX_SREGS 32
-#define MAX_DREGS 16
-
 class HSAILFrame {
   friend class VMStructs;
 private:
   jint  _pc_offset;  // The HSAIL "pc_offset" where the exception happens
   jbyte _num_s_regs;
   jbyte _num_d_regs;
-  jshort _dreg_oops_map;  // bits = 1 if that dreg is an oop
-  jlong  _save_area[MAX_SREGS/2 + MAX_DREGS];  
+  jshort _num_stack_slots; 
+  jbyte  _save_area[0];     // save area size can vary per kernel compilation  
 
 public:
   // Accessors
   jint pc_offset() { return _pc_offset; }
   jint num_s_regs() {return _num_s_regs; }
   jint num_d_regs() {return _num_d_regs; }
-  jint dreg_oops_map() {return _dreg_oops_map; }
+  jint num_stack_slots() {return _num_stack_slots; }
   jlong get_d_reg(int idx) {
-    char *p = (char *) _save_area;
     int ofst = num_s_regs() * 4 + idx * 8;
-    return(*(jlong *) (p + ofst));
+    return(*(jlong *) (_save_area + ofst));
   }
   jint get_s_reg(int idx) {
-    char *p = (char *) _save_area;
     int ofst = idx * 4;
-    return(*(jint *) (p + ofst));
+    return(*(jint *) (_save_area + ofst));
   }
   void put_d_reg(int idx, jlong val) {
-    char *p = (char *) _save_area;
     int ofst = num_s_regs() * 4 + idx * 8;
-    (*(jlong *) (p + ofst)) = val;
+    (*(jlong *) (_save_area + ofst)) = val;
+  }
+  jint get_stackslot32(int stackOffset) {
+    int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset;
+    return(*(jint *) (_save_area + ofst));
+  }
+  jlong get_stackslot64(int stackOffset) {
+    int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset;
+    return(*(jlong *) (_save_area + ofst));
+  }
+  void put_stackslot64(int stackOffset, jlong val) {
+    int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset;
+    (*(jlong *) (_save_area + ofst)) = val;
   }
 };
   
--- a/src/gpu/hsail/vm/vmStructs_hsail.hpp	Fri May 02 11:04:51 2014 -0700
+++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp	Fri May 02 21:58:28 2014 +0200
@@ -32,10 +32,11 @@
 // constants required by the Serviceability Agent. This file is
 // referenced by vmStructs.cpp.
 
-#define VM_STRUCTS_GPU_HSAIL(nonstatic_field)                                                                                         \
+#define VM_STRUCTS_GPU_HSAIL(nonstatic_field)                           \
   nonstatic_field(HSAILFrame, _pc_offset,                                                  jint)                                      \
   nonstatic_field(HSAILFrame, _num_s_regs,                                                 jbyte)                                     \
-  nonstatic_field(HSAILFrame, _save_area[0],                                               jlong)                                     \
+  nonstatic_field(HSAILFrame, _num_d_regs,                                                 jbyte)                                     \
+  nonstatic_field(HSAILFrame, _num_stack_slots,                                            jshort)                                    \
                                                                                                                                       \
   nonstatic_field(Hsail::HSAILKernelDeoptimization, _workitemid,                                jint)                                 \
   nonstatic_field(Hsail::HSAILKernelDeoptimization, _actionAndReason,                           jint)                                 \
@@ -47,7 +48,6 @@
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _donor_threads,                          JavaThread**)                              \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _never_ran_array,                        jboolean *)                                \
   nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_save_states[0],                   Hsail::HSAILKernelDeoptimization)          \
-  nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_save_states[1],                   Hsail::HSAILKernelDeoptimization)
 
 #define VM_TYPES_GPU_HSAIL(declare_type, declare_toplevel_type)                 \
   declare_toplevel_type(HSAILFrame)                                  \
@@ -55,4 +55,8 @@
   declare_toplevel_type(Hsail::HSAILKernelDeoptimization)            \
   declare_toplevel_type(Hsail::HSAILDeoptimizationInfo)
 
+#define VM_INT_CONSTANTS_GPU_HSAIL(declare_constant)                                                                                  \
+  declare_constant(sizeof(HSAILFrame))                                                                                                \
+  declare_constant(sizeof(Hsail::HSAILKernelDeoptimization))                                                                          \
+
 #endif // GPU_HSAIL_VM_VMSTRUCTS_HSAIL_HPP
--- a/src/share/vm/runtime/vmStructs.cpp	Fri May 02 11:04:51 2014 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Fri May 02 21:58:28 2014 +0200
@@ -106,6 +106,7 @@
 #include "utilities/macros.hpp"
 #ifdef GRAAL
 # include "graal/vmStructs_graal.hpp"
+# include "hsail/vm/vmStructs_hsail.hpp"
 #endif
 #ifdef TARGET_ARCH_x86
 # include "vmStructs_x86.hpp"
@@ -153,8 +154,6 @@
 # include "vmStructs_bsd_zero.hpp"
 #endif
 
-#include "hsail/vm/vmStructs_hsail.hpp"
-
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
@@ -3042,7 +3041,9 @@
                  GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY,
                  GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY)
 
+#ifdef GRAAL
   VM_STRUCTS_GPU_HSAIL(GENERATE_NONSTATIC_VM_STRUCT_ENTRY)
+#endif
           
   VM_STRUCTS_OS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
                     GENERATE_STATIC_VM_STRUCT_ENTRY,
@@ -3094,8 +3095,10 @@
                GENERATE_C2_VM_TYPE_ENTRY,
                GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY)
 
+#ifdef GRAAL
   VM_TYPES_GPU_HSAIL(GENERATE_VM_TYPE_ENTRY,
                GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
+#endif
 
   VM_TYPES_OS_CPU(GENERATE_VM_TYPE_ENTRY,
                   GENERATE_TOPLEVEL_VM_TYPE_ENTRY,
@@ -3120,6 +3123,8 @@
 #ifdef GRAAL
   VM_INT_CONSTANTS_GRAAL(GENERATE_VM_INT_CONSTANT_ENTRY,
                          GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
+
+  VM_INT_CONSTANTS_GPU_HSAIL(GENERATE_VM_INT_CONSTANT_ENTRY)
 #endif
 
 #if INCLUDE_ALL_GCS
@@ -3201,7 +3206,9 @@
                  CHECK_NO_OP,
                  CHECK_NO_OP);
 
-  VM_STRUCTS_GPU_HSAIL(CHECK_NONSTATIC_VM_STRUCT_ENTRY);
+#ifdef GRAAL
+  VM_STRUCTS_GPU_HSAIL(CHECK_NONSTATIC_VM_STRUCT_ENTRY)
+#endif
 
   VM_STRUCTS_OS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
                     CHECK_STATIC_VM_STRUCT_ENTRY,
@@ -3243,8 +3250,10 @@
                CHECK_C2_VM_TYPE_ENTRY,
                CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY);
 
+#ifdef GRAAL
   VM_TYPES_GPU_HSAIL(CHECK_VM_TYPE_ENTRY,
                CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
+#endif
 
   VM_TYPES_OS_CPU(CHECK_VM_TYPE_ENTRY,
                   CHECK_SINGLE_ARG_VM_TYPE_NO_OP,