changeset 7147:88d626e2c2a8

added TLAB fast refill stub for array allocation
author Doug Simon <doug.simon@oracle.com>
date Fri, 07 Dec 2012 23:38:09 +0100
parents 8c02d320a1ac
children 46bad05d39b1
files graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java src/share/vm/graal/graalCompilerToVM.cpp
diffstat 15 files changed, 402 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Dec 07 23:38:09 2012 +0100
@@ -27,6 +27,7 @@
 import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*;
 import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewArraySlowStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceSlowStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
@@ -85,8 +86,14 @@
                 /* arg0: object */ arg(0, Kind.Object),
                 /* arg1:   lock */ arg(1, word));
 
-        addRuntimeCall(NEW_ARRAY, c.newArrayStub,
-                /*        temps */ new Register[] {rcx, rdi, rsi},
+        addRuntimeCall(NEW_ARRAY, 0L,
+                /*        temps */ null,
+                /*          ret */ rax.asValue(Kind.Object),
+                /* arg0:    hub */ rdx.asValue(word),
+                /* arg1: length */ rbx.asValue(Kind.Int));
+
+        addRuntimeCall(NEW_ARRAY_SLOW, c.newArrayStub,
+                /*        temps */ null,
                 /*          ret */ rax.asValue(Kind.Object),
                 /* arg0:    hub */ rdx.asValue(word),
                 /* arg1: length */ rbx.asValue(Kind.Int));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Dec 07 23:38:09 2012 +0100
@@ -237,6 +237,14 @@
     public boolean tlabStats;
     public int klassInstanceSizeOffset;
     public boolean inlineContiguousAllocationSupported;
+    public long arrayPrototypeMarkWord;
+    public int layoutHelperLog2ElementSizeShift;
+    public int layoutHelperLog2ElementSizeMask;
+    public int layoutHelperElementTypeShift;
+    public int layoutHelperElementTypeMask;
+    public int layoutHelperHeaderSizeShift;
+    public int layoutHelperHeaderSizeMask;
+    public int layoutHelperOffset;
 
     // methodData information
     public int methodDataOopDataOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Dec 07 23:38:09 2012 +0100
@@ -192,6 +192,4 @@
     long[] getDeoptedLeafGraphIds();
 
     String decodePC(long pc);
-
-    long getPrototypeMarkWord(HotSpotResolvedObjectType hotSpotResolvedJavaType);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Dec 07 23:38:09 2012 +0100
@@ -139,7 +139,4 @@
 
     @Override
     public native String decodePC(long pc);
-
-    @Override
-    public native long getPrototypeMarkWord(HotSpotResolvedObjectType type);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Fri Dec 07 23:38:09 2012 +0100
@@ -470,7 +470,12 @@
     }
 
     public long prototypeMarkWord() {
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrototypeMarkWord(this);
+        HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig();
+        if (isArray()) {
+            return config.arrayPrototypeMarkWord;
+        } else {
+            return unsafeReadWord(metaspaceKlass + config.prototypeMarkWordOffset);
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Dec 07 23:38:09 2012 +0100
@@ -84,6 +84,7 @@
     private MonitorSnippets.Templates monitorSnippets;
 
     private NewInstanceStub newInstanceStub;
+    private NewArrayStub newArrayStub;
 
     private final Map<Descriptor, HotSpotRuntimeCallTarget> runtimeCalls = new HashMap<>();
     private final Map<ResolvedJavaMethod, Stub> stubs = new HashMap<>();
@@ -300,7 +301,9 @@
         installer.install(InstanceOfSnippets.class);
         installer.install(NewObjectSnippets.class);
         installer.install(MonitorSnippets.class);
+
         installer.install(NewInstanceStub.class);
+        installer.install(NewArrayStub.class);
 
         checkcastSnippets = new CheckCastSnippets.Templates(this, assumptions, graalRuntime.getTarget());
         instanceofSnippets = new InstanceOfSnippets.Templates(this, assumptions, graalRuntime.getTarget());
@@ -308,7 +311,9 @@
         monitorSnippets = new MonitorSnippets.Templates(this, assumptions, graalRuntime.getTarget(), config.useFastLocking);
 
         newInstanceStub = new NewInstanceStub(this, assumptions, graalRuntime.getTarget());
+        newArrayStub = new NewArrayStub(this, assumptions, graalRuntime.getTarget());
         newInstanceStub.install(graalRuntime.getCompiler());
+        newArrayStub.install(graalRuntime.getCompiler());
     }
 
     public HotSpotGraalRuntime getGraalRuntime() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Fri Dec 07 23:38:09 2012 +0100
@@ -37,17 +37,17 @@
 
     @Input private final ValueNode memory;
     @Input private final ValueNode length;
-    @Input private final ValueNode size;
+    @Input private final ValueNode allocationSize;
     private final ResolvedJavaType type;
     private final boolean fillContents;
     private final boolean locked;
 
-    public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode size, ResolvedJavaType type, boolean fillContents, boolean locked) {
+    public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode allocationSize, ResolvedJavaType type, boolean fillContents, boolean locked) {
         super(StampFactory.exactNonNull(type));
         this.memory = memory;
         this.type = type;
         this.length = length;
-        this.size = size;
+        this.allocationSize = allocationSize;
         this.fillContents = fillContents;
         this.locked = locked;
     }
