changeset 8203:1c82ddf25b20

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 11 Mar 2013 17:28:20 +0100
parents 4ba3455566e0 (current diff) 4508b693afa6 (diff)
children be49c1cab1d1
files
diffstat 14 files changed, 440 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Mon Mar 11 17:28:20 2013 +0100
@@ -439,7 +439,7 @@
     }
 
     public final void bsfq(Register dst, AMD64Address src) {
-        emitByte(Prefix.REXW);
+        prefixq(src, dst);
         emitByte(0x0F);
         emitByte(0xBC);
         emitOperandHelper(dst, src);
@@ -453,7 +453,7 @@
     }
 
     public final void bsrq(Register dst, AMD64Address src) {
-        emitByte(Prefix.REXW);
+        prefixq(src, dst);
         emitByte(0x0F);
         emitByte(0xBD);
         emitOperandHelper(dst, src);
@@ -539,6 +539,15 @@
         }
     }
 
+    public final void cvtsd2ss(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x5A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsd2ss(Register dst, Register src) {
         assert dst.isFpu();
         assert src.isFpu();
@@ -549,6 +558,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvtsi2sdl(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsi2sdl(Register dst, Register src) {
         assert dst.isFpu();
         emitByte(0xF2);
@@ -558,6 +576,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvtsi2ssl(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsi2ssl(Register dst, Register src) {
         assert dst.isFpu();
         emitByte(0xF3);
@@ -567,6 +594,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvtss2sd(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x5A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtss2sd(Register dst, Register src) {
         assert dst.isFpu();
         assert src.isFpu();
@@ -577,6 +613,14 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvttsd2sil(Register dst, AMD64Address src) {
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvttsd2sil(Register dst, Register src) {
         assert src.isFpu();
         emitByte(0xF2);
@@ -586,6 +630,14 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvttss2sil(Register dst, AMD64Address src) {
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvttss2sil(Register dst, Register src) {
         assert src.isFpu();
         emitByte(0xF3);
@@ -1055,6 +1107,13 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void movsxw(Register dst, AMD64Address src) {
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0xBF);
+        emitOperandHelper(dst, src);
+    }
+
     public final void movw(AMD64Address dst, int imm16) {
         emitByte(0x66); // switch to 16-bit mode
         prefix(dst);
@@ -1954,6 +2013,15 @@
         emitOperandHelper(reg, adr);
     }
 
+    public final void cvtsi2sdq(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsi2sdq(Register dst, Register src) {
         assert dst.isFpu();
         emitByte(0xF2);
@@ -1963,6 +2031,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvtsi2ssq(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsi2ssq(Register dst, Register src) {
         assert dst.isFpu();
         emitByte(0xF3);
@@ -1972,6 +2049,14 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvttsd2siq(Register dst, AMD64Address src) {
+        emitByte(0xF2);
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvttsd2siq(Register dst, Register src) {
         assert src.isFpu();
         emitByte(0xF2);
@@ -1981,6 +2066,14 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvttss2siq(Register dst, AMD64Address src) {
+        emitByte(0xF3);
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvttss2siq(Register dst, Register src) {
         assert src.isFpu();
         emitByte(0xF3);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java	Mon Mar 11 17:28:20 2013 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.amd64.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.backend.*;
+
+public class AMD64AllocatorTest extends AllocatorTest {
+
+    @Test
+    public void test1() {
+        test("test1snippet", 2, 1, 0);
+    }
+
+    public static long test1snippet(long x) {
+        return x + 5;
+    }
+
+    @Ignore
+    @Test
+    public void test2() {
+        test("test2snippet", 2, 0, 0);
+    }
+
+    public static long test2snippet(long x) {
+        return x * 5;
+    }
+
+    @Ignore
+    @Test
+    public void test3() {
+        test("test3snippet", 4, 1, 0);
+    }
+
+    public static long test3snippet(long x) {
+        return x / 3 + x % 3;
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Mar 11 17:28:20 2013 +0100
@@ -41,36 +41,7 @@
 
 public class AllocatorTest extends GraalCompilerTest {
 
-    @Test
-    public void test1() {
-        test("test1snippet", 2, 1, 0);
-    }
-
-    public static long test1snippet(long x) {
-        return x + 5;
-    }
-
-    @Ignore
-    @Test
-    public void test2() {
-        test("test2snippet", 2, 0, 0);
-    }
-
-    public static long test2snippet(long x) {
-        return x * 5;
-    }
-
-    @Ignore
-    @Test
-    public void test3() {
-        test("test3snippet", 4, 1, 0);
-    }
-
-    public static long test3snippet(long x) {
-        return x / 3 + x % 3;
-    }
-
-    private void test(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) {
+    protected void test(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) {
         final StructuredGraph graph = parse(snippet);
         Debug.scope("AllocatorTest", new Object[]{graph, graph.method(), backend.target}, new Runnable() {
 
@@ -91,7 +62,7 @@
         });
     }
 
-    class RegisterStats {
+    private class RegisterStats {
 
         public final LIR lir;
         public HashSet<Register> registers = new HashSet<>();
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java	Mon Mar 11 17:28:20 2013 +0100
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.snippets.SnippetTemplate.*;
 import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
+import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -58,6 +59,7 @@
     @Snippet
     public static int f2i(@Parameter("input") float input, @Parameter("result") int result) {
         if (result == Integer.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
             if (Float.isNaN(input)) {
                 // input is NaN -> return 0
                 return 0;
@@ -83,6 +85,7 @@
     @Snippet
     public static long f2l(@Parameter("input") float input, @Parameter("result") long result) {
         if (result == Long.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
             if (Float.isNaN(input)) {
                 // input is NaN -> return 0
                 return 0;
@@ -108,6 +111,7 @@
     @Snippet
     public static int d2i(@Parameter("input") double input, @Parameter("result") int result) {
         if (result == Integer.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
             if (Double.isNaN(input)) {
                 // input is NaN -> return 0
                 return 0;
@@ -133,6 +137,7 @@
     @Snippet
     public static long d2l(@Parameter("input") double input, @Parameter("result") long result) {
         if (result == Long.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
             if (Double.isNaN(input)) {
                 // input is NaN -> return 0
                 return 0;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Mon Mar 11 17:28:20 2013 +0100
@@ -62,4 +62,13 @@
     public static GraphBuilderConfiguration getSnippetDefault() {
         return new GraphBuilderConfiguration(true, true);
     }
+
+    /**
+     * Returns {@code true} if it is an error for a class/field/method resolution to fail.
+     * The default is the same result as returned by {@link #eagerResolving()}.
+     * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}.
+     */
+    public boolean unresolvedIsError() {
+        return eagerResolving;
+    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Mar 11 17:28:20 2013 +0100
@@ -114,6 +114,20 @@
 
     private Block[] loopHeaders;
 
+    /**
+     * Gets the current frame state being processed by this builder.
+     */
+    protected FrameStateBuilder getCurrentFrameState() {
+        return frameState;
+    }
+
+    /**
+     * Gets the graph being processed by this builder.
+     */
+    protected StructuredGraph getGraph() {
+        return currentGraph;
+    }
+
     public GraphBuilderPhase(MetaAccessProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
         this.graphBuilderConfig = graphBuilderConfig;
         this.optimisticOpts = optimisticOpts;
@@ -261,6 +275,99 @@
         return handler.catchTypeCPI() == 0;
     }
 
+    /**
+     * @param type the unresolved type of the constant
+     */
+    protected void handleUnresolvedLoadConstant(JavaType type) {
+        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+        frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
+    }
+
+    /**
+     * @param type the unresolved type of the type check
+     * @param object the object value whose type is being checked against {@code type}
+     */
+    protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) {
+        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile)));
+        frameState.apush(appendConstant(Constant.NULL_OBJECT));
+    }
+
+    /**
+     * @param type the unresolved type of the type check
+     * @param object the object value whose type is being checked against {@code type}
+     */
+    protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) {
+        BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode());
+        DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved));
+        IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1));
+        append(ifNode);
+        lastInstr = successor;
+        frameState.ipush(appendConstant(Constant.INT_0));
+    }
+
+    /**
+     * @param type the type being instantiated
+     */
+    protected void handleUnresolvedNewInstance(JavaType type) {
+        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+        frameState.apush(appendConstant(Constant.NULL_OBJECT));
+    }
+
+    /**
+     * @param type the type of the array being instantiated
+     * @param length the length of the array
+     */
+    protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) {
+        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+        frameState.apush(appendConstant(Constant.NULL_OBJECT));
+    }
+
+    /**
+     * @param type the type being instantiated
+     * @param dims the dimensions for the multi-array
+     */
+    protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) {
+        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+        frameState.apush(appendConstant(Constant.NULL_OBJECT));
+    }
+
+    /**
+     * @param field the unresolved field
+     * @param receiver the object containing the field or {@code null} if {@code field} is static
+     */
+    protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) {
+        Kind kind = field.getKind();
+        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+        frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+    }
+
+    /**
+     * @param field the unresolved field
+     * @param value the value being stored to the field
+     * @param receiver the object containing the field or {@code null} if {@code field} is static
+     */
+    protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) {
+        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+    }
+
+    /**
+     * @param representation
+     * @param type
+     */
+    protected void handleUnresolvedExceptionType(Representation representation, JavaType type) {
+        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+    }
+
+    protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) {
+        boolean withReceiver = invokeKind != InvokeKind.Static;
+        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+        frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver));
+        Kind kind = javaMethod.getSignature().getReturnKind();
+        if (kind != Kind.Void) {
+            frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+        }
+    }
+
     private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) {
         assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci";
         Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci));
@@ -307,8 +414,7 @@
             if (type instanceof ResolvedJavaType) {
                 frameState.push(Kind.Object, append(ConstantNode.forConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass), runtime, currentGraph)));
             } else {
-                append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-                frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
+                handleUnresolvedLoadConstant(type);
             }
         } else if (con instanceof Constant) {
             Constant constant = (Constant) con;
@@ -636,21 +742,21 @@
     private JavaType lookupType(int cpi, int bytecode) {
         eagerResolvingForSnippets(cpi, bytecode);
         JavaType result = constantPool.lookupType(cpi, bytecode);
-        assert !graphBuilderConfig.eagerResolving() || result instanceof ResolvedJavaType;
+        assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
         return result;
     }
 
     private JavaMethod lookupMethod(int cpi, int opcode) {
         eagerResolvingForSnippets(cpi, opcode);
         JavaMethod result = constantPool.lookupMethod(cpi, opcode);
-        assert !graphBuilderConfig.eagerResolving() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result;
+        assert !graphBuilderConfig.unresolvedIsError() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result;
         return result;
     }
 
     private JavaField lookupField(int cpi, int opcode) {
         eagerResolvingForSnippets(cpi, opcode);
         JavaField result = constantPool.lookupField(cpi, opcode);
-        assert !graphBuilderConfig.eagerResolving() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
+        assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
         return result;
     }
 
@@ -683,16 +789,13 @@
     private void genCheckCast() {
         int cpi = stream().readCPI();
         JavaType type = lookupType(cpi, CHECKCAST);
-        boolean initialized = type instanceof ResolvedJavaType;
-        if (initialized) {
-            ValueNode object = frameState.apop();
+        ValueNode object = frameState.apop();
+        if (type instanceof ResolvedJavaType) {
             CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) type, object, getProfileForTypeCheck((ResolvedJavaType) type)));
             append(checkCast);
             frameState.apush(checkCast);
         } else {
-            ValueNode object = frameState.apop();
-            append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile)));
-            frameState.apush(appendConstant(Constant.NULL_OBJECT));
+            handleUnresolvedCheckCast(type, object);
         }
     }
 
@@ -706,12 +809,7 @@
             ConditionalNode conditional = currentGraph.unique(new ConditionalNode(currentGraph.unique(instanceOfNode), ConstantNode.forInt(1, currentGraph), ConstantNode.forInt(0, currentGraph)));
             frameState.ipush(append(conditional));
         } else {
-            BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode());
-            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved));
-            IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1));
-            append(ifNode);
-            lastInstr = successor;
-            frameState.ipush(appendConstant(Constant.INT_0));
+            handleUnresolvedInstanceOf(type, object);
         }
     }
 
@@ -721,8 +819,7 @@
             NewInstanceNode n = currentGraph.add(new NewInstanceNode((ResolvedJavaType) type, true, false));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.apush(appendConstant(Constant.NULL_OBJECT));
+            handleUnresolvedNewInstance(type);
         }
     }
 
@@ -772,8 +869,7 @@
             NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true, false));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.apush(appendConstant(Constant.NULL_OBJECT));
+            handleUnresolvedNewObjectArray(type, length);
         }
 
     }
