# HG changeset patch # User Doug Simon # Date 1354919889 -3600 # Node ID 88d626e2c2a8d57c68bc9465707f4b5103e9e92e # Parent 8c02d320a1acb149c13c403b3b6bf2f256fec9e3 added TLAB fast refill stub for array allocation diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- 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)); diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- 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; diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- 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); } diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- 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); } diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- 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 diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- 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 runtimeCalls = new HashMap<>(); private final Map 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() { diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java --- 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); } diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java --- /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); +} diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java --- 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 { diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java --- 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; diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java --- 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); diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- /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); + } + } +} diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- 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; - } } diff -r 8c02d320a1ac -r 88d626e2c2a8 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java --- 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. diff -r 8c02d320a1ac -r 88d626e2c2a8 src/share/vm/graal/graalCompilerToVM.cpp --- 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)},