@@ -61,8 +61,11 @@
         return length;
     }
 
-    public ValueNode size() {
-        return size;
+    /**
+     * Gets the size (in bytes) of the memory chunk allocated for the array.
+     */
+    public ValueNode allocationSize() {
+        return allocationSize;
     }
 
     public ResolvedJavaType type() {
@@ -83,5 +86,5 @@
     }
 
     @NodeIntrinsic
-    public static native Object initialize(Object memory, int length, int size, @ConstantNodeParameter ResolvedJavaType type, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter boolean locked);
+    public static native Object initialize(Object memory, int length, int allocationSize, @ConstantNodeParameter ResolvedJavaType type, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter boolean locked);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java	Fri Dec 07 23:38:09 2012 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.snippets.*;
+
+/**
+ * Node implementing a call to the {@code new_array} stub.
+ */
+public class NewArraySlowStubCall extends FixedWithNextNode implements LIRGenLowerable {
+
+    private static final Stamp defaultStamp = StampFactory.objectNonNull();
+
+    @Input private final ValueNode hub;
+    @Input private final ValueNode length;
+
+    public static final Descriptor NEW_ARRAY_SLOW = new Descriptor("new_array_slow", false, Kind.Object, wordKind(), Kind.Int);
+
+    public NewArraySlowStubCall(ValueNode hub, ValueNode length) {
+        super(defaultStamp);
+        this.hub = hub;
+        this.length = length;
+    }
+
+    @Override
+    public boolean inferStamp() {
+        if (stamp() == defaultStamp && hub.isConstant()) {
+            updateStamp(StampFactory.exactNonNull(HotSpotResolvedObjectType.fromMetaspaceKlass(hub.asConstant())));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY_SLOW);
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), gen.operand(length));
+        gen.setResult(this, result);
+    }
+
+    @NodeIntrinsic
+    public static native Object call(Word hub, int length);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Fri Dec 07 23:38:09 2012 +0100
@@ -30,13 +30,14 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.snippets.*;
 
 /**
- * Node implementing a call to the {@code new_array} stub.
+ * A call to the {@link NewArrayStub}.
  */
 public class NewArrayStubCall extends FixedWithNextNode implements LIRGenLowerable {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Fri Dec 07 23:38:09 2012 +0100
@@ -90,6 +90,11 @@
     }
 
     @Fold
+    public static long arrayPrototypeMarkWord() {
+        return config().arrayPrototypeMarkWord;
+    }
+
+    @Fold
     public static int markOffset() {
         return config().markOffset;
     }
@@ -255,6 +260,149 @@
     @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true)
     static native Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word);
 