@@ -789,8 +885,7 @@
             FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((ResolvedJavaType) type, dims));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.apush(appendConstant(Constant.NULL_OBJECT));
+            handleUnresolvedNewMultiArray(type, dims);
         }
     }
 
@@ -803,8 +898,7 @@
             LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (ResolvedJavaField) field));
             appendOptimizedLoadField(kind, load);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+            handleUnresolvedLoadField(field, receiver);
         }
     }
 
@@ -890,7 +984,7 @@
             StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (ResolvedJavaField) field, value));
             appendOptimizedStoreField(store);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+            handleUnresolvedStoreField(field, value, receiver);
         }
     }
 
@@ -905,8 +999,7 @@
                 appendOptimizedLoadField(kind, load);
             }
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+            handleUnresolvedLoadField(field, null);
         }
     }
 
@@ -916,15 +1009,15 @@
             StoreFieldNode store = currentGraph.add(new StoreFieldNode(null, (ResolvedJavaField) field, value));
             appendOptimizedStoreField(store);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+            handleUnresolvedStoreField(field, value, null);
         }
     }
 
-    private ConstantNode genTypeOrDeopt(Representation representation, JavaType holder, boolean initialized) {
+    private ConstantNode genTypeOrDeopt(Representation representation, JavaType type, boolean initialized) {
         if (initialized) {
-            return appendConstant(((ResolvedJavaType) holder).getEncoding(representation));
+            return appendConstant(((ResolvedJavaType) type).getEncoding(representation));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+            handleUnresolvedExceptionType(representation, type);
             return null;
         }
     }
@@ -944,13 +1037,13 @@
             ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
             ResolvedJavaType holder = resolvedTarget.getDeclaringClass();
             if (!holder.isInitialized() && GraalOptions.ResolveClassBeforeStaticInvoke) {
-                genInvokeDeopt(target, false);
+                handleUnresolvedInvoke(target, InvokeKind.Static);
             } else {
                 ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false));
                 appendInvoke(InvokeKind.Static, resolvedTarget, args);
             }
         } else {
-            genInvokeDeopt(target, false);
+            handleUnresolvedInvoke(target, InvokeKind.Static);
         }
     }
 
