changeset 12636:748b8381b171

Merge.
author Christian Humer <christian.humer@gmail.com>
date Tue, 29 Oct 2013 16:23:59 +0100
parents ba6593e52d22 (current diff) 7f55cdeec6af (diff)
children 9b23caa3ad31
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerThread.java
diffstat 30 files changed, 582 insertions(+), 359 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Tue Oct 29 16:23:59 2013 +0100
@@ -138,12 +138,18 @@
         if (values != null) {
             if (!type.isArray()) {
                 ResolvedJavaField[] fields = type.getInstanceFields(true);
-                assert fields.length == values.length : type + ": fields=" + Arrays.toString(fields) + ", field values=" + Arrays.toString(values);
+                int fieldIndex = 0;
                 for (int i = 0; i < values.length; i++) {
-                    ResolvedJavaField field = fields[i];
+                    ResolvedJavaField field = fields[fieldIndex++];
                     Kind valKind = values[i].getKind().getStackKind();
-                    assert valKind == field.getKind().getStackKind() : field + ": " + valKind + " != " + field.getKind().getStackKind();
+                    if ((valKind == Kind.Double || valKind == Kind.Long) && field.getKind() == Kind.Int) {
+                        assert fields[fieldIndex].getKind() == Kind.Int;
+                        fieldIndex++;
+                    } else {
+                        assert valKind == field.getKind().getStackKind() : field + ": " + valKind + " != " + field.getKind().getStackKind();
+                    }
                 }
+                assert fields.length == fieldIndex : type + ": fields=" + Arrays.toString(fields) + ", field values=" + Arrays.toString(values);
             } else {
                 Kind componentKind = type.getComponentType().getKind().getStackKind();
                 for (int i = 0; i < values.length; i++) {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Tue Oct 29 16:23:59 2013 +0100
@@ -112,11 +112,15 @@
 
     @Override
     public String toString() {
-        String annotationSuffix = "";
-        if (getKind() != Kind.Object && getPrimitiveAnnotation() != null) {
-            annotationSuffix = "{" + getPrimitiveAnnotation() + "}";
+        if (getKind() == Kind.Illegal) {
+            return "illegal";
+        } else {
+            String annotationSuffix = "";
+            if (getKind() != Kind.Object && getPrimitiveAnnotation() != null) {
+                annotationSuffix = "{" + getPrimitiveAnnotation() + "}";
+            }
+            return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]" + annotationSuffix;
         }
-        return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]" + annotationSuffix;
     }
 
     /**
@@ -144,6 +148,8 @@
                 return asDouble();
             case Object:
                 return object;
+            case Illegal:
+                return this;
         }
         throw new IllegalArgumentException();
     }
@@ -427,6 +433,10 @@
         }
     }
 
+    public static Constant forIllegal() {
+        return new Constant(Kind.Illegal, null, 0);
+    }
+
     /**
      * Returns a constant with the default value for the given kind.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThreadFactory.java	Tue Oct 29 16:23:59 2013 +0100
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.debug.*;
+
+/**
+ * Facility for creating {@linkplain CompilerThread compiler threads}.
+ */
+public class CompilerThreadFactory implements ThreadFactory {
+
+    /**
+     * Capability to get a thread-local debug configuration for the current thread.
+     */
+    public interface DebugConfigAccess {
+        /**
+         * Get a thread-local debug configuration for the current thread. This will be null if
+         * debugging is {@linkplain Debug#isEnabled() disabled}.
+         */
+        GraalDebugConfig getDebugConfig();
+    }
+
+    protected final String threadNamePrefix;
+    protected final DebugConfigAccess debugConfigAccess;
+
+    public CompilerThreadFactory(String threadNamePrefix, DebugConfigAccess debugConfigAccess) {
+        this.threadNamePrefix = threadNamePrefix;
+        this.debugConfigAccess = debugConfigAccess;
+    }
+
+    public Thread newThread(Runnable r) {
+        return new CompilerThread(r, threadNamePrefix, debugConfigAccess);
+    }
+
+    /**
+     * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY} and executes in
+     * the context of a thread-local {@linkplain GraalDebugConfig debug configuration}.
+     */
+    public static class CompilerThread extends Thread {
+
+        private final DebugConfigAccess debugConfigAccess;
+
+        public CompilerThread(Runnable r, String namePrefix, DebugConfigAccess debugConfigAccess) {
+            super(r);
+            this.setName(namePrefix + "-" + this.getId());
+            this.setPriority(Thread.MAX_PRIORITY);
+            this.setDaemon(true);
+            this.debugConfigAccess = debugConfigAccess;
+        }
+
+        @Override
+        public void run() {
+            GraalDebugConfig debugConfig = debugConfigAccess.getDebugConfig();
+            try {
+                super.run();
+            } finally {
+                if (debugConfig != null) {
+                    for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) {
+                        try {
+                            dumpHandler.close();
+                        } catch (Throwable t) {
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Tue Oct 29 16:23:59 2013 +0100
@@ -87,8 +87,17 @@
                             changed = true;
                             VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobj);
                             assert currentField != null;
+                            int pos = 0;
                             for (int i = 0; i < vobj.entryCount(); i++) {
-                                values[i] = toValue(currentField.fieldValues().get(i));
+                                if (!currentField.fieldValues().get(i).isConstant() || currentField.fieldValues().get(i).asConstant().getKind() != Kind.Illegal) {
+                                    values[pos++] = toValue(currentField.fieldValues().get(i));
+                                } else {
+                                    assert currentField.fieldValues().get(i - 1).kind() == Kind.Double || currentField.fieldValues().get(i - 1).kind() == Kind.Long : vobj + " " + i + " " +
+                                                    currentField.fieldValues().get(i - 1);
+                                }
+                            }
+                            if (pos != vobj.entryCount()) {
+                                values = Arrays.copyOf(values, pos);
                             }
                         }
                         entry.getValue().setValues(values);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Oct 29 16:23:59 2013 +0100
@@ -34,6 +34,7 @@
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.CompilerThreadFactory.CompilerThread;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.hotspot.meta.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Mon Oct 28 11:06:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot;
-
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
-import java.io.*;
-import java.util.concurrent.*;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.printer.*;
-
-public final class CompilerThread extends Thread {
-
-    public static final ThreadFactory FACTORY = new ThreadFactory() {
-
-        @Override
-        public Thread newThread(Runnable r) {
-            return new CompilerThread(r);
-        }
-    };
-
-    private CompilerThread(Runnable r) {
-        super(r);
-        this.setName("GraalCompilerThread-" + this.getId());
-        this.setPriority(MAX_PRIORITY);
-        this.setDaemon(true);
-    }
-
-    @Override
-    public void run() {
-        GraalDebugConfig debugConfig = null;
-        if (Debug.isEnabled()) {
-            PrintStream log = runtime().getVMToCompiler().log();
-            debugConfig = DebugEnvironment.initialize(log);
-        }
-        try {
-            super.run();
-        } finally {
-            if (debugConfig != null) {
-                for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) {
-                    try {
-                        dumpHandler.close();
-                    } catch (Throwable t) {
-
-                    }
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Tue Oct 29 16:23:59 2013 +0100
@@ -127,6 +127,12 @@
 
     /**
      * Updates a given stub with respect to the registers it destroys.
+     * <p>
+     * Any entry in {@code calleeSaveInfo} that {@linkplain SaveRegistersOp#supportsRemove()
+     * supports} pruning will have {@code destroyedRegisters}
+     * {@linkplain SaveRegistersOp#remove(Set) removed} as these registers are declared as
+     * temporaries in the stub's {@linkplain ForeignCallLinkage linkage} (and thus will be saved by
+     * the stub's caller).
      * 
      * @param stub the stub to update
      * @param destroyedRegisters the registers destroyed by the stub
@@ -141,10 +147,6 @@
         for (Map.Entry<LIRFrameState, SaveRegistersOp> e : calleeSaveInfo.entrySet()) {
             SaveRegistersOp save = e.getValue();
             if (save.supportsRemove()) {
-                // Since the registers destroyed by the stub are declared as temporaries in the
-                // linkage (see ForeignCallLinkage.getTemporaries()) for the stub, the caller
-                // will already save these registers and so there's no need for the stub to
-                // save them again.
                 save.remove(destroyedRegisters);
             }
             DebugInfo info = e.getKey() == null ? null : e.getKey().debugInfo();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Oct 29 16:23:59 2013 +0100
@@ -39,6 +39,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.CompilerThreadFactory.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
@@ -192,7 +194,12 @@
         }
 
         // Create compilation queue.
-        compileQueue = new ThreadPoolExecutor(Threads.getValue(), Threads.getValue(), 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), CompilerThread.FACTORY);
+        CompilerThreadFactory factory = new CompilerThreadFactory("GraalCompilerThread", new DebugConfigAccess() {
+            public GraalDebugConfig getDebugConfig() {
+                return Debug.isEnabled() ? DebugEnvironment.initialize(log) : null;
+            }
+        });
+        compileQueue = new ThreadPoolExecutor(Threads.getValue(), Threads.getValue(), 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), factory);
 
         // Create queue status printing thread.
         if (PrintQueue.getValue()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostLoweringProvider.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostLoweringProvider.java	Tue Oct 29 16:23:59 2013 +0100
@@ -317,10 +317,19 @@
                             if (value == null) {
                                 omittedValues.set(valuePos);
                             } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
+                                // Constant.illegal is always the defaultForKind, so it is skipped
                                 VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
-                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true),
-                                                (virtualInstance.field(i).getKind() == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE,
-                                                virtualInstance.field(i).getKind() == Kind.Object);
+                                Kind accessKind;
+                                HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) virtualInstance.field(i);
+                                if (value.kind().getStackKind() != field.getKind().getStackKind()) {
+                                    assert value.kind() == Kind.Long || value.kind() == Kind.Double;
+                                    accessKind = value.kind();
+                                } else {
+                                    accessKind = field.getKind();
+                                }
+                                ConstantLocationNode location = ConstantLocationNode.create(INIT_LOCATION, accessKind, field.offset(), graph);
+                                BarrierType barrierType = (virtualInstance.field(i).getKind() == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE;
+                                WriteNode write = new WriteNode(newObject, value, location, barrierType, virtualInstance.field(i).getKind() == Kind.Object);
                                 graph.addAfterFixed(newObject, graph.add(write));
                             }
                             valuePos++;
@@ -338,8 +347,20 @@
                             if (value == null) {
                                 omittedValues.set(valuePos);
                             } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph), true),
-                                                (value.kind() == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE, value.kind() == Kind.Object);
+                                // Constant.illegal is always the defaultForKind, so it is skipped
+                                Kind componentKind = element.getKind();
+                                Kind accessKind;
+                                if (value.kind().getStackKind() != componentKind.getStackKind()) {
+                                    assert value.kind() == Kind.Long || value.kind() == Kind.Double;
+                                    accessKind = value.kind();
+                                } else {
+                                    accessKind = componentKind;
+                                }
+
+                                int scale = getScalingFactor(componentKind);
+                                ConstantLocationNode location = ConstantLocationNode.create(INIT_LOCATION, accessKind, getArrayBaseOffset(componentKind) + i * scale, graph);
+                                BarrierType barrierType = (componentKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE;
+                                WriteNode write = new WriteNode(newObject, value, location, barrierType, componentKind == Kind.Object);
                                 graph.addAfterFixed(newObject, graph.add(write));
                             }
                             valuePos++;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Tue Oct 29 16:23:59 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.word.*;
@@ -41,6 +42,7 @@
 public class AESCryptSubstitutions {
 
     static final long kOffset;
+    static final LocationIdentity kLocationIdentity;
     static final Class<?> AESCryptClass;
 
     static {
@@ -50,6 +52,7 @@
             ClassLoader cl = Launcher.getLauncher().getClassLoader();
             AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl);
             kOffset = UnsafeAccess.unsafe.objectFieldOffset(AESCryptClass.getDeclaredField("K"));
+            kLocationIdentity = HotSpotResolvedObjectType.fromClass(AESCryptClass).findInstanceFieldWithOffset(kOffset);
         } catch (Exception ex) {
             throw new GraalInternalError(ex);
         }
@@ -66,7 +69,7 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
-        Object kObject = UnsafeLoadNode.load(rcvr, kOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
+        Object kObject = UnsafeLoadNode.load(rcvr, kOffset, Kind.Object, kLocationIdentity);
         Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -187,7 +187,7 @@
                     return;
                 }
                 for (int i = 0; i < length; i++) {
-                    tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i));
+                    tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i), false);
                 }
                 tool.delete();
                 if (Debug.isLogEnabled()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Tue Oct 29 16:23:59 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -42,14 +43,22 @@
 public class CipherBlockChainingSubstitutions {
 
     private static final long embeddedCipherOffset;
+    private static final LocationIdentity embeddedCipherLocationIdentity;
     private static final long rOffset;
+    private static final LocationIdentity rLocationIdentity;
     static {
         try {
             // Need to use launcher class path as com.sun.crypto.provider.AESCrypt
             // is normally not on the boot class path
             ClassLoader cl = Launcher.getLauncher().getClassLoader();
-            embeddedCipherOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl).getDeclaredField("embeddedCipher"));
-            rOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl).getDeclaredField("r"));
+
+            Class<?> feedbackCipherClass = Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl);
+            embeddedCipherOffset = UnsafeAccess.unsafe.objectFieldOffset(feedbackCipherClass.getDeclaredField("embeddedCipher"));
+            embeddedCipherLocationIdentity = HotSpotResolvedObjectType.fromClass(feedbackCipherClass).findInstanceFieldWithOffset(embeddedCipherOffset);
+
+            Class<?> cipherBlockChainingClass = Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl);
+            rOffset = UnsafeAccess.unsafe.objectFieldOffset(cipherBlockChainingClass.getDeclaredField("r"));
+            rLocationIdentity = HotSpotResolvedObjectType.fromClass(cipherBlockChainingClass).findInstanceFieldWithOffset(rOffset);
         } catch (Exception ex) {
             throw new GraalInternalError(ex);
         }
@@ -62,7 +71,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, embeddedCipherLocationIdentity);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true);
         } else {
@@ -72,7 +81,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, embeddedCipherLocationIdentity);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false);
         } else {
@@ -81,8 +90,8 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
-        Object rObject = UnsafeLoadNode.load(rcvr, rOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
+        Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, Kind.Object, AESCryptSubstitutions.kLocationIdentity);
+        Object rObject = UnsafeLoadNode.load(rcvr, rOffset, Kind.Object, rLocationIdentity);
         Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
         Word rAddr = (Word) Word.fromObject(rObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -77,10 +77,23 @@
                 long offset = indexValue.asConstant().asLong();
                 int entryIndex = state.getVirtualObject().entryIndexForOffset(offset);
                 if (entryIndex != -1) {
+                    Kind entryKind = state.getVirtualObject().entryKind(entryIndex);
                     ValueNode entry = state.getEntry(entryIndex);
-                    if (entry.kind() == value.kind() || state.getVirtualObject().entryKind(entryIndex) == accessKind()) {
-                        tool.setVirtualEntry(state, entryIndex, value());
+                    if (entry.kind() == value.kind() || entryKind == accessKind()) {
+                        tool.setVirtualEntry(state, entryIndex, value(), true);
                         tool.delete();
+                    } else {
+                        if ((accessKind() == Kind.Long || accessKind() == Kind.Double) && entryKind == Kind.Int) {
+                            int nextIndex = state.getVirtualObject().entryIndexForOffset(offset + 4);
+                            if (nextIndex != -1) {
+                                Kind nextKind = state.getVirtualObject().entryKind(nextIndex);
+                                if (nextKind == Kind.Int) {
+                                    tool.setVirtualEntry(state, entryIndex, value(), true);
+                                    tool.setVirtualEntry(state, nextIndex, ConstantNode.forConstant(Constant.forIllegal(), tool.getMetaAccessProvider(), graph()), true);
+                                    tool.delete();
+                                }
+                            }
+                        }
                     }
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -98,7 +98,7 @@
                 VirtualObjectNode virtual = state.getVirtualObject();
                 int entryIndex = virtual.entryIndexForOffset(constantLocation.getDisplacement());
                 if (entryIndex != -1 && virtual.entryKind(entryIndex) == constantLocation.getValueKind()) {
-                    tool.setVirtualEntry(state, entryIndex, value());
+                    tool.setVirtualEntry(state, entryIndex, value(), false);
                     tool.delete();
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -74,7 +74,7 @@
         if (state != null && state.getState() == EscapeState.Virtual) {
             int fieldIndex = ((VirtualInstanceNode) state.getVirtualObject()).fieldIndex(field());
             if (fieldIndex != -1) {
-                tool.setVirtualEntry(state, fieldIndex, value());
+                tool.setVirtualEntry(state, fieldIndex, value(), false);
                 tool.delete();
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -76,7 +76,7 @@
                 ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType();
                 if (componentType.isPrimitive() || ObjectStamp.isObjectAlwaysNull(value) || componentType.getSuperclass() == null ||
                                 (ObjectStamp.typeOrNull(value) != null && componentType.isAssignableFrom(ObjectStamp.typeOrNull(value)))) {
-                    tool.setVirtualEntry(arrayState, index, value());
+                    tool.setVirtualEntry(arrayState, index, value(), false);
                     tool.delete();
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Tue Oct 29 16:23:59 2013 +0100
@@ -84,8 +84,9 @@
      * @param state the state.
      * @param index the index to be set.
      * @param value the new value for the given index.
+     * @param unsafe if true, then mismatching value {@link Kind}s will be accepted.
      */
-    void setVirtualEntry(State state, int index, ValueNode value);
+    void setVirtualEntry(State state, int index, ValueNode value, boolean unsafe);
 
     // scalar replacement
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Tue Oct 29 16:23:59 2013 +0100
@@ -27,7 +27,7 @@
 public final class GenericStamp extends Stamp {
 
     public enum GenericStampType {
-        Dependency, Extension, Virtual, Condition, Void
+        Dependency, Extension, Condition, Void
     }
 
     private final GenericStampType type;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Tue Oct 29 16:23:59 2013 +0100
@@ -37,7 +37,6 @@
     private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true);
     private static final Stamp dependencyStamp = new GenericStamp(GenericStampType.Dependency);
     private static final Stamp extensionStamp = new GenericStamp(GenericStampType.Extension);
-    private static final Stamp virtualStamp = new GenericStamp(GenericStampType.Virtual);
     private static final Stamp conditionStamp = new GenericStamp(GenericStampType.Condition);
     private static final Stamp voidStamp = new GenericStamp(GenericStampType.Void);
     private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false);
@@ -94,10 +93,6 @@
         return extensionStamp;
     }
 
-    public static Stamp virtual() {
-        return virtualStamp;
-    }
-
     public static Stamp condition() {
         return conditionStamp;
     }
@@ -163,6 +158,8 @@
                 return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
             case Double:
                 return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
+            case Illegal:
+                return illegal(Kind.Illegal);
             default:
                 throw new GraalInternalError("unexpected kind: %s", kind);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -119,6 +119,14 @@
             used[index] = true;
             usedCount++;
         }
+        if (usedCount == 0) {
+            List<Node> inputSnapshot = inputs().snapshot();
+            graph().removeFixed(this);
+            for (Node input : inputSnapshot) {
+                tool.removeIfUnused(input);
+            }
+            return;
+        }
         boolean progress;
         do {
             progress = false;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -36,7 +36,7 @@
     private final int length;
 
     public VirtualArrayNode(ResolvedJavaType componentType, int length) {
-        super(true);
+        super(componentType.getArrayClass(), true);
         this.componentType = componentType;
         this.length = length;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -37,7 +37,7 @@
     }
 
     public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) {
-        super(hasIdentity);
+        super(type, hasIdentity);
         this.type = type;
         this.fields = fields;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Tue Oct 29 16:23:59 2013 +0100
@@ -32,8 +32,8 @@
 
     private boolean hasIdentity;
 
-    public VirtualObjectNode(boolean hasIdentity) {
-        super(StampFactory.virtual());
+    public VirtualObjectNode(ResolvedJavaType type, boolean hasIdentity) {
+        super(StampFactory.exactNonNull(type));
         this.hasIdentity = hasIdentity;
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Oct 29 16:23:59 2013 +0100
@@ -35,6 +35,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.CompilerThreadFactory.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
@@ -81,7 +82,12 @@
         this.skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess());
 
         // Create compilation queue.
-        compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), TruffleCompilerThread.FACTORY);
+        CompilerThreadFactory factory = new CompilerThreadFactory("TruffleCompilerThread", new DebugConfigAccess() {
+            public GraalDebugConfig getDebugConfig() {
+                return Debug.isEnabled() ? DebugEnvironment.initialize(TTY.out().out()) : null;
+            }
+        });
+        compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), factory);
 
         final GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault();
         config.setSkippedExceptionTypes(skippedExceptionTypes);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerThread.java	Mon Oct 28 11:06:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.truffle;
-
-import java.util.concurrent.*;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.printer.*;
-
-public final class TruffleCompilerThread extends Thread {
-
-    public static final ThreadFactory FACTORY = new ThreadFactory() {
-
-        @Override
-        public Thread newThread(Runnable r) {
-            return new TruffleCompilerThread(r);
-        }
-    };
-
-    private TruffleCompilerThread(Runnable r) {
-        super(r);
-        this.setName("TruffleCompilerThread-" + this.getId());
-        this.setPriority(MAX_PRIORITY);
-        this.setDaemon(true);
-    }
-
-    @Override
-    public void run() {
-        GraalDebugConfig debugConfig = null;
-        if (Debug.isEnabled()) {
-            debugConfig = DebugEnvironment.initialize(System.out);
-        }
-        try {
-            super.run();
-        } finally {
-            if (debugConfig != null) {
-                for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) {
-                    try {
-                        dumpHandler.close();
-                    } catch (Throwable t) {
-
-                    }
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Tue Oct 29 16:23:59 2013 +0100
@@ -132,13 +132,14 @@
     }
 
     /**
-     * Sets the phi node's input at the given index to the given value.
+     * Sets the phi node's input at the given index to the given value, adding new phi inputs as
+     * needed.
      * 
      * @param node The phi node whose input should be changed.
      * @param index The index of the phi input to be changed.
      * @param value The new value for the phi input.
      */
-    public void setPhiInput(final PhiNode node, final int index, final ValueNode value) {
+    public void initializePhiInput(final PhiNode node, final int index, final ValueNode value) {
         add(new Effect() {
 
             @Override
@@ -149,7 +150,7 @@
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert node.isAlive() && value.isAlive() && index >= 0;
-                node.setValueAt(index, value);
+                node.initializeValueAt(index, value);
             }
         });
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Oct 29 16:23:59 2013 +0100
@@ -208,20 +208,26 @@
         }
     }
 
-    private void ensureMaterialized(BlockT state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
+    /**
+     * @return true if materialization happened, false if not.
+     */
+    private boolean ensureMaterialized(BlockT state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
         assert obj != null;
         if (obj.getState() == EscapeState.Virtual) {
             metric.increment();
             state.materializeBefore(materializeBefore, obj.virtual, EscapeState.Materialized, effects);
+            assert !obj.isVirtual();
+            return true;
         } else {
             assert obj.getState() == EscapeState.Materialized;
+            return false;
         }
-        assert !obj.isVirtual();
     }
 
-    private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockT state, ObjectState obj, GraphEffectList effects, DebugMetric metric) {
-        ensureMaterialized(state, obj, materializeBefore, effects, metric);
+    private boolean replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockT state, ObjectState obj, GraphEffectList effects, DebugMetric metric) {
+        boolean materialized = ensureMaterialized(state, obj, materializeBefore, effects, metric);
         effects.replaceFirstInput(usage, value, obj.getMaterializedValue());
+        return materialized;
     }
 
     @Override
@@ -275,8 +281,7 @@
     protected class MergeProcessor extends EffectsClosure<BlockT>.MergeProcessor {
 
         private final HashMap<Object, PhiNode> materializedPhis = new HashMap<>();
-        private final IdentityHashMap<VirtualObjectNode, PhiNode[]> valuePhis = new IdentityHashMap<>();
-        private final IdentityHashMap<PhiNode, PhiNode[]> valueObjectMergePhis = new IdentityHashMap<>();
+        private final IdentityHashMap<ValueNode, PhiNode[]> valuePhis = new IdentityHashMap<>();
         private final IdentityHashMap<PhiNode, VirtualObjectNode> valueObjectVirtuals = new IdentityHashMap<>();
 
         public MergeProcessor(Block mergeBlock) {
@@ -292,21 +297,13 @@
             return result;
         }
 
-        private PhiNode[] getValuePhis(VirtualObjectNode virtual) {
-            PhiNode[] result = valuePhis.get(virtual);
-            if (result == null) {
-                result = new PhiNode[virtual.entryCount()];
-                valuePhis.put(virtual, result);
-            }
-            return result;
-        }
-
-        private PhiNode[] getValueObjectMergePhis(PhiNode phi, int entryCount) {
-            PhiNode[] result = valueObjectMergePhis.get(phi);
+        private PhiNode[] getValuePhis(ValueNode key, int entryCount) {
+            PhiNode[] result = valuePhis.get(key);
             if (result == null) {
                 result = new PhiNode[entryCount];
-                valueObjectMergePhis.put(phi, result);
+                valuePhis.put(key, result);
             }
+            assert result.length == entryCount;
             return result;
         }
 
@@ -319,194 +316,299 @@
             return result;
         }
 
+        /**
+         * Merge all predecessor block states into one block state. This is an iterative process,
+         * because merging states can lead to materializations which make previous parts of the
+         * merging operation invalid. The merging process is executed until a stable state has been
+         * reached. This method needs to be careful to place the effects of the merging operation
+         * into the correct blocks.
+         * 
+         * @param states the predecessor block states of the merge
+         */
         @Override
         protected void merge(List<BlockT> states) {
             super.merge(states);
 
-            /*
-             * Iterative processing: Merging the materialized/virtual state of virtual objects can
-             * lead to new materializations, which can lead to new materializations because of phis,
-             * and so on.
-             */
-
+            // calculate the set of virtual objects that exist in all predecessors
             HashSet<VirtualObjectNode> virtualObjTemp = new HashSet<>(states.get(0).getVirtualObjects());
             for (int i = 1; i < states.size(); i++) {
                 virtualObjTemp.retainAll(states.get(i).getVirtualObjects());
             }
 
+            ObjectState[] objStates = new ObjectState[states.size()];
             boolean materialized;
             do {
                 mergeEffects.clear();
                 afterMergeEffects.clear();
                 materialized = false;
                 for (VirtualObjectNode object : virtualObjTemp) {
-                    ObjectState[] objStates = new ObjectState[states.size()];
-                    for (int i = 0; i < states.size(); i++) {
-                        objStates[i] = states.get(i).getObjectStateOptional(object);
-                        assert objStates[i] != null;
+                    for (int i = 0; i < objStates.length; i++) {
+                        objStates[i] = states.get(i).getObjectState(object);
                     }
+
+                    // determine if all inputs are virtual or the same materialized value
                     int virtual = 0;
                     ObjectState startObj = objStates[0];
                     boolean locksMatch = true;
-                    ValueNode singleValue = startObj.isVirtual() ? null : startObj.getMaterializedValue();
+                    ValueNode uniqueMaterializedValue = startObj.isVirtual() ? null : startObj.getMaterializedValue();
                     for (ObjectState obj : objStates) {
                         if (obj.isVirtual()) {
                             virtual++;
-                            singleValue = null;
-                        } else {
-                            if (obj.getMaterializedValue() != singleValue) {
-                                singleValue = null;
-                            }
+                            uniqueMaterializedValue = null;
+                            locksMatch &= obj.locksEqual(startObj);
+                        } else if (obj.getMaterializedValue() != uniqueMaterializedValue) {
+                            uniqueMaterializedValue = null;
                         }
-                        locksMatch &= obj.locksEqual(startObj);
                     }
 
-                    if (virtual < states.size() || !locksMatch) {
-                        if (singleValue == null) {
+                    if (virtual == objStates.length && locksMatch) {
+                        materialized |= mergeObjectStates(object, objStates, states);
+                    } else {
+                        if (uniqueMaterializedValue != null) {
+                            newState.addObject(object, new ObjectState(object, uniqueMaterializedValue, EscapeState.Materialized, null));
+                        } else {
                             PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object);
                             mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi");
-                            for (int i = 0; i < states.size(); i++) {
-                                BlockT state = states.get(i);
+                            for (int i = 0; i < objStates.length; i++) {
                                 ObjectState obj = objStates[i];
-                                materialized |= obj.isVirtual();
                                 Block predecessor = mergeBlock.getPredecessors().get(i);
-                                ensureMaterialized(state, obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                                materialized |= ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
                                 afterMergeEffects.addPhiInput(materializedValuePhi, obj.getMaterializedValue());
                             }
                             newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Materialized, null));
-                        } else {
-                            newState.addObject(object, new ObjectState(object, singleValue, EscapeState.Materialized, null));
                         }
-                    } else {
-                        assert virtual == states.size();
-                        ValueNode[] values = startObj.getEntries().clone();
-                        PhiNode[] phis = getValuePhis(object);
-                        for (int index = 0; index < values.length; index++) {
-                            for (int i = 1; i < states.size(); i++) {
-                                ValueNode[] fields = objStates[i].getEntries();
-                                if (phis[index] == null && values[index] != fields[index]) {
-                                    Kind kind = values[index].kind();
-                                    if (kind == Kind.Illegal) {
-                                        // Can happen if one of the values is virtual and is only
-                                        // materialized in the following loop.
-                                        kind = Kind.Object;
-                                    }
-                                    phis[index] = new PhiNode(kind, merge);
-                                }
-                            }
-                        }
-                        outer: for (int index = 0; index < values.length; index++) {
-                            if (phis[index] != null) {
-                                mergeEffects.addFloatingNode(phis[index], "virtualMergePhi");
-                                for (int i = 0; i < states.size(); i++) {
-                                    if (!objStates[i].isVirtual()) {
-                                        break outer;
-                                    }
-                                    ValueNode[] fields = objStates[i].getEntries();
-                                    if (fields[index] instanceof VirtualObjectNode) {
-                                        ObjectState obj = states.get(i).getObjectState((VirtualObjectNode) fields[index]);
-                                        materialized |= obj.isVirtual();
-                                        Block predecessor = mergeBlock.getPredecessors().get(i);
-                                        ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
-                                        fields[index] = obj.getMaterializedValue();
-                                    }
-                                    afterMergeEffects.addPhiInput(phis[index], fields[index]);
-                                }
-                                values[index] = phis[index];
-                            }
-                        }
-                        newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, startObj.getLocks()));
                     }
                 }
 
                 for (PhiNode phi : merge.phis()) {
                     if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
-                        materialized |= processPhi(phi, states);
+                        materialized |= processPhi(phi, states, virtualObjTemp);
                     }
                 }
             } while (materialized);
         }
 
-        private boolean processPhi(PhiNode phi, List<BlockT> states) {
-            aliases.set(phi, null);
-            assert states.size() == phi.valueCount();
-            int virtualInputs = 0;
-            boolean materialized = false;
-            VirtualObjectNode sameObject = null;
-            ResolvedJavaType sameType = null;
-            int sameEntryCount = -1;
-            boolean hasIdentity = false;
-            for (int i = 0; i < phi.valueCount(); i++) {
-                ValueNode value = phi.valueAt(i);
-                ObjectState obj = getObjectState(states.get(i), value);
-                if (obj != null) {
-                    if (obj.isVirtual()) {
-                        virtualInputs++;
-                        if (i == 0) {
-                            sameObject = obj.virtual;
-                            sameType = obj.virtual.type();
-                            sameEntryCount = obj.virtual.entryCount();
-                        } else {
-                            if (sameObject != obj.virtual) {
-                                sameObject = null;
+        /**
+         * Try to merge multiple virtual object states into a single object state. If the incoming
+         * object states are compatible, then this method will create PhiNodes for the object's
+         * entries where needed. If they are incompatible, then all incoming virtual objects will be
+         * materialized, and a PhiNode for the materialized values will be created. Object states
+         * can be incompatible if they contain {@code long} or {@code double} values occupying two
+         * {@code int} slots in such a way that that their values cannot be merged using PhiNodes.
+         * 
+         * @param object the virtual object that should be associated with the merged object state
+         * @param objStates the incoming object states (all of which need to be virtual)
+         * @param blockStates the predecessor block states of the merge
+         * @return true if materialization happened during the merge, false otherwise
+         */
+        private boolean mergeObjectStates(VirtualObjectNode object, ObjectState[] objStates, List<BlockT> blockStates) {
+            boolean compatible = true;
+            ValueNode[] values = objStates[0].getEntries().clone();
+
+            // determine all entries that have a two-slot value
+            Kind[] twoSlotKinds = null;
+            outer: for (int i = 0; i < objStates.length; i++) {
+                ValueNode[] entries = objStates[i].getEntries();
+                int valueIndex = 0;
+                while (valueIndex < values.length) {
+                    Kind otherKind = entries[valueIndex].kind();
+                    Kind entryKind = object.entryKind(valueIndex);
+                    if (entryKind == Kind.Int && (otherKind == Kind.Long || otherKind == Kind.Double)) {
+                        if (twoSlotKinds == null) {
+                            twoSlotKinds = new Kind[values.length];
+                        }
+                        if (twoSlotKinds[valueIndex] != null && twoSlotKinds[valueIndex] != otherKind) {
+                            compatible = false;
+                            break outer;
+                        }
+                        twoSlotKinds[valueIndex] = otherKind;
+                        // skip the next entry
+                        valueIndex++;
+                    } else {
+                        assert entryKind.getStackKind() == otherKind.getStackKind() : entryKind + " vs " + otherKind;
+                    }
+                    valueIndex++;
+                }
+            }
+            if (compatible && twoSlotKinds != null) {
+                // if there are two-slot values then make sure the incoming states can be merged
+                outer: for (int valueIndex = 0; valueIndex < values.length; valueIndex++) {
+                    if (twoSlotKinds[valueIndex] != null) {
+                        assert valueIndex < object.entryCount() - 1 && object.entryKind(valueIndex) == Kind.Int && object.entryKind(valueIndex + 1) == Kind.Int;
+                        for (int i = 0; i < objStates.length; i++) {
+                            ValueNode value = objStates[i].getEntry(valueIndex);
+                            Kind valueKind = value.kind();
+                            if (valueKind != twoSlotKinds[valueIndex]) {
+                                ValueNode nextValue = objStates[i].getEntry(valueIndex + 1);
+                                if (value.isConstant() && value.asConstant().equals(Constant.INT_0) && nextValue.isConstant() && nextValue.asConstant().equals(Constant.INT_0)) {
+                                    // rewrite to a zero constant of the larger kind
+                                    objStates[i].setEntry(valueIndex, ConstantNode.defaultForKind(twoSlotKinds[valueIndex], merge.graph()));
+                                    objStates[i].setEntry(valueIndex + 1, ConstantNode.forConstant(Constant.forIllegal(), tool.getMetaAccessProvider(), merge.graph()));
+                                } else {
+                                    compatible = false;
+                                    break outer;
+                                }
                             }
-                            if (sameType != obj.virtual.type()) {
-                                sameType = null;
-                            }
-                            if (sameEntryCount != obj.virtual.entryCount()) {
-                                sameEntryCount = -1;
-                            }
-                            hasIdentity |= obj.virtual.hasIdentity();
                         }
-                    } else {
-                        afterMergeEffects.setPhiInput(phi, i, obj.getMaterializedValue());
                     }
                 }
             }
-            boolean materialize = false;
-            if (virtualInputs == 0) {
-                // nothing to do...
-            } else if (virtualInputs == phi.valueCount()) {
-                if (sameObject != null) {
-                    addAndMarkAlias(sameObject, phi);
-                } else if (sameType != null && sameEntryCount != -1) {
-                    if (!hasIdentity) {
-                        VirtualObjectNode virtual = getValueObjectVirtual(phi, getObjectState(states.get(0), phi.valueAt(0)).virtual);
+
+            if (compatible) {
+                // virtual objects are compatible: create phis for all entries that need them
+                PhiNode[] phis = getValuePhis(object, object.entryCount());
+                int valueIndex = 0;
+                while (valueIndex < values.length) {
+                    for (int i = 1; i < objStates.length; i++) {
+                        ValueNode[] fields = objStates[i].getEntries();
+                        if (phis[valueIndex] == null && values[valueIndex] != fields[valueIndex]) {
+                            phis[valueIndex] = new PhiNode(values[valueIndex].kind(), merge);
+                        }
+                    }
+                    if (twoSlotKinds != null && twoSlotKinds[valueIndex] != null) {
+                        // skip an entry after a long/double value that occupies two int slots
+                        valueIndex++;
+                        phis[valueIndex] = null;
+                        values[valueIndex] = ConstantNode.forConstant(Constant.forIllegal(), tool.getMetaAccessProvider(), merge.graph());
+                    }
+                    valueIndex++;
+                }
+
+                boolean materialized = false;
+                for (int i = 0; i < values.length; i++) {
+                    PhiNode phi = phis[i];
+                    if (phi != null) {
+                        mergeEffects.addFloatingNode(phi, "virtualMergePhi");
+                        if (object.entryKind(i) == Kind.Object) {
+                            materialized |= mergeObjectEntry(objStates, blockStates, phi, i);
+                        } else {
+                            mergePrimitiveEntry(objStates, phi, i);
+                        }
+                        values[i] = phi;
+                    }
+                }
+                newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, objStates[0].getLocks()));
+                return materialized;
+            } else {
+                // not compatible: materialize in all predecessors
+                PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object);
+                for (int i = 0; i < blockStates.size(); i++) {
+                    ObjectState obj = objStates[i];
+                    Block predecessor = mergeBlock.getPredecessors().get(i);
+                    ensureMaterialized(blockStates.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                    afterMergeEffects.addPhiInput(materializedValuePhi, obj.getMaterializedValue());
+                }
+                newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Materialized, null));
+                return true;
+            }
+        }
 
-                        PhiNode[] phis = getValueObjectMergePhis(phi, virtual.entryCount());
-                        for (int i = 0; i < virtual.entryCount(); i++) {
-                            assert virtual.entryKind(i) != Kind.Object;
-                            if (phis[i] == null) {
-                                phis[i] = new PhiNode(virtual.entryKind(i), merge);
-                            }
-                            mergeEffects.addFloatingNode(phis[i], "valueObjectPhi");
-                            for (int i2 = 0; i2 < phi.valueCount(); i2++) {
-                                afterMergeEffects.addPhiInput(phis[i], getObjectState(states.get(i2), phi.valueAt(i2)).getEntry(i));
-                            }
+        /**
+         * Fill the inputs of the PhiNode corresponding to one {@link Kind#Object} entry in the
+         * virtual object.
+         * 
+         * @return true if materialization happened during the merge, false otherwise
+         */
+        private boolean mergeObjectEntry(ObjectState[] objStates, List<BlockT> blockStates, PhiNode phi, int entryIndex) {
+            boolean materialized = false;
+            for (int i = 0; i < objStates.length; i++) {
+                if (!objStates[i].isVirtual()) {
+                    break;
+                }
+                ValueNode[] entries = objStates[i].getEntries();
+                if (entries[entryIndex] instanceof VirtualObjectNode) {
+                    ObjectState obj = blockStates.get(i).getObjectState((VirtualObjectNode) entries[entryIndex]);
+                    Block predecessor = mergeBlock.getPredecessors().get(i);
+                    materialized |= ensureMaterialized(blockStates.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                    entries[entryIndex] = obj.getMaterializedValue();
+                }
+                afterMergeEffects.addPhiInput(phi, entries[entryIndex]);
+            }
+            return materialized;
+        }
+
+        /**
+         * Fill the inputs of the PhiNode corresponding to one primitive entry in the virtual
+         * object.
+         */
+        private void mergePrimitiveEntry(ObjectState[] objStates, PhiNode phi, int entryIndex) {
+            for (ObjectState state : objStates) {
+                if (!state.isVirtual()) {
+                    break;
+                }
+                afterMergeEffects.addPhiInput(phi, state.getEntries()[entryIndex]);
+            }
+        }
+
+        /**
+         * Examine a PhiNode and try to replace it with merging of virtual objects if all its inputs
+         * refer to virtual object states. In order for the merging to happen, all incoming object
+         * states need to be compatible and without object identity (meaning that their object
+         * identity if not used later on).
+         * 
+         * @param phi the PhiNode that should be processed
+         * @param states the predecessor block states of the merge
+         * @param mergedVirtualObjects the set of virtual objects that exist in all incoming states,
+         *            and therefore also exist in the merged state
+         * @return true if materialization happened during the merge, false otherwise
+         */
+        private boolean processPhi(PhiNode phi, List<BlockT> states, Set<VirtualObjectNode> mergedVirtualObjects) {
+            aliases.set(phi, null);
+            assert states.size() == phi.valueCount();
+
+            // determine how many inputs are virtual and if they're all the same virtual object
+            int virtualInputs = 0;
+            ObjectState[] objStates = new ObjectState[states.size()];
+            boolean uniqueVirtualObject = true;
+            for (int i = 0; i < objStates.length; i++) {
+                ObjectState obj = objStates[i] = getObjectState(states.get(i), phi.valueAt(i));
+                if (obj != null) {
+                    if (obj.isVirtual()) {
+                        if (objStates[0] == null || objStates[0].virtual != obj.virtual) {
+                            uniqueVirtualObject = false;
                         }
+                        virtualInputs++;
+                    }
+                }
+            }
+            if (virtualInputs == objStates.length) {
+                if (uniqueVirtualObject) {
+                    // all inputs refer to the same object: just make the phi node an alias
+                    addAndMarkAlias(objStates[0].virtual, phi);
+                    return false;
+                } else {
+                    // all inputs are virtual: check if they're compatible and without identity
+                    boolean compatible = true;
+                    ObjectState firstObj = objStates[0];
+                    for (int i = 0; i < objStates.length; i++) {
+                        ObjectState obj = objStates[i];
+                        boolean hasIdentity = obj.virtual.hasIdentity() && mergedVirtualObjects.contains(obj.virtual);
+                        if (hasIdentity || firstObj.virtual.type() != obj.virtual.type() || firstObj.virtual.entryCount() != obj.virtual.entryCount() || !firstObj.locksEqual(obj)) {
+                            compatible = false;
+                            break;
+                        }
+                    }
+
+                    if (compatible) {
+                        VirtualObjectNode virtual = getValueObjectVirtual(phi, getObjectState(states.get(0), phi.valueAt(0)).virtual);
                         mergeEffects.addFloatingNode(virtual, "valueObjectNode");
-                        newState.addObject(virtual, new ObjectState(virtual, Arrays.copyOf(phis, phis.length, ValueNode[].class), EscapeState.Virtual, null));
+
+                        boolean materialized = mergeObjectStates(virtual, objStates, states);
                         addAndMarkAlias(virtual, virtual);
                         addAndMarkAlias(virtual, phi);
-                    } else {
-                        materialize = true;
+                        return materialized;
                     }
-                } else {
-                    materialize = true;
                 }
-            } else {
-                materialize = true;
             }
 
-            if (materialize) {
-                for (int i = 0; i < phi.valueCount(); i++) {
-                    ValueNode value = phi.valueAt(i);
-                    ObjectState obj = getObjectState(states.get(i), value);
-                    if (obj != null) {
-                        materialized |= obj.isVirtual();
-                        Block predecessor = mergeBlock.getPredecessors().get(i);
-                        replaceWithMaterialized(value, phi, predecessor.getEndNode(), states.get(i), obj, blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_PHI);
-                    }
+            // otherwise: materialize all phi inputs
+            boolean materialized = false;
+            for (int i = 0; i < objStates.length; i++) {
+                ObjectState obj = objStates[i];
+                if (obj != null) {
+                    Block predecessor = mergeBlock.getPredecessors().get(i);
+                    materialized |= ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_PHI);
+                    afterMergeEffects.initializePhiInput(phi, i, obj.getMaterializedValue());
                 }
             }
             return materialized;
@@ -531,10 +633,8 @@
     void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node) {
         if (node.isAlive()) {
             aliases.set(node, virtual);
-            if (node.recordsUsages()) {
-                for (Node usage : node.usages()) {
-                    markVirtualUsages(usage);
-                }
+            for (Node usage : node.usages()) {
+                markVirtualUsages(usage);
             }
         }
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Oct 28 11:06:51 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Tue Oct 29 16:23:59 2013 +0100
@@ -80,22 +80,26 @@
     }
 
     @Override
-    public void setVirtualEntry(State objectState, int index, ValueNode value) {
+    public void setVirtualEntry(State objectState, int index, ValueNode value, boolean unsafe) {
         ObjectState obj = (ObjectState) objectState;
         assert obj != null && obj.isVirtual() : "not virtual: " + obj;
-        ObjectState valueState = closure.getObjectState(state, value);
         ValueNode newValue;
-        if (valueState == null) {
-            newValue = getReplacedValue(value);
-            assert obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind() || (isObjectEntry(obj.getEntry(index)) && isObjectEntry(newValue));
+        if (value == null) {
+            newValue = null;
         } else {
-            if (valueState.getState() != EscapeState.Virtual) {
-                newValue = valueState.getMaterializedValue();
-                assert newValue.kind() == Kind.Object;
+            ObjectState valueState = closure.getObjectState(state, value);
+            if (valueState == null) {
+                newValue = getReplacedValue(value);
+                assert unsafe || obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind() || (isObjectEntry(obj.getEntry(index)) && isObjectEntry(newValue));
             } else {
-                newValue = valueState.getVirtualObject();
+                if (valueState.getState() != EscapeState.Virtual) {
+                    newValue = valueState.getMaterializedValue();
+                    assert newValue.kind() == Kind.Object;
+                } else {
+                    newValue = valueState.getVirtualObject();
+                }
+                assert obj.getEntry(index) == null || isObjectEntry(obj.getEntry(index));
             }
-            assert obj.getEntry(index) == null || isObjectEntry(obj.getEntry(index));
         }
         obj.setEntry(index, newValue);
     }
--- a/mxtool/mx.py	Mon Oct 28 11:06:51 2013 +0100
+++ b/mxtool/mx.py	Tue Oct 29 16:23:59 2013 +0100
@@ -34,6 +34,7 @@
 
 import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch
 import textwrap
+import socket
 import xml.parsers.expat
 import shutil, re, xml.dom.minidom
 from collections import Callable
@@ -2534,7 +2535,7 @@
 
     suppliedParser = parser is not None
 
-    parser = parser if suppliedParser else ArgumentParser(prog='mx build')
+    parser = parser if suppliedParser else ArgumentParser(prog='mx clean')
     parser.add_argument('--no-native', action='store_false', dest='native', help='do not clean native projects')
     parser.add_argument('--no-java', action='store_false', dest='java', help='do not clean Java projects')
 
@@ -2600,8 +2601,56 @@
     print 'mx {0} {1}\n\n{2}\n'.format(name, usage, doc)
 
 def projectgraph(args, suite=None):
-    """create dot graph for project structure ("mx projectgraph | dot -Tpdf -oprojects.pdf")"""
-
+    """create graph for project structure ("mx projectgraph | dot -Tpdf -oprojects.pdf" or "mx projectgraph --igv")"""
+
+    parser = ArgumentParser(prog='mx projectgraph')
+    parser.add_argument('--igv', action='store_true', help='output to IGV listening on 127.0.0.1:4444')
+    parser.add_argument('--igv-format', action='store_true', help='output graph in IGV format')
+
+    args = parser.parse_args(args)
+
+    if args.igv or args.igv_format:
+        ids = {}
+        nextToIndex = {}
+        igv = XMLDoc()
+        igv.open('graphDocument')
+        igv.open('group')
+        igv.open('properties')
+        igv.element('p', {'name' : 'name'}, 'GraalProjectDependencies')
+        igv.close('properties')
+        igv.open('graph', {'name' : 'dependencies'})
+        igv.open('nodes')
+        for p in sorted_deps(includeLibs=True):
+            ident = len(ids)
+            ids[p.name] = str(ident)
+            igv.open('node', {'id' : str(ident)})
+            igv.open('properties')
+            igv.element('p', {'name' : 'name'}, p.name)
+            igv.close('properties')
+            igv.close('node')
+        igv.close('nodes')
+        igv.open('edges')
+        for p in projects():
+            fromIndex = 0
+            for dep in p.canonical_deps():
+                toIndex = nextToIndex.get(dep, 0)
+                nextToIndex[dep] = toIndex + 1
+                igv.element('edge', {'from' : ids[p.name], 'fromIndex' : str(fromIndex), 'to' : ids[dep], 'toIndex' : str(toIndex), 'label' : 'dependsOn'})
+                fromIndex = fromIndex + 1
+        igv.close('edges')
+        igv.close('graph')
+        igv.close('group')
+        igv.close('graphDocument')
+        
+        if args.igv:
+            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            s.connect(('127.0.0.1', 4444))
+            s.send(igv.xml())
+        else:
+            print igv.xml(indent='  ', newl='\n');
+        return
+        
+            
     print 'digraph projects {'
     print 'rankdir=BT;'
     print 'node [shape=rect];'
--- a/src/share/vm/runtime/deoptimization.cpp	Mon Oct 28 11:06:51 2013 +0100
+++ b/src/share/vm/runtime/deoptimization.cpp	Tue Oct 29 16:23:59 2013 +0100
@@ -914,7 +914,8 @@
   fields->sort(compare);
   for (int i = 0; i < fields->length(); i++) {
     intptr_t val;
-    StackValue* value = StackValue::create_stack_value(fr, reg_map, sv->field_at(svIndex));
+    ScopeValue* scope_field = sv->field_at(svIndex);
+    StackValue* value = StackValue::create_stack_value(fr, reg_map, scope_field);
     int offset = fields->at(i)._offset;
     BasicType type = fields->at(i)._type;
     switch (type) {
@@ -923,6 +924,37 @@
         obj->obj_field_put(offset, value->get_obj()());
         break;
 
+      // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
+      case T_INT: case T_FLOAT: { // 4 bytes.
+        assert(value->type() == T_INT, "Agreement.");
+        bool big_value = false;
+        if (i+1 < fields->length() && fields->at(i+1)._type == T_INT) {
+          if (scope_field->is_location()) {
+            Location::Type type = ((LocationValue*) scope_field)->location().type();
+            if (type == Location::dbl || type == Location::lng) {
+              big_value = true;
+            }
+          }
+          if (scope_field->is_constant_int()) {
+            ScopeValue* next_scope_field = sv->field_at(svIndex + 1);
+            if (next_scope_field->is_constant_long() || next_scope_field->is_constant_double()) {
+              big_value = true;
+            }
+          }
+        }
+
+        if (big_value) {
+          i++;
+          assert(i < fields->length(), "second T_INT field needed");
+          assert(fields->at(i)._type == T_INT, "T_INT field needed");
+        } else {
+          val = value->get_int();
+          obj->int_field_put(offset, (jint)*((jint*)&val));
+          break;
+        }
+      }
+        /* no break */
+
       case T_LONG: case T_DOUBLE: {
         assert(value->type() == T_INT, "Agreement.");
         StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++svIndex));
@@ -939,12 +971,6 @@
         obj->long_field_put(offset, res);
         break;
       }
-      // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
-      case T_INT: case T_FLOAT: // 4 bytes.
-        assert(value->type() == T_INT, "Agreement.");
-        val = value->get_int();
-        obj->int_field_put(offset, (jint)*((jint*)&val));
-        break;
 
       case T_SHORT: case T_CHAR: // 2 bytes
         assert(value->type() == T_INT, "Agreement.");