Mercurial > hg > graal-compiler
changeset 14101:2ec05c3f773b
fix overzeroing of new storage, refactor zeroing and unroll zeroing of small arrays
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Thu, 06 Mar 2014 18:41:42 -0800 |
parents | 8c376c174030 |
children | 43a80ad2730a |
files | graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/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.word/src/com/oracle/graal/word/Pointer.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java |
diffstat | 5 files changed, 75 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Thu Mar 06 16:24:47 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Thu Mar 06 18:41:42 2014 -0800 @@ -139,7 +139,7 @@ if (useTLAB() && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, false); - result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize); + result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, false); } else { new_stub.inc(); result = NewInstanceStubCall.call(hub); @@ -176,16 +176,16 @@ @Snippet public static Object allocateArray(Word hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter String typeContext) { + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { // This handles both negative array sizes and very large array sizes DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, typeContext); + return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext); } private static Object allocateArrayImpl(Word hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, @ConstantParameter Register threadRegister, - String typeContext) { + @ConstantParameter boolean maybeUnroll, String typeContext) { Object result; int alignment = wordSize(); int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); @@ -197,7 +197,7 @@ writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, true); newarray_loopInit.inc(); - result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents); + result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll); } else { newarray_stub.inc(); result = NewArrayStubCall.call(hub, length); @@ -244,7 +244,7 @@ int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, "dynamic type"); + return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type"); } /** @@ -277,35 +277,81 @@ } /** - * Maximum size of an object whose body is initialized by a sequence of zero-stores to its - * fields. Larger objects have their bodies initialized in a loop. + * Maximum number of long stores to emit when zeroing an object with a constant size Larger + * objects have their bodies initialized in a loop. */ - private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize(); + private static final int MAX_UNROLLED_OBJECT_ZEROING_STORES = 8; /** - * Formats some allocated memory with an object header zeroes out the rest. + * Zero uninitialized memory in a newly allocated object, unrolling as necessary and ensuring + * that stores are aligned. + * + * @param size number of bytes to zero + * @param memory beginning of object which is being zeroed + * @param constantSize is @ size} known to be constant in the snippet + * @param startOffset offset to begin zeroing. May not be word aligned. + * @param manualUnroll maximally unroll zeroing */ - private static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize) { - Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; - initializeObjectHeader(memory, prototypeMarkWord, hub); - if (fillContents) { - if (constantSize && size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) { + private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean noAsserts) { + assert noAsserts || size % 8 == 0 : "unaligned object size"; + int offset = startOffset; + if (offset % 8 != 0) { + memory.writeInt(offset, 0, INIT_LOCATION); + offset += 4; + } + assert noAsserts || offset % 8 == 0 : "unaligned"; + if (manualUnroll && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { + assert noAsserts || !constantSize : "size shouldn't be constant at instantiation time"; + // This case handles arrays of constant length. Instead of having a snippet variant for + // each length, generate a chain of stores of maximum length. Once it's inlined the + // break statement will trim excess stores. + new_seqInit.inc(); + explodeLoop(); + for (int i = 0; i < MAX_UNROLLED_OBJECT_ZEROING_STORES; i++, offset += 8) { + if (offset == size) { + break; + } + memory.initializeLong(offset, 0, INIT_LOCATION); + } + } else { + // Use Word instead of int to avoid extension to long in generated code + Word off = Word.signed(offset); + if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { new_seqInit.inc(); explodeLoop(); } else { new_loopInit.inc(); } - for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) { - memory.initializeWord(offset, Word.zero(), INIT_LOCATION); + for (; off.rawValue() < size; off = off.add(8)) { + memory.initializeLong(off, 0, INIT_LOCATION); } } + } + + /** + * Formats some allocated memory with an object header and zeroes out the rest. Disables asserts + * since they can't be compiled in stubs. + */ + public static Object formatObjectForStub(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord) { + return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, true); + } + + /** + * Formats some allocated memory with an object header and zeroes out the rest. + */ + private static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean noAsserts) { + Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; + initializeObjectHeader(memory, prototypeMarkWord, hub); + if (fillContents) { + zeroMemory(size, memory, constantSize, instanceHeaderSize(), false, noAsserts); + } return memory.toObject(); } /** * Formats some allocated memory with an object header and zeroes out the rest. */ - public static Object formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { + public static Object formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll) { memory.writeInt(arrayLengthOffset(), length, INIT_LOCATION); /* * store hub last as the concurrent garbage collectors assume length is valid if hub field @@ -313,9 +359,7 @@ */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { - memory.initializeWord(offset, Word.zero(), INIT_LOCATION); - } + zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, true); } return memory.toObject(); } @@ -377,6 +421,7 @@ args.addConst("log2ElementSize", log2ElementSize); args.addConst("fillContents", newArrayNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); + args.addConst("maybeUnroll", newArrayNode.length().isConstant()); args.addConst("typeContext", ProfileAllocations.getValue() ? toJavaName(arrayType, false) : ""); SnippetTemplate template = template(args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Thu Mar 06 16:24:47 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Thu Mar 06 18:41:42 2014 -0800 @@ -110,7 +110,7 @@ if (logging()) { printf("newArray: allocated new array at %p\n", memory.rawValue()); } - return verifyObject(formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true)); + return verifyObject(formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true, false)); } } if (logging()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Thu Mar 06 16:24:47 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Thu Mar 06 18:41:42 2014 -0800 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; @@ -111,10 +110,7 @@ Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); if (memory.notEqual(0)) { Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - initializeObjectHeader(memory, prototypeMarkWord, hub); - for (int offset = instanceHeaderSize(); offset < sizeInBytes; offset += wordSize()) { - memory.writeWord(offset, Word.zero(), ANY_LOCATION); - } + NewObjectSnippets.formatObjectForStub(hub, sizeInBytes, memory, prototypeMarkWord); return verifyObject(memory.toObject()); } } @@ -192,7 +188,7 @@ // an int int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes >>> 2; int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts; - NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false); + NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false, false); long allocated = thread.readLong(threadAllocatedBytesOffset(), TLAB_THREAD_ALLOCATED_BYTES_LOCATION); allocated = allocated + top.subtract(readTlabStart(thread)).rawValue();
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Thu Mar 06 16:24:47 2014 -0800 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Thu Mar 06 18:41:42 2014 -0800 @@ -377,7 +377,7 @@ * @param locationIdentity the identity of the write (see {@link LocationNode}) * @param val the value to be written to memory */ - void initializeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity); + void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity); /** * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in @@ -481,7 +481,7 @@ * @param locationIdentity the identity of the write (see {@link LocationNode}) * @param val the value to be written to memory */ - void initializeWord(int offset, WordBase val, LocationIdentity locationIdentity); + void initializeLong(int offset, long val, LocationIdentity locationIdentity); /** * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Thu Mar 06 16:24:47 2014 -0800 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Thu Mar 06 18:41:42 2014 -0800 @@ -788,8 +788,8 @@ @Override @Operation(opcode = Opcode.INITIALIZE) - public void initializeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity) { - unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox()); + public void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity) { + unsafe.putLong(add((Word) offset).unbox(), val); } @Override @@ -846,8 +846,8 @@ @Override @Operation(opcode = Opcode.INITIALIZE) - public void initializeWord(int offset, WordBase val, LocationIdentity locationIdentity) { - initializeWord(signed(offset), val, locationIdentity); + public void initializeLong(int offset, long val, LocationIdentity locationIdentity) { + initializeLong(signed(offset), val, locationIdentity); } @Override