@@ -959,7 +1052,7 @@
             ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
             genInvokeIndirect(InvokeKind.Interface, (ResolvedJavaMethod) target, args);
         } else {
-            genInvokeDeopt(target, true);
+            handleUnresolvedInvoke(target, InvokeKind.Interface);
         }
     }
 
@@ -968,7 +1061,7 @@
             ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
             genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
         } else {
-            genInvokeDeopt(target, true);
+            handleUnresolvedInvoke(target, InvokeKind.Virtual);
         }
 
     }
@@ -980,16 +1073,7 @@
             ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
             invokeDirect((ResolvedJavaMethod) target, args);
         } else {
-            genInvokeDeopt(target, true);
-        }
-    }
-
-    private void genInvokeDeopt(JavaMethod unresolvedTarget, boolean withReceiver) {
-        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-        frameState.popArguments(unresolvedTarget.getSignature().getParameterSlots(withReceiver), unresolvedTarget.getSignature().getParameterCount(withReceiver));
-        Kind kind = unresolvedTarget.getSignature().getReturnKind();
-        if (kind != Kind.Void) {
-            frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+            handleUnresolvedInvoke(target, InvokeKind.Special);
         }
     }
 
@@ -1213,7 +1297,7 @@
         }
     }
 
-    private ConstantNode appendConstant(Constant constant) {
+    protected ConstantNode appendConstant(Constant constant) {
         assert constant != null;
         return ConstantNode.forConstant(constant, runtime, currentGraph);
     }
@@ -1224,7 +1308,7 @@
         return fixed;
     }
 