+    @Fold
+    public
+    static int log2WordSize() {
+        return CodeUtil.log2(wordSize());
+    }
+
+    @Fold
+    public
+    static int klassStateOffset() {
+        return config().klassStateOffset;
+    }
+
+    @Fold
+    public
+    static int klassInstanceSizeOffset() {
+        return config().klassInstanceSizeOffset;
+    }
+
+    @Fold
+    public
+    static long heapTopAddress() {
+        return config().heapTopAddress;
+    }
+
+    @Fold
+    public
+    static long heapEndAddress() {
+        return config().heapEndAddress;
+    }
+
+    @Fold
+    public
+    static int threadTlabStartOffset() {
+        return config().threadTlabStartOffset;
+    }
+
+    @Fold
+    public
+    static long tlabIntArrayMarkWord() {
+        return config().tlabIntArrayMarkWord;
+    }
+
+    @Fold
+    public
+    static boolean inlineContiguousAllocationSupported() {
+        return config().inlineContiguousAllocationSupported;
+    }
+
+    @Fold
+    public
+    static int tlabAlignmentReserveInHeapWords() {
+        return config().tlabAlignmentReserve;
+    }
+
+    @Fold
+    public
+    static int threadTlabSizeOffset() {
+        return config().threadTlabSizeOffset;
+    }
+
+    @Fold
+    public
+    static int threadAllocatedBytesOffset() {
+        return config().threadAllocatedBytesOffset;
+    }
+
+    @Fold
+    public
+    static int klassStateFullyInitialized() {
+        return config().klassStateFullyInitialized;
+    }
+
+    @Fold
+    public
+    static int tlabRefillWasteLimitOffset() {
+        return config().tlabRefillWasteLimitOffset;
+    }
+
+    @Fold
+    public
+    static int tlabNumberOfRefillsOffset() {
+        return config().tlabNumberOfRefillsOffset;
+    }
+
+    @Fold
+    public
+    static int tlabFastRefillWasteOffset() {
+        return config().tlabFastRefillWasteOffset;
+    }
+
+    @Fold
+    public
+    static int tlabSlowAllocationsOffset() {
+        return config().tlabSlowAllocationsOffset;
+    }
+
+    @Fold
+    public
+    static int tlabRefillWasteIncrement() {
+        return config().tlabRefillWasteIncrement;
+    }
+
+    @Fold
+    public
+    static boolean tlabStats() {
+        return config().tlabStats;
+    }
+
+    @Fold
+    public static int layoutHelperOffset() {
+        return config().layoutHelperOffset;
+    }
+
+    @Fold
+    public static int layoutHelperHeaderSizeShift() {
+        return config().layoutHelperHeaderSizeShift;
+    }
+
+    @Fold
+    public static int layoutHelperHeaderSizeMask() {
+        return config().layoutHelperHeaderSizeMask;
+    }
+
+    @Fold
+    public static int layoutHelperLog2ElementSizeShift() {
+        return config().layoutHelperLog2ElementSizeShift;
+    }
+
+    @Fold
+    public static int layoutHelperLog2ElementSizeMask() {
+        return config().layoutHelperLog2ElementSizeMask;
+    }
+
+    @Fold
+    public static int layoutHelperElementTypeShift() {
+        return config().layoutHelperElementTypeShift;
+    }
+
+    @Fold
+    public static int layoutHelperElementTypeMask() {
+        return config().layoutHelperElementTypeMask;
+    }
+
     static {
         assert arrayIndexScale(Kind.Byte) == 1;
         assert arrayIndexScale(Kind.Boolean) == 1;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Fri Dec 07 23:38:09 2012 +0100
@@ -99,26 +99,26 @@
                     @Parameter("memory") Word memory,
                     @Parameter("hub") Word hub,
                     @Parameter("length") int length,
-                    @Parameter("size") int size,
+                    @Parameter("allocationSize") int allocationSize,
                     @Parameter("prototypeMarkWord") Word prototypeMarkWord,
                     @ConstantParameter("headerSize") int headerSize,
                     @ConstantParameter("fillContents") boolean fillContents,
                     @ConstantParameter("locked") boolean locked) {
         if (locked) {
-            return initializeArray(memory, hub, length, size, thread().or(biasedLockPattern()), headerSize, fillContents);
+            return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents);
         } else {
-            return initializeArray(memory, hub, length, size, prototypeMarkWord, headerSize, fillContents);
+            return initializeArray(memory, hub, length, allocationSize, prototypeMarkWord, headerSize, fillContents);
         }
     }
 
-    private static Object initializeArray(Word memory, Word hub, int length, int size, Word prototypeMarkWord, int headerSize, boolean fillContents) {
+    private static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, int headerSize, boolean fillContents) {
         Object result;
         if (memory == Word.zero()) {
             newarray_stub.inc();
             result = NewArrayStubCall.call(hub, length);
         } else {
             newarray_loopInit.inc();
-            formatArray(hub, size, length, headerSize, memory, prototypeMarkWord, fillContents);
+            formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents);
             result = memory.toObject();
         }
         return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
@@ -127,7 +127,7 @@
     /**
      * Maximum array length for which fast path allocation is used.
      */
-    private static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF;
+    public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF;
 
     @Snippet
     public static Object allocateArrayAndInitialize(
@@ -140,12 +140,21 @@
             // This handles both negative array sizes and very large array sizes
             DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.RuntimeConstraint);
         }
