changeset 7780:550c952f5d3f

Merge
author Christian Humer <christian.humer@gmail.com>
date Tue, 12 Feb 2013 16:06:20 +0100
parents 18eea22675ad 1ca1425a067f
children 3a6a718af535 39d4a79568b6
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BooleanNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java
diffstat 66 files changed, 788 insertions(+), 331 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Tue Feb 12 16:06:20 2013 +0100
@@ -37,7 +37,7 @@
         CodeGenTest test = new CodeGenTest() {
 
             @Override
-            public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig) {
+            public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) {
                 AMD64Assembler asm = new AMD64Assembler(target, registerConfig);
                 Register ret = registerConfig.getReturnRegister(Kind.Int);
                 asm.movl(ret, 8472);
@@ -53,7 +53,7 @@
         CodeGenTest test = new CodeGenTest() {
 
             @Override
-            public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig) {
+            public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) {
                 AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig);
                 Register ret = registerConfig.getReturnRegister(Kind.Double);
                 compResult.recordDataReference(asm.codeBuffer.position(), Constant.forDouble(84.72), 8, false);
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Tue Feb 12 16:06:20 2013 +0100
@@ -201,7 +201,7 @@
         emitByte(op2 | encode(dst) << 3 | encode(src));
     }
 
-    private void emitOperandHelper(Register reg, Address addr) {
+    protected void emitOperandHelper(Register reg, Address addr) {
         Register base = isLegal(addr.getBase()) ? asRegister(addr.getBase()) : Register.None;
         Register index = isLegal(addr.getIndex()) ? asRegister(addr.getIndex()) : Register.None;
 
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Tue Feb 12 16:06:20 2013 +0100
@@ -38,7 +38,7 @@
 
     public interface CodeGenTest {
 
-        Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig);
+        Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc);
     }
 
     public AssemblerTest() {
@@ -51,17 +51,28 @@
 
         CompilationResult compResult = new CompilationResult();
 
-        Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig);
+        Signature sig = method.getSignature();
+        JavaType retType = sig.getReturnType(null);
+        JavaType[] argTypes = new JavaType[sig.getParameterCount(false)];
+        for (int i = 0; i < argTypes.length; i++) {
+            argTypes[i] = sig.getParameterType(i, null);
+        }
+        CallingConvention cc = registerConfig.getCallingConvention(CallingConvention.Type.JavaCallee, retType, argTypes, codeCache.getTarget(), false);
+
+        Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
         compResult.setTargetCode(codeBuffer.close(true), codeBuffer.position());
 
         return codeCache.addMethod(method, compResult, null);
     }
 
-    protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) {
+    protected Object runTest(String methodName, CodeGenTest test, Object... args) {
         Method method = getMethod(methodName);
         InstalledCode code = assembleMethod(method, test);
+        return code.executeVarargs(args);
+    }
 
-        Object actual = code.executeVarargs(args);
+    protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) {
+        Object actual = runTest(methodName, test, args);
         Assert.assertEquals("unexpected return value: " + actual, actual, expected);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Feb 12 16:06:20 2013 +0100
@@ -186,7 +186,9 @@
         ReturnNode returnNode = testEscapeAnalysis("testInstanceOfSnippet", null, false);
         ValueNode result = returnNode.result();
         Assert.assertTrue(result instanceof ConditionalNode);
-        Assert.assertEquals(Constant.TRUE, ((ConditionalNode) result).condition().asConstant());
+        ConditionalNode conditional = (ConditionalNode) result;
+        Assert.assertTrue(conditional.condition() instanceof LogicConstantNode);
+        Assert.assertEquals(true, ((LogicConstantNode) conditional.condition()).getValue());
     }
 
     public boolean testInstanceOfSnippet() {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Feb 12 16:06:20 2013 +0100
@@ -585,10 +585,10 @@
     }
 
     @Override
-    public void emitGuardCheck(BooleanNode comp, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
+    public void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
         if (comp instanceof IsNullNode && negated) {
             emitNullCheckGuard(((IsNullNode) comp).object());
-        } else if (comp instanceof ConstantNode && (comp.asConstant().asBoolean() != negated)) {
+        } else if (comp instanceof LogicConstantNode && ((LogicConstantNode) comp).getValue() != negated) {
             // True constant, nothing to emit.
             // False constants are handled within emitBranch.
         } else {
@@ -605,13 +605,13 @@
 
     protected abstract void emitNullCheckGuard(ValueNode object);
 
-    public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
+    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         if (node instanceof IsNullNode) {
             emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, info);
         } else if (node instanceof CompareNode) {
             emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, info);
-        } else if (node instanceof ConstantNode) {
-            emitConstantBranch(((ConstantNode) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info);
+        } else if (node instanceof LogicConstantNode) {
+            emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor, info);
         } else if (node instanceof IntegerTestNode) {
             emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, info);
         } else {
@@ -666,16 +666,15 @@
         setResult(conditional, emitConditional(conditional.condition(), tVal, fVal));
     }
 
-    public Variable emitConditional(BooleanNode node, Value trueValue, Value falseValue) {
+    public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) {
         if (node instanceof IsNullNode) {
             IsNullNode isNullNode = (IsNullNode) node;
             return emitConditionalMove(operand(isNullNode.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue);
         } else if (node instanceof CompareNode) {
             CompareNode compare = (CompareNode) node;
             return emitConditionalMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
-        } else if (node instanceof ConstantNode) {
-            ConstantNode constantNode = (ConstantNode) node;
-            return emitMove(constantNode.asConstant().asBoolean() ? trueValue : falseValue);
+        } else if (node instanceof LogicConstantNode) {
+            return emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue);
         } else if (node instanceof IntegerTestNode) {
             IntegerTestNode test = (IntegerTestNode) node;
             return emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Feb 12 16:06:20 2013 +0100
@@ -74,7 +74,7 @@
 
     /**
      * Denotes that a parameter of an {@linkplain NodeIntrinsic intrinsic} method must be a compile
-     * time constant at all call sites to the intrinic method.
+     * time constant at all call sites to the intrinsic method.
      */
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.PARAMETER)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Feb 12 16:06:20 2013 +0100
@@ -287,6 +287,7 @@
     public int layoutHelperLog2ElementSizeMask;
     public int layoutHelperElementTypeShift;
     public int layoutHelperElementTypeMask;
+    public int layoutHelperElementTypePrimitiveInPlace;
     public int layoutHelperHeaderSizeShift;
     public int layoutHelperHeaderSizeMask;
     public int layoutHelperOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Feb 12 16:06:20 2013 +0100
@@ -350,6 +350,9 @@
         if (GraalOptions.IntrinsifyArrayCopy) {
             installer.installSnippets(ArrayCopySnippets.class);
         }
+        if (GraalOptions.IntrinsifyObjectClone) {
+            installer.installSnippets(ObjectCloneSnippets.class);
+        }
 
         installer.installSnippets(CheckCastSnippets.class);
         installer.installSnippets(InstanceOfSnippets.class);
@@ -705,7 +708,7 @@
             assert loadHub.kind() == wordKind;
             LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph);
             ValueNode object = loadHub.object();
-            assert !object.isConstant();
+            assert !object.isConstant() || object.asConstant().isNull();
             ValueNode guard = tool.createNullCheckGuard(object);
             ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind())));
             hub.dependencies().add(guard);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Tue Feb 12 16:06:20 2013 +0100
@@ -256,7 +256,7 @@
             long end = (dstAddr + header + ((long) destPos + length - 1) * scale) >>> cardShift;
             long count = end - start + 1;
             while (count-- > 0) {
-                DirectStoreNode.store((start + cardStart) + count, false);
+                DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean);
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Tue Feb 12 16:06:20 2013 +0100
@@ -442,6 +442,12 @@
         return config().layoutHelperElementTypeMask;
     }
 