-    private ValueNode append(FixedWithNextNode x) {
+    protected ValueNode append(FixedWithNextNode x) {
         return appendWithBCI(x);
     }
 
@@ -1232,7 +1316,7 @@
         return v;
     }
 
-    private ValueNode appendWithBCI(FixedWithNextNode x) {
+    protected ValueNode appendWithBCI(FixedWithNextNode x) {
         assert x.predecessor() == null : "instruction should not have been appended yet";
         assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
         lastInstr.setNext(x);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Mon Mar 11 17:28:20 2013 +0100
@@ -58,7 +58,7 @@
     public static class Unary2Op extends AMD64LIRInstruction {
         @Opcode private final AMD64Arithmetic opcode;
         @Def({REG}) protected AllocatableValue result;
-        @Use({REG}) protected AllocatableValue x;
+        @Use({REG, STACK}) protected AllocatableValue x;
 
         public Unary2Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) {
             this.opcode = opcode;
@@ -455,6 +455,33 @@
                 case DSUB: masm.subsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
                 case DMUL: masm.mulsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
                 case DDIV: masm.divsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
+
+                case I2B: masm.movsxb(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case I2S: masm.movsxw(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case I2L: masm.movslq(asLongReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case F2D: masm.cvtss2sd(asDoubleReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break;
+                case D2F: masm.cvtsd2ss(asFloatReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
+                case I2F: masm.cvtsi2ssl(asFloatReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case I2D: masm.cvtsi2sdl(asDoubleReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case L2F: masm.cvtsi2ssq(asFloatReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case L2D: masm.cvtsi2sdq(asDoubleReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case F2I:
+                    masm.cvttss2sil(asIntReg(dst), (AMD64Address) tasm.asFloatAddr(src));
+                    break;
+                case D2I:
+                    masm.cvttsd2sil(asIntReg(dst), (AMD64Address) tasm.asDoubleAddr(src));
+                    break;
+                case F2L:
+                    masm.cvttss2siq(asLongReg(dst), (AMD64Address) tasm.asFloatAddr(src));
+                    break;
+                case D2L:
+                    masm.cvttsd2siq(asLongReg(dst), (AMD64Address) tasm.asDoubleAddr(src));
+                    break;
+                case MOV_I2F: masm.movss(asFloatReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case MOV_L2D: masm.movsd(asDoubleReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case MOV_F2I: masm.movl(asIntReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break;
+                case MOV_D2L: masm.movq(asLongReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
+
                 default:   throw GraalInternalError.shouldNotReachHere();
             }
         }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Mon Mar 11 17:28:20 2013 +0100
@@ -63,7 +63,10 @@
             // make sure that the displacement word of the call ends up word aligned
             int offset = masm.codeBuffer.position();
             offset += tasm.target.arch.getMachineCodeCallDisplacementOffset();
-            masm.nop(tasm.target.wordSize - offset % tasm.target.wordSize);
+            int modulus = tasm.target.wordSize;
+            if (offset % modulus != 0) {
+                masm.nop(modulus - offset % modulus);
+            }
         }
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Mar 11 17:28:20 2013 +0100
@@ -22,11 +22,14 @@
  */
 package com.oracle.graal.lir;
 
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.Map.Entry;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
@@ -37,6 +40,8 @@
 
     private static final Class<Value> VALUE_CLASS = Value.class;
     private static final Class<Constant> CONSTANT_CLASS = Constant.class;
+    private static final Class<RegisterValue> REGISTER_VALUE_CLASS = RegisterValue.class;
+    private static final Class<StackSlot> STACK_SLOT_CLASS = StackSlot.class;
     private static final Class<Value[]> VALUE_ARRAY_CLASS = Value[].class;
 
     public LIRIntrospection(Class<?> clazz) {
@@ -82,11 +87,15 @@
                 OperandModeAnnotation annotation = getOperandModeAnnotation(field);
                 assert annotation != null : "Field must have operand mode annotation: " + field;
                 annotation.scalarOffsets.add(offset);
+                EnumSet<OperandFlag> flags = getFlags(field);
+                assert verifyFlags(field, type, flags);
                 annotation.flags.put(offset, getFlags(field));
             } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) {
                 OperandModeAnnotation annotation = getOperandModeAnnotation(field);
                 assert annotation != null : "Field must have operand mode annotation: " + field;
                 annotation.arrayOffsets.add(offset);
+                EnumSet<OperandFlag> flags = getFlags(field);
+                assert verifyFlags(field, type.getComponentType(), flags);
                 annotation.flags.put(offset, getFlags(field));
             } else {
                 assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field;
@@ -94,6 +103,19 @@
                 dataOffsets.add(offset);
             }
         }
+
+        private static boolean verifyFlags(Field field, Class<?> type, EnumSet<OperandFlag> flags) {
+            if (flags.contains(REG)) {
+                assert type.isAssignableFrom(REGISTER_VALUE_CLASS) : "Cannot assign RegisterValue to field with REG flag:" + field;
+            }
+            if (flags.contains(STACK)) {
+                assert type.isAssignableFrom(STACK_SLOT_CLASS) : "Cannot assign StackSlot to field with STACK flag:" + field;
+            }
+            if (flags.contains(CONST)) {
+                assert type.isAssignableFrom(CONSTANT_CLASS) : "Cannot assign Constant to field with CONST flag:" + field;
+            }
+            return true;
+        }
     }
 
     protected static void forEach(Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure proc) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Mon Mar 11 17:28:20 2013 +0100
@@ -29,10 +29,14 @@
 /**
  * Marks a position in the graph where a safepoint should be emitted.
  */
-public final class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
+public class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
 
     public SafepointNode() {
-        super(StampFactory.forVoid());
+        this(StampFactory.forVoid());
+    }
+
+    public SafepointNode(Stamp stamp) {
+        super(stamp);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Mar 11 17:28:20 2013 +0100
@@ -53,6 +53,9 @@
         if (kind() != Kind.Object || object().kind() != Kind.Object) {
             return false;
         }
+        if (stamp() == StampFactory.forNodeIntrinsic()) {
+            return false;
+        }
         if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
             // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull
             // guard, but the
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Mon Mar 11 17:28:03 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Mon Mar 11 17:28:20 2013 +0100
@@ -53,10 +53,10 @@
  */
 public class SnippetInstaller {
 
-    private final MetaAccessProvider runtime;
-    private final TargetDescription target;
-    private final Assumptions assumptions;
-    private final BoxingMethodPool pool;
+    protected final MetaAccessProvider runtime;
+    protected final TargetDescription target;
+    protected final Assumptions assumptions;
+    protected final BoxingMethodPool pool;
     private final Thread owner;
 
     /**
@@ -191,6 +191,19 @@
         }
     }
 
+    /**
+     * Does final processing of a snippet graph.
+     */
+    protected void finalizeGraph(ResolvedJavaMethod method, StructuredGraph graph) {
+        new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
+        assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph);
+
+        new SnippetFrameStateCleanupPhase().apply(graph);
+        new DeadCodeEliminationPhase().apply(graph);
+
+        new InsertStateAfterPlaceholderPhase().apply(graph);
+    }
+
     public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
         return Debug.scope("BuildSnippetGraph", new Object[]{method}, new Callable<StructuredGraph>() {
 
@@ -198,13 +211,7 @@
             public StructuredGraph call() throws Exception {
                 StructuredGraph graph = parseGraph(method, policy);
 
-                new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
-                assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph);
-
-                new SnippetFrameStateCleanupPhase().apply(graph);
-                new DeadCodeEliminationPhase().apply(graph);
-
-                new InsertStateAfterPlaceholderPhase().apply(graph);
+                finalizeGraph(method, graph);
 
                 Debug.dump(graph, "%s: Final", method.getName());
 
@@ -222,8 +229,10 @@
         return graph;
     }
 
-    private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
-        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method;
+    /**
+     * Builds the initial graph for a snippet.
+     */
+    protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod method) {
         final StructuredGraph graph = new StructuredGraph(method);
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
         GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
@@ -232,9 +241,42 @@
         Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName());
 
         new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
+        new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
 
+        return graph;
+    }
+
+    /**
+     * Called after a graph is inlined.
+     * 
+     * @param caller the graph into which {@code callee} was inlined
+     * @param callee the graph that was inlined into {@code caller}
+     */
+    protected void afterInline(StructuredGraph caller, StructuredGraph callee) {
+        if (GraalOptions.OptCanonicalizer) {
+            new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller);
+            new CanonicalizerPhase(runtime, assumptions).apply(caller);
+        }
+    }
+
+    /**
+     * Called after all inlining for a given graph is complete.
+     */
+    protected void afterInlining(StructuredGraph graph) {
         new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
 
+        new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
+
+        new DeadCodeEliminationPhase().apply(graph);
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(runtime, assumptions).apply(graph);
+        }
+    }
+
+    private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
+        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method;
+        final StructuredGraph graph = buildInitialGraph(method);
+
         for (Invoke invoke : graph.getInvokes()) {
             MethodCallTargetNode callTarget = invoke.methodCallTarget();
             ResolvedJavaMethod callee = callTarget.targetMethod();
@@ -244,31 +286,19 @@
                 InliningUtil.inline(invoke, originalGraph, true);
 
                 Debug.dump(graph, "after inlining %s", callee);
-                if (GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase(runtime, assumptions).apply(graph);
-                }
+                afterInline(graph, originalGraph);
                 substituteCallsOriginal = true;
             } else {
                 if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) {
                     StructuredGraph targetGraph = parseGraph(callee, policy);
                     InliningUtil.inline(invoke, targetGraph, true);
                     Debug.dump(graph, "after inlining %s", callee);
-                    if (GraalOptions.OptCanonicalizer) {
-                        new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
-                        new CanonicalizerPhase(runtime, assumptions).apply(graph);
-                    }
+                    afterInline(graph, targetGraph);
                 }
             }
         }
 
-        new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
-
-        new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
-
-        new DeadCodeEliminationPhase().apply(graph);
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
-        }
+        afterInlining(graph);
 
         for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
             end.disableSafepoint();
--- a/mx/projects	Mon Mar 11 17:28:03 2013 +0100
+++ b/mx/projects	Mon Mar 11 17:28:20 2013 +0100
@@ -238,6 +238,13 @@
 project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.amd64@javaCompliance=1.7
 
+# graal.compiler.amd64.test
+project@com.oracle.graal.compiler.amd64.test@subDir=graal
+project@com.oracle.graal.compiler.amd64.test@sourceDirs=src
+project@com.oracle.graal.compiler.amd64.test@dependencies=com.oracle.graal.compiler.test
+project@com.oracle.graal.compiler.amd64.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.compiler.amd64.test@javaCompliance=1.7
+
 # graal.compiler.ptx
 project@com.oracle.graal.compiler.ptx@subDir=graal
 project@com.oracle.graal.compiler.ptx@sourceDirs=src
--- a/mxtool/mx.py	Mon Mar 11 17:28:03 2013 +0100
+++ b/mxtool/mx.py	Mon Mar 11 17:28:20 2013 +0100
@@ -2337,6 +2337,14 @@
         out.open('project', {'name' : p.name, 'default' : 'default', 'basedir' : '.'})
         out.element('description', data='Builds, tests, and runs the project ' + p.name + '.')
         out.element('import', {'file' : 'nbproject/build-impl.xml'})
+        out.open('target', {'name' : '-post-compile'})
+        out.open('exec', { 'executable' : sys.executable})
+        out.element('env', {'key' : 'JAVA_HOME', 'value' : java().jdk})
+        out.element('arg', {'value' : os.path.abspath(__file__)})
+        out.element('arg', {'value' : 'archive'})
+        out.element('arg', {'value' : '@GRAAL'})
+        out.close('exec')
+        out.close('target')
         out.close('project')
         updated = update_file(join(p.dir, 'build.xml'), out.xml(indent='\t', newl='\n')) or updated