-        int size = getArraySize(length, alignment, headerSize, log2ElementSize);
-        Word memory = TLABAllocateNode.allocateVariableSize(size);
-        return InitializeArrayNode.initialize(memory, length, size, type, true, false);
+        int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize);
+        Word memory = TLABAllocateNode.allocateVariableSize(allocationSize);
+        return InitializeArrayNode.initialize(memory, length, allocationSize, type, true, false);
     }
 
-    public static int getArraySize(int length, int alignment, int headerSize, int log2ElementSize) {
+    /**
+     * Computes the size of the memory chunk allocated for an array. This size accounts for the array
+     * header size, boy size and any padding after the last element to satisfy object alignment requirements.
+     *
+     * @param length the number of elements in the array
+     * @param alignment the object alignment requirement
+     * @param headerSize the size of the array header
+     * @param log2ElementSize log2 of the size of an element in the array
+     */
+    public static int computeArrayAllocationSize(int length, int alignment, int headerSize, int log2ElementSize) {
         int size = (length << log2ElementSize) + headerSize + (alignment - 1);
         int mask = ~(alignment - 1);
         return size & mask;
@@ -200,13 +209,13 @@
     /**
      * Formats some allocated memory with an object header zeroes out the rest.
      */
-    public static void formatArray(Word hub, int size, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
+    public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
         storeWord(memory, 0, markOffset(), prototypeMarkWord);
         storeInt(memory, 0, arrayLengthOffset(), length);
         // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null
         storeWord(memory, 0, hubOffset(), hub);
         if (fillContents) {
-            for (int offset = headerSize; offset < size; offset += wordSize()) {
+            for (int offset = headerSize; offset < allocationSize; offset += wordSize()) {
                 storeWord(memory, 0, offset, Word.zero());
             }
         }
@@ -282,7 +291,7 @@
                 graph.replaceFixedWithFixed(newArrayNode, initializeNode);
             } else if (length != null && belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
                 // Calculate aligned size
-                int size = getArraySize(length, alignment, headerSize, log2ElementSize);
+                int size = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize);
                 ConstantNode sizeNode = ConstantNode.forInt(size, graph);
                 tlabAllocateNode = graph.add(new TLABAllocateNode(sizeNode));
                 graph.addBeforeFixed(newArrayNode, tlabAllocateNode);
@@ -340,7 +349,7 @@
             final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind);
             Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked());
             ValueNode memory = initializeNode.memory();
-            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("size", initializeNode.size()).add("length", initializeNode.length());
+            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length", initializeNode.length());
             SnippetTemplate template = cache.get(key, assumptions);
             Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
             template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Dec 07 23:38:09 2012 +0100
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.stubs;
+
+import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+import static com.oracle.graal.hotspot.snippets.NewObjectSnippets.*;
+import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.snippets.*;
+import com.oracle.graal.snippets.*;
+import com.oracle.graal.snippets.Snippet.ConstantParameter;
+import com.oracle.graal.snippets.Snippet.Parameter;
+import com.oracle.graal.snippets.SnippetTemplate.Key;
+
+/**
+ * Stub implementing the fast path for TLAB refill during instance class allocation.
+ * This stub is called from the {@linkplain NewObjectSnippets inline} allocation
+ * code when TLAB allocation fails. If this stub fails to refill the TLAB
+ * or allocate the object, it calls out to the HotSpot C++ runtime for
+ * to complete the allocation.
+ */
+public class NewArrayStub extends Stub {
+
+    public NewArrayStub(final HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target) {
+        super(runtime, assumptions, target, NewArrayStubCall.NEW_ARRAY);
+    }
+
+    @Override
+    protected void populateKey(Key key) {
+        HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class);
+        Constant intArrayHub = intArrayType.klass();
+        key.add("intArrayHub", intArrayHub);
+    }
+
+    /**
+     * Re-attempts allocation after an initial TLAB allocation failed or was skipped (e.g., due to -XX:-UseTLAB).
+     *
+     * @param hub the hub of the object to be allocated
+     * @param length the length of the array
+     * @param intArrayHub the hub for {@code int[].class}
+     */
+    @Snippet
+    private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub) {
+        int layoutHelper = loadIntFromWord(hub, layoutHelperOffset());
+        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
+        int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
+        int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask();
+        int sizeInBytes = computeArrayAllocationSize(length, wordSize(), headerSize, log2ElementSize);
+        logf("newArray: element kind %d\n", elementKind);
+        logf("newArray: array length %d\n", length);
+        logf("newArray: array size %d\n", sizeInBytes);
+        logf("newArray: hub=%p\n", hub.toLong());
+
+        // check that array length is small enough for fast path.
+        if (length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) {
+            Word memory;
+            if (refillTLAB(intArrayHub, Word.fromLong(tlabIntArrayMarkWord()), tlabAlignmentReserveInHeapWords() * wordSize())) {
+                memory = allocate(sizeInBytes);
+            } else {
+                logf("newArray: allocating directly in eden\n", 0L);
+                memory = edenAllocate(Word.fromInt(sizeInBytes));
+            }
+            if (memory != Word.zero()) {
+                logf("newArray: allocated new array at %p\n", memory.toLong());
+                formatArray(hub, sizeInBytes, length, headerSize, memory, Word.fromLong(arrayPrototypeMarkWord()), true);
+                return verifyOop(memory.toObject());
+            }
+        }
+        logf("newArray: calling new_array_slow", 0L);
+        return verifyOop(NewArraySlowStubCall.call(hub, length));
+    }
+
+    private static final boolean LOGGING_ENABLED = Boolean.getBoolean("graal.logNewArrayStub");
+
+    private static void logf(String format, long value) {
+        if (LOGGING_ENABLED) {
+            Log.printf(format, value);
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri Dec 07 23:38:09 2012 +0100
@@ -35,7 +35,6 @@
 import com.oracle.graal.hotspot.snippets.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
-import com.oracle.graal.snippets.Snippet.Fold;
 import com.oracle.graal.snippets.Snippet.Parameter;
 import com.oracle.graal.snippets.SnippetTemplate.Key;
 
@@ -67,10 +66,10 @@
      */
     @Snippet
     private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub) {
-        logf("newInstance: hub=%p\n", hub.toLong());
+        int sizeInBytes = loadIntFromWord(hub, klassInstanceSizeOffset());
+        logf("newInstance: size %d\n", sizeInBytes);
         if (inlineContiguousAllocationSupported()) {
             if (loadIntFromWord(hub, klassStateOffset()) == klassStateFullyInitialized()) {
-                int sizeInBytes = loadIntFromWord(hub, klassInstanceSizeOffset());
                 Word memory;
                 if (refillTLAB(intArrayHub, Word.fromLong(tlabIntArrayMarkWord()), tlabAlignmentReserveInHeapWords() * wordSize())) {
                     memory = allocate(sizeInBytes);
@@ -102,7 +101,7 @@
      * @param alignmentReserveInBytes the amount of extra bytes to reserve in a new TLAB
      * @return whether or not a new TLAB was allocated
      */
-    private static boolean refillTLAB(Word intArrayHub, Word intArrayMarkWord, int alignmentReserveInBytes) {
+    static boolean refillTLAB(Word intArrayHub, Word intArrayMarkWord, int alignmentReserveInBytes) {
 
         Word thread = thread();
         Word top = loadWordFromWord(thread, threadTlabTopOffset());
@@ -186,7 +185,7 @@
      * @param sizeInBytes the size of the chunk to allocate
      * @return the allocated chunk or {@link Word#zero()} if allocation fails
      */
-    private static Word edenAllocate(Word sizeInBytes) {
+    static Word edenAllocate(Word sizeInBytes) {
         Word heapTopAddress = Word.fromLong(heapTopAddress());
         Word heapEndAddress = Word.fromLong(heapEndAddress());
         logf("edenAllocate: heapTopAddress %p\n", heapTopAddress.toLong());
@@ -223,94 +222,4 @@
             Log.printf(format, value);
         }
     }
-
-    @Fold
-    static int log2WordSize() {
-        return CodeUtil.log2(wordSize());
-    }
-
-    @Fold
-    static int klassStateOffset() {
-        return config().klassStateOffset;
-    }
-
-    @Fold
-    static int klassInstanceSizeOffset() {
-        return config().klassInstanceSizeOffset;
-    }
-
-    @Fold
-    static long heapTopAddress() {
-        return config().heapTopAddress;
-    }
-
-    @Fold
-    static long heapEndAddress() {
-        return config().heapEndAddress;
-    }
-
-    @Fold
-    static int threadTlabStartOffset() {
-        return config().threadTlabStartOffset;
-    }
-
-    @Fold
-    static long tlabIntArrayMarkWord() {
-        return config().tlabIntArrayMarkWord;
-    }
-
-    @Fold
-    static boolean inlineContiguousAllocationSupported() {
-        return config().inlineContiguousAllocationSupported;
-    }
-
-    @Fold
-    static int tlabAlignmentReserveInHeapWords() {
-        return config().tlabAlignmentReserve;
-    }
-
-    @Fold
-    static int threadTlabSizeOffset() {
-        return config().threadTlabSizeOffset;
-    }
-
-    @Fold
-    static int threadAllocatedBytesOffset() {
-        return config().threadAllocatedBytesOffset;
-    }
-
-    @Fold
-    static int klassStateFullyInitialized() {
-        return config().klassStateFullyInitialized;
-    }
-
-    @Fold
-    static int tlabRefillWasteLimitOffset() {
-        return config().tlabRefillWasteLimitOffset;
-    }
-
-    @Fold
-    static int tlabNumberOfRefillsOffset() {
-        return config().tlabNumberOfRefillsOffset;
-    }
-
-    @Fold
-    static int tlabFastRefillWasteOffset() {
-        return config().tlabFastRefillWasteOffset;
-    }
-
-    @Fold
-    static int tlabSlowAllocationsOffset() {
-        return config().tlabSlowAllocationsOffset;
-    }
-
-    @Fold
-    static int tlabRefillWasteIncrement() {
-        return config().tlabRefillWasteIncrement;
-    }
-
-    @Fold
-    static boolean tlabStats() {
-        return config().tlabStats;
-    }
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Fri Dec 07 23:35:23 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Fri Dec 07 23:38:09 2012 +0100
@@ -311,7 +311,7 @@
     }
 
     private void changeToWord(ValueNode valueNode) {
-        assert !(valueNode instanceof ConstantNode);
+        assert !(valueNode instanceof ConstantNode) : "boxed Word constants should not appear in a snippet graph: " + valueNode + ", stamp: " + valueNode.stamp();
         valueNode.setStamp(StampFactory.forKind(wordKind));
 
         // Propagate word kind.
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Dec 07 23:35:23 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Fri Dec 07 23:38:09 2012 +0100
@@ -514,15 +514,6 @@
   return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD));
 C2V_END
 
-C2V_VMENTRY(jlong, getPrototypeMarkWord, (JNIEnv *, jobject, jobject klass))
-  KlassHandle klass_handle(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(klass)));
-  if (klass_handle->oop_is_array()) {
-    return (int32_t)(intptr_t) markOopDesc::prototype();
-  } else {
-    return (jlong) (intptr_t) klass_handle->prototype_header();
-  }
-C2V_END
-
 C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass))
   Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass));
   assert(klass != NULL, "method must not be called for primitive types");
@@ -680,6 +671,15 @@
   set_boolean("tlabStats", TLABStats);
   set_boolean("inlineContiguousAllocationSupported", !CMSIncrementalMode && Universe::heap()->supports_inline_contig_alloc());
 
+  set_long("arrayPrototypeMarkWord", (intptr_t)markOopDesc::prototype());
+  set_int("layoutHelperLog2ElementSizeShift", Klass::_lh_log2_element_size_shift);
+  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);
+  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()));
+
   set_long("debugStub", VmIds::addStub((address)warning));
   set_long("instanceofStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id)));
   set_long("newInstanceStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id)));
@@ -949,7 +949,6 @@
   {CC"lookupReferencedTypeInPool",    CC"("HS_RESOLVED_TYPE"IB)V",                                      FN_PTR(lookupReferencedTypeInPool)},
   {CC"lookupFieldInPool",             CC"("HS_RESOLVED_TYPE"IB)"FIELD,                                  FN_PTR(lookupFieldInPool)},
   {CC"resolveMethod",                 CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD,                     FN_PTR(resolveMethod)},
-  {CC"getPrototypeMarkWord",          CC"("HS_RESOLVED_TYPE")J",                                        FN_PTR(getPrototypeMarkWord)},
   {CC"getInstanceFields",             CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD,                       FN_PTR(getInstanceFields)},
   {CC"isTypeInitialized",             CC"("HS_RESOLVED_TYPE")Z",                                        FN_PTR(isTypeInitialized)},
   {CC"initializeType",                CC"("HS_RESOLVED_TYPE")V",                                        FN_PTR(initializeType)},