+    @Fold
+    public static int layoutHelperElementTypePrimitiveInPlace() {
+        System.out.println(String.format("%x", config().layoutHelperElementTypePrimitiveInPlace));
+        return config().layoutHelperElementTypePrimitiveInPlace;
+    }
+
     static {
         assert arrayIndexScale(Kind.Byte) == 1;
         assert arrayIndexScale(Kind.Boolean) == 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.snippets;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.snippets.nodes.*;
+
+public class ObjectCloneNode extends MacroNode implements VirtualizableAllocation, ArrayLengthProvider {
+
+    public ObjectCloneNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(getObject().stamp());
+    }
+
+    private ValueNode getObject() {
+        return arguments.get(0);
+    }
+
+    private Method selectSnippetMethod(LoweringTool tool) {
+        ResolvedJavaType type = getObject().objectStamp().type();
+        if (type.isArray()) {
+            return ObjectCloneSnippets.arrayCloneMethod;
+        } else if (type.isAssignableFrom(tool.getRuntime().lookupJavaType(Object[].class))) {
+            // arrays are assignable to Object, Cloneable and Serializable
+            return ObjectCloneSnippets.genericCloneMethod;
+        } else {
+            return ObjectCloneSnippets.instanceCloneMethod;
+        }
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        if (!GraalOptions.IntrinsifyObjectClone) {
+            super.lower(tool);
+            return;
+        }
+        ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(selectSnippetMethod(tool));
+        if (Debug.isLogEnabled()) {
+            Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType());
+        }
+
+        StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class);
+        assert snippetGraph != null : "ObjectCloneSnippets should be installed";
+        InvokeNode invoke = replaceWithInvoke();
+        InliningUtil.inline(invoke, snippetGraph, false);
+    }
+
+    private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) {
+        return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type);
+    }
+
+    private static ResolvedJavaType getConcreteType(ObjectStamp stamp, Assumptions assumptions) {
+        if (stamp.isExactType()) {
+            return stamp.type();
+        } else {
+            ResolvedJavaType type = stamp.type().findUniqueConcreteSubtype();
+            if (type != null) {
+                assumptions.recordConcreteSubtype(stamp.type(), type);
+            }
+            return type;
+        }
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State originalState = tool.getObjectState(getObject());
+        if (originalState != null && originalState.getState() == EscapeState.Virtual) {
+            VirtualObjectNode originalVirtual = originalState.getVirtualObject();
+            if (isCloneableType(originalVirtual.type(), tool.getMetaAccessProvider())) {
+                ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()];
+                for (int i = 0; i < newEntryState.length; i++) {
+                    newEntryState[i] = originalState.getEntry(i);
+                }
+                VirtualObjectNode newVirtual = originalVirtual.duplicate();
+                tool.createVirtualObject(newVirtual, newEntryState, 0);
+                tool.replaceWithVirtual(newVirtual);
+            }
+        } else {
+            ValueNode obj;
+            if (originalState != null) {
+                obj = originalState.getMaterializedValue();
+            } else {
+                obj = tool.getReplacedValue(getObject());
+            }
+            ResolvedJavaType type = getConcreteType(obj.objectStamp(), tool.getAssumptions());
+            if (isCloneableType(type, tool.getMetaAccessProvider())) {
+                if (!type.isArray()) {
+                    ResolvedJavaField[] fields = type.getInstanceFields(true);
+                    ValueNode[] state = new ValueNode[fields.length];
+                    final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
+                    for (int i = 0; i < fields.length; i++) {
+                        state[i] = loads[i] = graph().add(new LoadFieldNode(obj, fields[i]));
+                    }
+
+                    VirtualObjectNode newVirtual = new VirtualInstanceNode(type, fields);
+                    final StructuredGraph structuredGraph = (StructuredGraph) graph();
+                    tool.customAction(new Runnable() {
+
+                        public void run() {
+                            for (LoadFieldNode load : loads) {
+                                structuredGraph.addBeforeFixed(ObjectCloneNode.this, load);
+                            }
+                        }
+                    });
+                    tool.createVirtualObject(newVirtual, state, 0);
+                    tool.replaceWithVirtual(newVirtual);
+                }
+            }
+        }
+    }
+
+    @Override
+    public ValueNode length() {
+        if (getObject() instanceof ArrayLengthProvider) {
+            return ((ArrayLengthProvider) getObject()).length();
+        } else {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java	Tue Feb 12 16:06:20 2013 +0100
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011, 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.snippets;
+
+import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
+
+public class ObjectCloneSnippets implements SnippetsInterface {
+
+    public static final Method instanceCloneMethod = getCloneMethod("instanceClone");
+    public static final Method arrayCloneMethod = getCloneMethod("arrayClone");
+    public static final Method genericCloneMethod = getCloneMethod("genericClone");
+
+    private static Method getCloneMethod(String name) {
+        try {
+            return ObjectCloneSnippets.class.getDeclaredMethod(name, Object.class);
+        } catch (SecurityException | NoSuchMethodException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    private static Object instanceClone(Object src, Word hub, int layoutHelper) {
+        int instanceSize = layoutHelper;
+        Pointer memory = NewObjectSnippets.allocate(instanceSize);
+        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
+        Object result = NewObjectSnippets.initializeObject((Word) memory, hub, prototypeMarkWord, instanceSize, false, false);
+
+        memory = Word.fromObject(result);
+        for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) {
+            memory.writeWord(offset, Word.fromObject(src).readWord(offset));
+        }
+
+        return result;
+    }
+
+    private static Object arrayClone(Object src, Word hub, int layoutHelper) {
+        int arrayLength = ArrayLengthNode.arrayLength(src);
+        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
+        int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
+        int sizeInBytes = NewObjectSnippets.computeArrayAllocationSize(arrayLength, wordSize(), headerSize, log2ElementSize);
+
+        Pointer memory = NewObjectSnippets.allocate(sizeInBytes);
+        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
+        Object result = NewObjectSnippets.initializeArray((Word) memory, hub, arrayLength, sizeInBytes, prototypeMarkWord, headerSize, false, false);
+
+        memory = Word.fromObject(result);
+        for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) {
+            memory.writeWord(offset, Word.fromObject(src).readWord(offset));
+        }
+        return result;
+    }
+
+    private static Word getAndCheckHub(Object src) {
+        Word hub = loadHub(src);
+        if (!(src instanceof Cloneable)) {
+            probability(DEOPT_PATH_PROBABILITY);
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        return hub;
+    }
+
+    @Snippet
+    public static Object instanceClone(Object src) {
+        instanceCloneCounter.inc();
+        Word hub = getAndCheckHub(src);
+        return instanceClone(src, hub, hub.readInt(layoutHelperOffset()));
+    }
+
+    @Snippet
+    public static Object arrayClone(Object src) {
+        arrayCloneCounter.inc();
+        Word hub = getAndCheckHub(src);
+        int layoutHelper = hub.readInt(layoutHelperOffset());
+        return arrayClone(src, hub, layoutHelper);
+    }
+
+    @Snippet
+    public static Object genericClone(Object src) {
+        genericCloneCounter.inc();
+        Word hub = getAndCheckHub(src);
+        int layoutHelper = hub.readInt(layoutHelperOffset());
+        if (layoutHelper < 0) {
+            probability(LIKELY_PROBABILITY);
+            genericArrayCloneCounter.inc();
+            return arrayClone(src, hub, layoutHelper);
+        } else {
+            genericInstanceCloneCounter.inc();
+            return instanceClone(src, hub, layoutHelper);
+        }
+    }
+
+    private static final SnippetCounter.Group cloneCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Object.clone") : null;
+    private static final SnippetCounter instanceCloneCounter = new SnippetCounter(cloneCounters, "instanceClone", "clone snippet for instances");
+    private static final SnippetCounter arrayCloneCounter = new SnippetCounter(cloneCounters, "arrayClone", "clone snippet for arrays");
+    private static final SnippetCounter genericCloneCounter = new SnippetCounter(cloneCounters, "genericClone", "clone snippet for arrays and instances");
+
+    private static final SnippetCounter.Group genericCloneCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Object.clone generic snippet") : null;
+    private static final SnippetCounter genericInstanceCloneCounter = new SnippetCounter(genericCloneCounters, "genericInstanceClone", "generic clone implementation took instance path");
+    private static final SnippetCounter genericArrayCloneCounter = new SnippetCounter(genericCloneCounters, "genericArrayClone", "generic clone implementation took array path");
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java	Tue Feb 12 16:06:20 2013 +0100
@@ -26,7 +26,7 @@
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 
 import com.oracle.graal.snippets.*;
-import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
+import com.oracle.graal.snippets.ClassSubstitution.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -45,4 +45,7 @@
     public static int hashCode(final Object thisObj) {
         return computeHashCode(thisObj);
     }
+
+    @MacroSubstitution(macro = ObjectCloneNode.class, isStatic = false)
+    public static native Object clone(Object obj);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSubstitutions.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSubstitutions.java	Tue Feb 12 16:06:20 2013 +0100
@@ -42,7 +42,7 @@
     public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", false, long.class);
     public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", false, long.class);
 
-    @MacroSubstitution(macro = ArrayCopyNode.class, isStatic = true)
+    @MacroSubstitution(macro = ArrayCopyNode.class)
     public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
 
     @MethodSubstitution
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 12 16:06:20 2013 +0100
@@ -512,7 +512,7 @@
     private void genLogicOp(Kind kind, int opcode) {
         ValueNode y = frameState.pop(kind);
         ValueNode x = frameState.pop(kind);
-        LogicNode v;
+        BitLogicNode v;
         switch (opcode) {
             case IAND:
             case LAND:
@@ -642,14 +642,14 @@
     private JavaMethod lookupMethod(int cpi, int opcode) {
         eagerResolvingForSnippets(cpi, opcode);
         JavaMethod result = constantPool.lookupMethod(cpi, opcode);
-        assert !graphBuilderConfig.eagerResolvingForSnippets() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized());
+        assert !graphBuilderConfig.eagerResolvingForSnippets() || ((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.eagerResolvingForSnippets() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized());
+        assert !graphBuilderConfig.eagerResolvingForSnippets() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
         return result;
     }
 
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_scope01.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_scope01.java	Tue Feb 12 16:06:20 2013 +0100
@@ -82,6 +82,7 @@
         return sum;
     }
 
+    @Ignore
     @Test
     public void run0() throws Throwable {
         runTest("test", 40);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Tue Feb 12 16:06:20 2013 +0100
@@ -30,7 +30,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.asm.*;
 
-//@formatter:off
 public class AMD64TestOp extends AMD64LIRInstruction {
 
     @Use({REG}) protected Value x;
@@ -55,21 +54,36 @@
     public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value x, Value y) {
         if (isRegister(y)) {
             switch (x.getKind()) {
-                case Int: masm.testl(asIntReg(x), asIntReg(y)); break;
-                case Long: masm.testq(asLongReg(x), asLongReg(y)); break;
-                default: throw GraalInternalError.shouldNotReachHere();
+                case Int:
+                    masm.testl(asIntReg(x), asIntReg(y));
+                    break;
+                case Long:
+                    masm.testq(asLongReg(x), asLongReg(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         } else if (isConstant(y)) {
             switch (x.getKind()) {
-                case Int: masm.testl(asIntReg(x), tasm.asIntConst(y)); break;
-                case Long: masm.testq(asLongReg(x), tasm.asIntConst(y)); break;
-                default: throw GraalInternalError.shouldNotReachHere();
+                case Int:
+                    masm.testl(asIntReg(x), tasm.asIntConst(y));
+                    break;
+                case Long:
+                    masm.testq(asLongReg(x), tasm.asIntConst(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         } else {
             switch (x.getKind()) {
-                case Int: masm.testl(asIntReg(x), tasm.asIntAddr(y)); break;
-                case Long: masm.testq(asLongReg(x), tasm.asLongAddr(y)); break;
-                default: throw GraalInternalError.shouldNotReachHere();
+                case Int:
+                    masm.testl(asIntReg(x), tasm.asIntAddr(y));
+                    break;
+                case Long:
+                    masm.testq(asLongReg(x), tasm.asLongAddr(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         }
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Tue Feb 12 16:06:20 2013 +0100
@@ -102,7 +102,7 @@
                     }
                     negated = true;
                 }
-                BooleanNode ifTest = ifNode.condition();
+                LogicNode ifTest = ifNode.condition();
                 if (!(ifTest instanceof IntegerLessThanNode)) {
                     if (ifTest instanceof IntegerBelowThanNode) {
                         Debug.log("Ignored potential Counted loop at %s with |<|", loopBegin);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BooleanNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public abstract class BooleanNode extends FloatingNode {
-
-    public BooleanNode(Stamp stamp) {
-        super(stamp);
-    }
-
-    public BooleanNode(Stamp stamp, ValueNode... dependencies) {
-        super(stamp, dependencies);
-    }
-
-    /**
-     * Tells all usages of this node to negate their effect. For example, IfNodes should switch
-     * their true and false successors.
-     */
-    public void negateUsages() {
-        for (Node n : usages().snapshot()) {
-            assert n instanceof Negatable;
-            ((Negatable) n).negate();
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -35,7 +36,7 @@
  * reference, address, etc.
  */
 @NodeInfo(shortName = "Const", nameTemplate = "Const({p#rawvalue})")
-public class ConstantNode extends BooleanNode implements LIRLowerable {
+public class ConstantNode extends FloatingNode implements LIRLowerable {
 
     public final Constant value;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -31,25 +31,25 @@
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}")
 public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, LIRLowerable, Node.IterableNodeType, Negatable {
 
-    @Input private BooleanNode condition;
+    @Input private LogicNode condition;
     private final DeoptimizationReason reason;
     private final DeoptimizationAction action;
     private boolean negated;
 
-    public BooleanNode condition() {
+    public LogicNode condition() {
         return condition;
     }
 
-    public void setCondition(BooleanNode x) {
+    public void setCondition(LogicNode x) {
         updateUsages(condition, x);
         condition = x;
     }
 
-    public FixedGuardNode(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
+    public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
         this(condition, deoptReason, action, false);
     }
 
-    public FixedGuardNode(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
+    public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
         super(StampFactory.forVoid());
         this.action = action;
         this.negated = negated;
@@ -85,9 +85,9 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        if (condition instanceof ConstantNode) {
-            ConstantNode c = (ConstantNode) condition;
-            if (c.asConstant().asBoolean() != negated) {
+        if (condition instanceof LogicConstantNode) {
+            LogicConstantNode c = (LogicConstantNode) condition;
+            if (c.getValue() != negated) {
                 ((StructuredGraph) graph()).removeFixed(this);
             } else {
                 FixedNode next = this.next();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -44,12 +44,12 @@
 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}")
 public final class GuardNode extends FloatingNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, Negatable {
 
-    @Input private BooleanNode condition;
+    @Input private LogicNode condition;
     private final DeoptimizationReason reason;
     private final DeoptimizationAction action;
     private boolean negated;
 
-    public GuardNode(BooleanNode condition, FixedNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated) {
+    public GuardNode(LogicNode condition, FixedNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated) {
         super(StampFactory.dependency(), anchor);
         this.condition = condition;
         this.reason = reason;
@@ -60,11 +60,11 @@
     /**
      * The instruction that produces the tested boolean value.
      */
-    public BooleanNode condition() {
+    public LogicNode condition() {
         return condition;
     }
 
-    public void setCondition(BooleanNode x) {
+    public void setCondition(LogicNode x) {
         updateUsages(condition, x);
         condition = x;
     }
@@ -97,9 +97,9 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (condition() instanceof ConstantNode) {
-            ConstantNode c = (ConstantNode) condition();
-            if (c.asConstant().asBoolean() != negated) {
+        if (condition() instanceof LogicConstantNode) {
+            LogicConstantNode c = (LogicConstantNode) condition();
+            if (c.getValue() != negated) {
                 if (!dependencies().isEmpty()) {
                     for (Node usage : usages()) {
                         if (usage instanceof ValueNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -41,23 +41,23 @@
 
     @Successor private BeginNode trueSuccessor;
     @Successor private BeginNode falseSuccessor;
-    @Input private BooleanNode condition;
+    @Input private LogicNode condition;
     private double trueSuccessorProbability;
 
-    public BooleanNode condition() {
+    public LogicNode condition() {
         return condition;
     }
 
-    public void setCondition(BooleanNode x) {
+    public void setCondition(LogicNode x) {
         updateUsages(condition, x);
         condition = x;
     }
 
-    public IfNode(BooleanNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) {
+    public IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) {
         this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), trueSuccessorProbability);
     }
 
-    public IfNode(BooleanNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
+    public IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
         super(StampFactory.forVoid());
         this.condition = condition;
         this.falseSuccessor = falseSuccessor;
@@ -140,9 +140,9 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        if (condition() instanceof ConstantNode) {
-            ConstantNode c = (ConstantNode) condition();
-            if (c.asConstant().asBoolean()) {
+        if (condition() instanceof LogicConstantNode) {
+            LogicConstantNode c = (LogicConstantNode) condition();
+            if (c.getValue()) {
                 tool.deleteBranch(falseSuccessor());
                 tool.addToWorkList(trueSuccessor());
                 ((StructuredGraph) graph()).removeSplit(this, trueSuccessor());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * The {@code ConstantNode} represents a constant such as an integer value, long, float, object
+ * reference, address, etc.
+ */
+@NodeInfo(nameTemplate = "{p#value}")
+public class LogicConstantNode extends LogicNode implements LIRLowerable {
+
+    public final boolean value;
+
+    protected LogicConstantNode(boolean value) {
+        super();
+        this.value = value;
+    }
+
+    /**
+     * Returns a node for a boolean constant.
+     * 
+     * @param v the boolean value for which to create the instruction
+     * @param graph
+     * @return a node representing the boolean
+     */
+    public static LogicConstantNode forBoolean(boolean v, Graph graph) {
+        return graph.unique(new LogicConstantNode(v));
+    }
+
+    public static LogicConstantNode tautology(Graph graph) {
+        return forBoolean(true, graph);
+    }
+
+    public static LogicConstantNode contradiction(Graph graph) {
+        return forBoolean(false, graph);
+    }
+
+    public boolean getValue() {
+        return value;
+    }
+
+    @Override
+    public LogicNode canonical(CanonicalizerTool tool) {
+        throw new GraalInternalError("shouldn't call canonical on LogicConstantNode");
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        // nothing to do
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public abstract class LogicNode extends FloatingNode {
+
+    public LogicNode(ValueNode... dependencies) {
+        super(StampFactory.condition(), dependencies);
+    }
+
+    /**
+     * Tells all usages of this node to negate their effect. For example, IfNodes should switch
+     * their true and false successors.
+     */
+    public void negateUsages() {
+        for (Node n : usages().snapshot()) {
+            assert n instanceof Negatable;
+            ((Negatable) n).negate();
+        }
+    }
+
+    // forces all subclasses to canonicalize to BooleanNode instances
+    public abstract LogicNode canonical(CanonicalizerTool tool);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "&")
-public final class AndNode extends LogicNode implements Canonicalizable, LIRLowerable {
+public final class AndNode extends BitLogicNode implements Canonicalizable, LIRLowerable {
 
     public AndNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -175,11 +175,11 @@
         } else if (node instanceof IntegerMulNode) {
             return IntegerArithmeticNode.mul(a, IntegerAddNode.mul(m1, m2));
         } else if (node instanceof AndNode) {
-            return LogicNode.and(a, LogicNode.and(m1, m2));
+            return BitLogicNode.and(a, BitLogicNode.and(m1, m2));
         } else if (node instanceof OrNode) {
-            return LogicNode.or(a, LogicNode.or(m1, m2));
+            return BitLogicNode.or(a, BitLogicNode.or(m1, m2));
         } else if (node instanceof XorNode) {
-            return LogicNode.xor(a, LogicNode.xor(m1, m2));
+            return BitLogicNode.xor(a, BitLogicNode.xor(m1, m2));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.calc;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * The {@code LogicNode} class definition.
+ */
+public abstract class BitLogicNode extends BinaryNode {
+
+    /**
+     * Constructs a new logic operation node.
+     * 
+     * @param x the first input into this node
+     * @param y the second input into this node
+     */
+    public BitLogicNode(Kind kind, ValueNode x, ValueNode y) {
+        super(kind, x, y);
+        assert kind == Kind.Int || kind == Kind.Long;
+    }
+
+    public static BitLogicNode and(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch (v1.kind()) {
+            case Int:
+                return graph.unique(new AndNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new AndNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
+
+    public static BitLogicNode or(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch (v1.kind()) {
+            case Int:
+                return graph.unique(new OrNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new OrNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
+
+    public static BitLogicNode xor(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch (v1.kind()) {
+            case Int:
+                return graph.unique(new XorNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new XorNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -26,7 +26,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /* TODO (thomaswue/gdub) For high-level optimization purpose the compare node should be a boolean *value* (it is currently only a helper node)
  * But in the back-end the comparison should not always be materialized (for example in x86 the comparison result will not be in a register but in a flag)
@@ -34,7 +33,7 @@
  * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed
  * into variants that do not materialize the value (CompareIf, CompareGuard...)
  */
-public abstract class CompareNode extends BooleanNode implements Canonicalizable, LIRLowerable {
+public abstract class CompareNode extends LogicNode implements Canonicalizable, LIRLowerable {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
@@ -54,7 +53,6 @@
      * @param y the instruction that produces the second input to this instruction
      */
     public CompareNode(ValueNode x, ValueNode y) {
-        super(StampFactory.condition());
         assert (x == null && y == null) || x.kind() == y.kind();
         this.x = x;
         this.y = y;
@@ -78,7 +76,7 @@
     public void generate(LIRGeneratorTool gen) {
     }
 
-    private ValueNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, MetaAccessProvider runtime, Condition cond) {
+    private LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, MetaAccessProvider runtime, Condition cond) {
         Constant trueConstant = conditionalNode.trueValue().asConstant();
         Constant falseConstant = conditionalNode.falseValue().asConstant();
 
@@ -87,7 +85,7 @@
             boolean falseResult = cond.foldCondition(falseConstant, constant, runtime, unorderedIsTrue());
 
             if (trueResult == falseResult) {
-                return ConstantNode.forBoolean(trueResult, graph());
+                return LogicConstantNode.forBoolean(trueResult, graph());
             } else {
                 if (trueResult) {
                     assert falseResult == false;
@@ -103,13 +101,14 @@
         return this;
     }
 
-    protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
+    protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         throw new GraalInternalError("NormalizeCompareNode connected to %s (%s %s %s)", this, constant, normalizeNode, mirrored);
     }
 
-    public ValueNode canonical(CanonicalizerTool tool) {
+    @Override
+    public LogicNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && y().isConstant() && tool.runtime() != null) {
-            return ConstantNode.forBoolean(condition().foldCondition(x().asConstant(), y().asConstant(), tool.runtime(), unorderedIsTrue()), graph());
+            return LogicConstantNode.forBoolean(condition().foldCondition(x().asConstant(), y().asConstant(), tool.runtime(), unorderedIsTrue()), graph());
         }
         if (x().isConstant()) {
             if (y() instanceof ConditionalNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -35,13 +35,13 @@
  */
 public final class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable, Negatable {
 
-    @Input private BooleanNode condition;
+    @Input private LogicNode condition;
 
-    public BooleanNode condition() {
+    public LogicNode condition() {
         return condition;
     }
 
-    public ConditionalNode(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
+    public ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) {
         super(trueValue.kind(), trueValue, falseValue);
         assert trueValue.kind() == falseValue.kind();
         this.condition = condition;
@@ -73,9 +73,9 @@
                 }
             }
         }
-        if (condition instanceof ConstantNode) {
-            ConstantNode c = (ConstantNode) condition;
-            if (c.asConstant().asBoolean()) {
+        if (condition instanceof LogicConstantNode) {
+            LogicConstantNode c = (LogicConstantNode) condition;
+            if (c.getValue()) {
                 return trueValue();
             } else {
                 return falseValue();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -58,9 +58,9 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
+    public LogicNode canonical(CanonicalizerTool tool) {
         if (x() == y() && !unorderedIsTrue()) {
-            return ConstantNode.forBoolean(false, graph());
+            return LogicConstantNode.contradiction(graph());
         }
         return super.canonical(tool);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -54,17 +54,17 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
+    public LogicNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
-            return ConstantNode.forBoolean(false, graph());
+            return LogicConstantNode.contradiction(graph());
         } else {
             IntegerStamp xStamp = x().integerStamp();
             IntegerStamp yStamp = y().integerStamp();
             if (yStamp.isPositive()) {
                 if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
-                    return ConstantNode.forBoolean(true, graph());
+                    return LogicConstantNode.tautology(graph());
                 } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
-                    return ConstantNode.forBoolean(false, graph());
+                    return LogicConstantNode.contradiction(graph());
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -53,7 +53,7 @@
     }
 
     @Override
-    protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
+    protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         if (constant.getKind() == Kind.Int && constant.asInt() == 0) {
             ValueNode a = mirrored ? normalizeNode.y() : normalizeNode.x();
             ValueNode b = mirrored ? normalizeNode.x() : normalizeNode.y();
@@ -68,11 +68,11 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
+    public LogicNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
-            return ConstantNode.forBoolean(true, graph());
+            return LogicConstantNode.tautology(graph());
         } else if (x().integerStamp().alwaysDistinct(y().integerStamp())) {
-            return ConstantNode.forBoolean(false, graph());
+            return LogicConstantNode.contradiction(graph());
         }
 
         if (x() instanceof AndNode && y().isConstant() && y().asConstant().asLong() == 0) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -54,7 +54,7 @@
     }
 
     @Override
-    protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
+    protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         assert condition() == Condition.LT;
         if (constant.getKind() == Kind.Int && constant.asInt() == 0) {
             ValueNode a = mirrored ? normalizeNode.y() : normalizeNode.x();
@@ -70,13 +70,13 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
+    public LogicNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
-            return ConstantNode.forBoolean(false, graph());
+            return LogicConstantNode.contradiction(graph());
         } else if (x().integerStamp().upperBound() < y().integerStamp().lowerBound()) {
-            return ConstantNode.forBoolean(true, graph());
+            return LogicConstantNode.tautology(graph());
         } else if (x().integerStamp().lowerBound() >= y().integerStamp().upperBound()) {
-            return ConstantNode.forBoolean(false, graph());
+            return LogicConstantNode.contradiction(graph());
         }
         if (IntegerStamp.sameSign(x().integerStamp(), y().integerStamp())) {
             return graph().unique(new IntegerBelowThanNode(x(), y()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -24,9 +24,13 @@
 
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
-public class IntegerTestNode extends BooleanNode implements Canonicalizable, LIRLowerable {
+/**
+ * This node will perform a "test" operation on its arguments. Its result is equivalent to the
+ * expression "(x &amp; y) == 0", meaning that it will return true if (and only if) no bit is set in
+ * both x and y.
+ */
+public class IntegerTestNode extends LogicNode implements Canonicalizable, LIRLowerable {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
@@ -46,7 +50,6 @@
      * @param y the instruction that produces the second input to this instruction
      */
     public IntegerTestNode(ValueNode x, ValueNode y) {
-        super(StampFactory.condition());
         assert (x == null && y == null) || x.kind() == y.kind();
         this.x = x;
         this.y = y;
@@ -56,12 +59,13 @@
     public void generate(LIRGeneratorTool gen) {
     }
 
-    public ValueNode canonical(CanonicalizerTool tool) {
+    @Override
+    public LogicNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && y().isConstant()) {
-            return ConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph());
+            return LogicConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph());
         }
         if ((x().integerStamp().mask() & y().integerStamp().mask()) == 0) {
-            return ConstantNode.forBoolean(true, graph());
+            return LogicConstantNode.tautology(graph());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -25,12 +25,11 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
  */
-public final class IsNullNode extends BooleanNode implements Canonicalizable, LIRLowerable, Virtualizable {
+public final class IsNullNode extends LogicNode implements Canonicalizable, LIRLowerable, Virtualizable {
 
     @Input private ValueNode object;
 
@@ -44,7 +43,6 @@
      * @param object the instruction producing the object to check against null
      */
     public IsNullNode(ValueNode object) {
-        super(StampFactory.condition());
         assert object.kind() == Kind.Object : object;
         this.object = object;
     }
@@ -62,14 +60,14 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
+    public LogicNode canonical(CanonicalizerTool tool) {
         Constant constant = object().asConstant();
         if (constant != null) {
             assert constant.getKind() == Kind.Object;
-            return ConstantNode.forBoolean(constant.isNull(), graph());
+            return LogicConstantNode.forBoolean(constant.isNull(), graph());
         }
         if (object.objectStamp().nonNull()) {
-            return ConstantNode.forBoolean(false, graph());
+            return LogicConstantNode.contradiction(graph());
         }
         return this;
     }
@@ -77,7 +75,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         if (tool.getObjectState(object) != null) {
-            tool.replaceWithValue(ConstantNode.forBoolean(false, graph()));
+            tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.calc;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * The {@code LogicNode} class definition.
- */
-public abstract class LogicNode extends BinaryNode {
-
-    /**
-     * Constructs a new logic operation node.
-     * 
-     * @param x the first input into this node
-     * @param y the second input into this node
-     */
-    public LogicNode(Kind kind, ValueNode x, ValueNode y) {
-        super(kind, x, y);
-        assert kind == Kind.Int || kind == Kind.Long;
-    }
-
-    public static LogicNode and(ValueNode v1, ValueNode v2) {
-        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
-        Graph graph = v1.graph();
-        switch (v1.kind()) {
-            case Int:
-                return graph.unique(new AndNode(Kind.Int, v1, v2));
-            case Long:
-                return graph.unique(new AndNode(Kind.Long, v1, v2));
-            default:
-                throw ValueNodeUtil.shouldNotReachHere();
-        }
-    }
-
-    public static LogicNode or(ValueNode v1, ValueNode v2) {
-        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
-        Graph graph = v1.graph();
-        switch (v1.kind()) {
-            case Int:
-                return graph.unique(new OrNode(Kind.Int, v1, v2));
-            case Long:
-                return graph.unique(new OrNode(Kind.Long, v1, v2));
-            default:
-                throw ValueNodeUtil.shouldNotReachHere();
-        }
-    }
-
-    public static LogicNode xor(ValueNode v1, ValueNode v2) {
-        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
-        Graph graph = v1.graph();
-        switch (v1.kind()) {
-            case Int:
-                return graph.unique(new XorNode(Kind.Int, v1, v2));
-            case Long:
-                return graph.unique(new XorNode(Kind.Long, v1, v2));
-            default:
-                throw ValueNodeUtil.shouldNotReachHere();
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -51,8 +51,8 @@
     public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
 
-        BooleanNode equalComp;
-        BooleanNode lessComp;
+        LogicNode equalComp;
+        LogicNode lessComp;
         if (x().kind() == Kind.Double || x().kind() == Kind.Float) {
             equalComp = graph.unique(new FloatEqualsNode(x(), y()));
             lessComp = graph.unique(new FloatLessThanNode(x(), y(), isUnorderedLess));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -53,9 +53,9 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
+    public LogicNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
-            return ConstantNode.forBoolean(true, graph());
+            return LogicConstantNode.tautology(graph());
         }
 
         if (x().objectStamp().alwaysNull()) {
@@ -64,7 +64,7 @@
             return graph().unique(new IsNullNode(x()));
         }
         if (x().stamp().alwaysDistinct(y().stamp())) {
-            return ConstantNode.forBoolean(false, graph());
+            return LogicConstantNode.contradiction(graph());
         }
 
         return super.canonical(tool);
@@ -79,10 +79,10 @@
 
         if (xVirtual ^ yVirtual) {
             // one of them is virtual: they can never be the same objects
-            tool.replaceWithValue(ConstantNode.forBoolean(false, graph()));
+            tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
         } else if (xVirtual && yVirtual) {
             // both are virtual: check if they refer to the same object
-            tool.replaceWithValue(ConstantNode.forBoolean(stateX == stateY, graph()));
+            tool.replaceWithValue(LogicConstantNode.forBoolean(stateX == stateY, graph()));
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "|")
-public final class OrNode extends LogicNode implements Canonicalizable, LIRLowerable {
+public final class OrNode extends BitLogicNode implements Canonicalizable, LIRLowerable {
 
     public OrNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "^")
-public final class XorNode extends LogicNode implements Canonicalizable, LIRLowerable {
+public final class XorNode extends BitLogicNode implements Canonicalizable, LIRLowerable {
 
     public XorNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -47,8 +47,9 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         if (array() instanceof ArrayLengthProvider) {
             ValueNode length = ((ArrayLengthProvider) array()).length();
-            assert length != null;
-            return length;
+            if (length != null) {
+                return length;
+            }
         }
         MetaAccessProvider runtime = tool.runtime();
         if (runtime != null && array().isConstant() && !array().isNullConstant()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -27,14 +27,13 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code InstanceOfDynamicNode} represents a type check where the type being checked is not
  * known at compile time. This is used, for instance, to intrinsify {@link Class#isInstance(Object)}
  * .
  */
-public final class InstanceOfDynamicNode extends BooleanNode implements Canonicalizable, Lowerable {
+public final class InstanceOfDynamicNode extends LogicNode implements Canonicalizable, Lowerable {
 
     @Input private ValueNode object;
     @Input private ValueNode mirror;
@@ -47,7 +46,6 @@
      * @param object the object being tested by the instanceof
      */
     public InstanceOfDynamicNode(ValueNode mirror, ValueNode object) {
-        super(StampFactory.condition());
         this.mirror = mirror;
         this.object = object;
         assert mirror.kind() == Kind.Object;
@@ -61,7 +59,7 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
+    public LogicNode canonical(CanonicalizerTool tool) {
         assert object() != null : this;
         if (mirror().isConstant()) {
             Class clazz = (Class) mirror().asConstant().asObject();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -32,7 +32,7 @@
 /**
  * The {@code InstanceOfNode} represents an instanceof test.
  */
-public final class InstanceOfNode extends BooleanNode implements Canonicalizable, Lowerable, Virtualizable {
+public final class InstanceOfNode extends LogicNode implements Canonicalizable, Lowerable, Virtualizable {
 
     @Input private ValueNode object;
     private final ResolvedJavaType type;
@@ -45,7 +45,6 @@
      * @param object the object being tested by the instanceof
      */
     public InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
-        super(StampFactory.condition());
         this.type = type;
         this.object = object;
         this.profile = profile;
@@ -58,7 +57,7 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
+    public LogicNode canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
         ObjectStamp stamp = object().objectStamp();
@@ -70,7 +69,7 @@
             if (subType) {
                 if (stamp.nonNull()) {
                     // the instanceOf matches, so return true
-                    return ConstantNode.forBoolean(true, graph());
+                    return LogicConstantNode.tautology(graph());
                 } else {
                     // the instanceof matches if the object is non-null, so return true depending on
                     // the null-ness.
@@ -81,7 +80,7 @@
                 // since this type check failed for an exact type we know that it can never succeed
                 // at run time.
                 // we also don't care about null values, since they will also make the check fail.
-                return ConstantNode.forBoolean(false, graph());
+                return LogicConstantNode.contradiction(graph());
             }
         } else if (stampType != null) {
             boolean subType = type().isAssignableFrom(stampType);
@@ -89,7 +88,7 @@
             if (subType) {
                 if (stamp.nonNull()) {
                     // the instanceOf matches, so return true
-                    return ConstantNode.forBoolean(true, graph());
+                    return LogicConstantNode.tautology(graph());
                 } else {
                     // the instanceof matches if the object is non-null, so return true depending on
                     // the null-ness.
@@ -102,7 +101,7 @@
             }
         }
         if (object().objectStamp().alwaysNull()) {
-            return ConstantNode.forBoolean(false, graph());
+            return LogicConstantNode.contradiction(graph());
         }
         return this;
     }
@@ -134,7 +133,7 @@
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
         if (state != null) {
-            tool.replaceWithValue(ConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph()));
+            tool.replaceWithValue(LogicConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph()));
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArrayLengthProvider.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArrayLengthProvider.java	Tue Feb 12 16:06:20 2013 +0100
@@ -26,5 +26,8 @@
 
 public interface ArrayLengthProvider {
 
+    /**
+     * @return the length of the array described by this node, or null if it is not available
+     */
     ValueNode length();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Tue Feb 12 16:06:20 2013 +0100
@@ -117,7 +117,7 @@
 
     public abstract void emitConditional(ConditionalNode i);
 
-    public abstract void emitGuardCheck(BooleanNode comp, DeoptimizationReason deoptReason, DeoptimizationAction deoptAction, boolean negated);
+    public abstract void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction deoptAction, boolean negated);
 
     public abstract void emitSwitch(SwitchNode i);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Tue Feb 12 16:06:20 2013 +0100
@@ -36,9 +36,9 @@
 
     ValueNode createNullCheckGuard(ValueNode object);
 
-    ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action);
+    ValueNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action);
 
-    ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated);
+    ValueNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated);
 
     Assumptions assumptions();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Tue Feb 12 16:06:20 2013 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.spi;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -43,6 +44,12 @@
     MetaAccessProvider getMetaAccessProvider();
 
     /**
+     * @return the {@link Assumptions} associated with the current compilation, which can be used to
+     *         make type assumptions during virtualization.
+     */
+    Assumptions getAssumptions();
+
+    /**
      * This method should be used to query the maximum size of virtualized objects before attempting
      * virtualization.
      * 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -70,4 +70,9 @@
     public Kind entryKind(int index) {
         return kind;
     }
+
+    @Override
+    public BoxedVirtualObjectNode duplicate() {
+        return new BoxedVirtualObjectNode(type, kind, unboxedValue);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -132,4 +132,9 @@
         assert index >= 0 && index < length;
         return componentType.getKind();
     }
+
+    @Override
+    public VirtualArrayNode duplicate() {
+        return new VirtualArrayNode(componentType, length);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -32,16 +32,23 @@
 
     private final ResolvedJavaType type;
     private final ResolvedJavaField[] fields;
-    private final HashMap<ResolvedJavaField, Integer> fieldMap = new HashMap<>();
+    private final HashMap<ResolvedJavaField, Integer> fieldMap;
 
     public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
         this.type = type;
         this.fields = fields;
+        fieldMap = new HashMap<>();
         for (int i = 0; i < fields.length; i++) {
             fieldMap.put(fields[i], i);
         }
     }
 
+    private VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, HashMap<ResolvedJavaField, Integer> fieldMap) {
+        this.type = type;
+        this.fields = fields;
+        this.fieldMap = fieldMap;
+    }
+
     @Override
     public ResolvedJavaType type() {
         return type;
@@ -85,4 +92,9 @@
         assert index >= 0 && index < fields.length;
         return fields[index].getKind();
     }
+
+    @Override
+    public VirtualInstanceNode duplicate() {
+        return new VirtualInstanceNode(type, fields, fieldMap);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -53,4 +53,6 @@
     public abstract int entryIndexForOffset(long constantOffset);
 
     public abstract Kind entryKind(int index);
+
+    public abstract VirtualObjectNode duplicate();
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Feb 12 16:06:20 2013 +0100
@@ -68,8 +68,8 @@
         private IdentityHashMap<ValueNode, ResolvedJavaType> knownTypes;
         private HashSet<ValueNode> knownNonNull;
         private HashSet<ValueNode> knownNull;
-        private IdentityHashMap<BooleanNode, ValueNode> trueConditions;
-        private IdentityHashMap<BooleanNode, ValueNode> falseConditions;
+        private IdentityHashMap<LogicNode, ValueNode> trueConditions;
+        private IdentityHashMap<LogicNode, ValueNode> falseConditions;
 
         public State() {
             this.knownTypes = new IdentityHashMap<>();
@@ -90,8 +90,8 @@
         @Override
         public boolean merge(MergeNode merge, List<State> withStates) {
             IdentityHashMap<ValueNode, ResolvedJavaType> newKnownTypes = new IdentityHashMap<>();
-            IdentityHashMap<BooleanNode, ValueNode> newTrueConditions = new IdentityHashMap<>();
-            IdentityHashMap<BooleanNode, ValueNode> newFalseConditions = new IdentityHashMap<>();
+            IdentityHashMap<LogicNode, ValueNode> newTrueConditions = new IdentityHashMap<>();
+            IdentityHashMap<LogicNode, ValueNode> newFalseConditions = new IdentityHashMap<>();
 
             HashSet<ValueNode> newKnownNull = new HashSet<>(knownNull);
             HashSet<ValueNode> newKnownNonNull = new HashSet<>(knownNonNull);
@@ -116,8 +116,8 @@
                 }
             }
 
-            for (Map.Entry<BooleanNode, ValueNode> entry : trueConditions.entrySet()) {
-                BooleanNode check = entry.getKey();
+            for (Map.Entry<LogicNode, ValueNode> entry : trueConditions.entrySet()) {
+                LogicNode check = entry.getKey();
                 ValueNode guard = entry.getValue();
 
                 for (State other : withStates) {
@@ -134,8 +134,8 @@
                     newTrueConditions.put(check, guard);
                 }
             }
-            for (Map.Entry<BooleanNode, ValueNode> entry : falseConditions.entrySet()) {
-                BooleanNode check = entry.getKey();
+            for (Map.Entry<LogicNode, ValueNode> entry : falseConditions.entrySet()) {
+                LogicNode check = entry.getKey();
                 ValueNode guard = entry.getValue();
 
                 for (State other : withStates) {
@@ -225,7 +225,7 @@
          * Adds information about a condition. If isTrue is true then the condition is known to
          * hold, otherwise the condition is known not to hold.
          */
-        public void addCondition(boolean isTrue, BooleanNode condition, ValueNode anchor) {
+        public void addCondition(boolean isTrue, LogicNode condition, ValueNode anchor) {
             if (isTrue) {
                 if (!trueConditions.containsKey(condition)) {
                     trueConditions.put(condition, anchor);
@@ -294,16 +294,16 @@
 
     public class ConditionalElimination extends PostOrderNodeIterator<State> {
 
-        private final BooleanNode trueConstant;
-        private final BooleanNode falseConstant;
+        private final LogicNode trueConstant;
+        private final LogicNode falseConstant;
 
         public ConditionalElimination(FixedNode start, State initialState) {
             super(start, initialState);
-            this.trueConstant = ConstantNode.forBoolean(true, graph);
-            this.falseConstant = ConstantNode.forBoolean(false, graph);
+            this.trueConstant = LogicConstantNode.tautology(graph);
+            this.falseConstant = LogicConstantNode.contradiction(graph);
         }
 
-        private void registerCondition(boolean isTrue, BooleanNode condition, ValueNode anchor) {
+        private void registerCondition(boolean isTrue, LogicNode condition, ValueNode anchor) {
             state.addCondition(isTrue, condition, anchor);
 
             if (isTrue && condition instanceof InstanceOfNode) {
@@ -351,7 +351,7 @@
             if (pred instanceof IfNode) {
                 IfNode ifNode = (IfNode) pred;
 
-                if (!(ifNode.condition() instanceof ConstantNode)) {
+                if (!(ifNode.condition() instanceof LogicConstantNode)) {
                     registerCondition(begin == ifNode.trueSuccessor(), ifNode.condition(), begin);
                 }
             } else if (pred instanceof TypeSwitchNode) {
@@ -378,7 +378,7 @@
         }
 
         private void registerGuard(GuardNode guard) {
-            BooleanNode condition = guard.condition();
+            LogicNode condition = guard.condition();
 
             ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition);
             if (existingGuards != null) {
@@ -386,7 +386,7 @@
                 GraphUtil.killWithUnusedFloatingInputs(guard);
                 metricGuardsRemoved.increment();
             } else {
-                BooleanNode replacement = evaluateCondition(condition, trueConstant, falseConstant);
+                LogicNode replacement = evaluateCondition(condition, trueConstant, falseConstant);
                 if (replacement != null) {
                     guard.setCondition(replacement);
                     if (condition.usages().isEmpty()) {
@@ -404,7 +404,7 @@
          * true, false or unknown. In case of true or false the corresponding value is returned,
          * otherwise null.
          */
-        private <T extends ValueNode> T evaluateCondition(BooleanNode condition, T trueValue, T falseValue) {
+        private <T extends ValueNode> T evaluateCondition(LogicNode condition, T trueValue, T falseValue) {
             if (state.trueConditions.containsKey(condition)) {
                 return trueValue;
             } else if (state.falseConditions.containsKey(condition)) {
@@ -482,8 +482,8 @@
                 }
             } else if (node instanceof IfNode) {
                 IfNode ifNode = (IfNode) node;
-                BooleanNode compare = ifNode.condition();
-                BooleanNode replacement = evaluateCondition(compare, trueConstant, falseConstant);
+                LogicNode compare = ifNode.condition();
+                LogicNode replacement = evaluateCondition(compare, trueConstant, falseConstant);
 
                 if (replacement != null) {
                     ifNode.setCondition(replacement);
@@ -498,7 +498,7 @@
                     ValueNode value = phi.valueAt(index);
                     if (value instanceof ConditionalNode) {
                         ConditionalNode materialize = (ConditionalNode) value;
-                        BooleanNode compare = materialize.condition();
+                        LogicNode compare = materialize.condition();
                         ValueNode replacement = evaluateCondition(compare, materialize.trueValue(), materialize.falseValue());
 
                         if (replacement != null) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Tue Feb 12 16:06:20 2013 +0100
@@ -79,7 +79,7 @@
         } else if (deoptBegin.predecessor() instanceof IfNode) {
             IfNode ifNode = (IfNode) deoptBegin.predecessor();
             BeginNode otherBegin = ifNode.trueSuccessor();
-            BooleanNode conditionNode = ifNode.condition();
+            LogicNode conditionNode = ifNode.condition();
             if (conditionNode instanceof InstanceOfNode) {
                 // TODO The lowering currently does not support a FixedGuard as the usage of an
                 // InstanceOfNode. Relax this restriction.
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java	Tue Feb 12 16:06:20 2013 +0100
@@ -49,10 +49,10 @@
 
     private static class Condition {
 
-        final BooleanNode conditionNode;
+        final LogicNode conditionNode;
         final boolean negated;
 
-        public Condition(BooleanNode conditionNode, boolean negated) {
+        public Condition(LogicNode conditionNode, boolean negated) {
             this.conditionNode = conditionNode;
             this.negated = negated;
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Tue Feb 12 16:06:20 2013 +0100
@@ -70,7 +70,7 @@
         }
 
         @Override
-        public ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
+        public ValueNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
             return createGuard(condition, deoptReason, action, false);
         }
 
@@ -80,7 +80,7 @@
         }
 
         @Override
-        public ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
+        public ValueNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
             if (GraalOptions.OptEliminateGuards) {
                 for (Node usage : condition.usages()) {
                     if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage)) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Feb 12 16:06:20 2013 +0100
@@ -197,6 +197,7 @@
     public static boolean OptDevirtualizeInvokesOptimistically = true;
 
     // Intrinsification settings
+    public static boolean IntrinsifyObjectClone              = ____;
     public static boolean IntrinsifyArrayCopy                = true;
     public static boolean IntrinsifyObjectMethods            = true;
     public static boolean IntrinsifySystemMethods            = true;
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSubstitutions.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSubstitutions.java	Tue Feb 12 16:06:20 2013 +0100
@@ -313,37 +313,37 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putByte(@SuppressWarnings("unused") final Object thisObj, long address, byte value) {
-        DirectStoreNode.store(address, value);
+        DirectStoreNode.store(address, value, Kind.Byte);
     }
 
     @MethodSubstitution(isStatic = false)
     public static void putShort(@SuppressWarnings("unused") final Object thisObj, long address, short value) {
-        DirectStoreNode.store(address, value);
+        DirectStoreNode.store(address, value, Kind.Short);
     }
 
     @MethodSubstitution(isStatic = false)
     public static void putChar(@SuppressWarnings("unused") final Object thisObj, long address, char value) {
-        DirectStoreNode.store(address, value);
+        DirectStoreNode.store(address, value, Kind.Char);
     }
 
     @MethodSubstitution(isStatic = false)
     public static void putInt(@SuppressWarnings("unused") final Object thisObj, long address, int value) {
-        DirectStoreNode.store(address, value);
+        DirectStoreNode.store(address, value, Kind.Int);
     }
 
     @MethodSubstitution(isStatic = false)
     public static void putLong(@SuppressWarnings("unused") final Object thisObj, long address, long value) {
-        DirectStoreNode.store(address, value);
+        DirectStoreNode.store(address, value, Kind.Long);
     }
 
     @MethodSubstitution(isStatic = false)
     public static void putFloat(@SuppressWarnings("unused") final Object thisObj, long address, float value) {
-        DirectStoreNode.store(address, value);
+        DirectStoreNode.store(address, value, Kind.Float);
     }
 
     @MethodSubstitution(isStatic = false)
     public static void putDouble(@SuppressWarnings("unused") final Object thisObj, long address, double value) {
-        DirectStoreNode.store(address, value);
+        DirectStoreNode.store(address, value, Kind.Double);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java	Tue Feb 12 16:06:20 2013 +0100
@@ -37,40 +37,48 @@
 
     @Input private ValueNode address;
     @Input private ValueNode value;
+    private final Kind kind;
 
-    public DirectStoreNode(ValueNode address, ValueNode value) {
+    public DirectStoreNode(ValueNode address, ValueNode value, Kind kind) {
         super(StampFactory.forVoid());
         this.address = address;
         this.value = value;
+        this.kind = kind;
     }
 
-    @NodeIntrinsic
-    public static native void store(long address, boolean value);
-
-    @NodeIntrinsic
-    public static native void store(long address, byte value);
-
-    @NodeIntrinsic
-    public static native void store(long address, short value);
-
-    @NodeIntrinsic
-    public static native void store(long address, char value);
-
-    @NodeIntrinsic
-    public static native void store(long address, int value);
-
-    @NodeIntrinsic
-    public static native void store(long address, long value);
-
-    @NodeIntrinsic
-    public static native void store(long address, float value);
-
-    @NodeIntrinsic
-    public static native void store(long address, double value);
-
     @Override
     public void generate(LIRGeneratorTool gen) {
         Value v = gen.operand(value);
-        gen.emitStore(new Address(v.getKind(), gen.operand(address)), v, false);
+        gen.emitStore(new Address(kind, gen.operand(address)), v, false);
     }
+
+    /*
+     * The kind of the store is provided explicitly in these intrinsics because it is not always
+     * possible to determine the kind from the given value during compilation (because stack kinds
+     * are used).
+     */
+
+    @NodeIntrinsic
+    public static native void store(long address, boolean value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native void store(long address, byte value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native void store(long address, short value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native void store(long address, char value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native void store(long address, int value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native void store(long address, long value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native void store(long address, float value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native void store(long address, double value, @ConstantNodeParameter Kind kind);
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Tue Feb 12 16:06:20 2013 +0100
@@ -92,7 +92,7 @@
                 public Boolean call() {
                     SchedulePhase schedule = new SchedulePhase();
                     schedule.apply(graph, false);
-                    PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime);
+                    PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime, assumptions);
                     ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null);
 
                     if (closure.getNewVirtualObjectCount() == 0) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Feb 12 16:06:20 2013 +0100
@@ -26,6 +26,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -59,10 +60,10 @@
 
     private final VirtualizerToolImpl tool;
 
-    public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess) {
+    public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
         this.usages = usages;
         this.schedule = schedule;
-        tool = new VirtualizerToolImpl(effects, usages, metaAccess);
+        tool = new VirtualizerToolImpl(effects, usages, metaAccess, assumptions);
     }
 
     public GraphEffectList getEffects() {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Tue Feb 12 15:59:46 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Tue Feb 12 16:06:20 2013 +0100
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -38,11 +39,13 @@
     private final GraphEffectList effects;
     private final NodeBitMap usages;
     private final MetaAccessProvider metaAccess;
+    private final Assumptions assumptions;
 
-    VirtualizerToolImpl(GraphEffectList effects, NodeBitMap usages, MetaAccessProvider metaAccess) {
+    VirtualizerToolImpl(GraphEffectList effects, NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) {
         this.effects = effects;
         this.usages = usages;
         this.metaAccess = metaAccess;
+        this.assumptions = assumptions;
     }
 
     private boolean deleted;
@@ -56,6 +59,11 @@
         return metaAccess;
     }
 
+    @Override
+    public Assumptions getAssumptions() {
+        return assumptions;
+    }
+
     public void reset(BlockState newState, ValueNode newCurrent) {
         deleted = false;
         customAction = false;
--- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Tue Feb 12 15:59:46 2013 +0100
+++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Tue Feb 12 16:06:20 2013 +0100
@@ -96,7 +96,7 @@
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning
 org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
 org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled
 org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
 org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
 org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Tue Feb 12 15:59:46 2013 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Feb 12 16:06:20 2013 +0100
@@ -63,6 +63,7 @@
     }
 #endif
     ShouldNotReachHere();
+    return NULL;
   }
 }
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Feb 12 15:59:46 2013 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Tue Feb 12 16:06:20 2013 +0100
@@ -701,6 +701,8 @@
   set_int("layoutHelperLog2ElementSizeMask", Klass::_lh_log2_element_size_mask);
   set_int("layoutHelperElementTypeShift", Klass::_lh_element_type_shift);
   set_int("layoutHelperElementTypeMask", Klass::_lh_element_type_mask);
+  // this filters out the bit that differentiates a type array from an object array
+  set_int("layoutHelperElementTypePrimitiveInPlace", (Klass::_lh_array_tag_type_value & ~Klass::_lh_array_tag_obj_value) << Klass::_lh_array_tag_shift);
   set_int("layoutHelperHeaderSizeShift", Klass::_lh_header_size_shift);
   set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask);
   set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset()));
--- a/src/share/vm/runtime/javaCalls.cpp	Tue Feb 12 15:59:46 2013 +0100
+++ b/src/share/vm/runtime/javaCalls.cpp	Tue Feb 12 16:06:20 2013 +0100
@@ -365,12 +365,13 @@
   }
   else debug_only(args->verify(method, result->get_type(), thread));
 
+#ifndef GRAAL
   // Ignore call if method is empty
   if (method->is_empty_method()) {
     assert(result->get_type() == T_VOID, "an empty method must return a void value");
     return;
   }
-
+#endif
 
 #ifdef ASSERT
   { InstanceKlass* holder = method->method_holder();