# HG changeset patch # User Christian Haeubl # Date 1355751390 -3600 # Node ID 80b278b69b5e6a7beb8c8c4b0406eb59d1f230f5 # Parent 26ffe1669cc8226514eba6cd899d8f38c888a322# Parent 885a6849ee9ecd42674025022ca4a421d70f646b Merge. diff -r 26ffe1669cc8 -r 80b278b69b5e 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 Mon Dec 17 14:35:43 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Dec 17 14:36:30 2012 +0100 @@ -238,7 +238,9 @@ /* temps */ null, /* ret */ ret(Kind.Void), /* arg0: format */ arg(0, Kind.Object), - /* arg1: value */ arg(1, Kind.Long)); + /* arg1: value */ arg(1, Kind.Long), + /* arg2: value */ arg(2, Kind.Long), + /* arg3: value */ arg(3, Kind.Long)); addRuntimeCall(LOG_OBJECT, config.logObjectStub, /* temps */ null, diff -r 26ffe1669cc8 -r 80b278b69b5e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Dec 17 14:35:43 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Dec 17 14:36:30 2012 +0100 @@ -33,6 +33,7 @@ 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; @@ -53,7 +54,7 @@ protected void populateKey(Key key) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub); + key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewArrayStub")); } /** @@ -62,43 +63,46 @@ * @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} + * @param log specifies if logging is enabled */ @Snippet - private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub) { + private static Object newArray( + @Parameter("hub") Word hub, + @Parameter("length") int length, + @ConstantParameter("intArrayHub") Word intArrayHub, + @ConstantParameter("log") boolean log) { 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()); + log(log, "newArray: element kind %d\n", elementKind); + log(log, "newArray: array length %d\n", length); + log(log, "newArray: array size %d\n", sizeInBytes); + log(log, "newArray: hub=%p\n", hub.toLong()); // check that array length is small enough for fast path. - if (length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { + if (!forceSlowPath() && length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { Word memory; - if (refillTLAB(intArrayHub, Word.fromLong(tlabIntArrayMarkWord()), tlabAlignmentReserveInHeapWords() * wordSize())) { + if (refillTLAB(intArrayHub, Word.fromLong(tlabIntArrayMarkWord()), tlabAlignmentReserveInHeapWords() * wordSize(), log)) { memory = allocate(sizeInBytes); } else { - logf("newArray: allocating directly in eden\n", 0L); - memory = edenAllocate(Word.fromInt(sizeInBytes)); + log(log, "newArray: allocating directly in eden\n", 0L); + memory = edenAllocate(Word.fromInt(sizeInBytes), log); } if (memory != Word.zero()) { - logf("newArray: allocated new array at %p\n", memory.toLong()); + log(log, "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); + log(log, "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); - } + @Fold + private static boolean forceSlowPath() { + // TODO (ds) make default "false" once refill issue is resolved + return "true".equalsIgnoreCase(System.getProperty("graal.newArrayStub.forceSlowPath", "true")); } } diff -r 26ffe1669cc8 -r 80b278b69b5e 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 Mon Dec 17 14:35:43 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Dec 17 14:36:30 2012 +0100 @@ -34,8 +34,7 @@ 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.Snippet.*; import com.oracle.graal.snippets.SnippetTemplate.Key; /** @@ -55,7 +54,7 @@ protected void populateKey(Key key) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub); + key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewInstanceStub")); } /** @@ -65,20 +64,20 @@ * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub) { + private static Object newInstance( + @Parameter("hub") Word hub, + @ConstantParameter("intArrayHub") Word intArrayHub, + @ConstantParameter("log") boolean log) { int sizeInBytes = loadIntFromWord(hub, klassInstanceSizeOffset()); - logf("newInstance: size %d\n", sizeInBytes); - if (inlineContiguousAllocationSupported()) { + if (!forceSlowPath() && inlineContiguousAllocationSupported()) { if (loadIntFromWord(hub, klassStateOffset()) == klassStateFullyInitialized()) { Word memory; - if (refillTLAB(intArrayHub, Word.fromLong(tlabIntArrayMarkWord()), tlabAlignmentReserveInHeapWords() * wordSize())) { + if (refillTLAB(intArrayHub, Word.fromLong(tlabIntArrayMarkWord()), tlabAlignmentReserveInHeapWords() * wordSize(), log)) { memory = allocate(sizeInBytes); } else { - logf("newInstance: allocating directly in eden\n", 0L); - memory = edenAllocate(Word.fromInt(sizeInBytes)); + memory = edenAllocate(Word.fromInt(sizeInBytes), log); } if (memory != Word.zero()) { - logf("newInstance: allocated new object at %p\n", memory.toLong()); Word prototypeMarkWord = loadWordFromWord(hub, prototypeMarkWordOffset()); storeWord(memory, 0, markOffset(), prototypeMarkWord); storeWord(memory, 0, hubOffset(), hub); @@ -89,7 +88,6 @@ } } } - logf("newInstance: calling new_instance_slow", 0L); return verifyOop(NewInstanceSlowStubCall.call(hub)); } @@ -99,9 +97,10 @@ * @param intArrayHub the hub for {@code int[].class} * @param intArrayMarkWord the mark word for the int array placed in the left over TLAB space * @param alignmentReserveInBytes the amount of extra bytes to reserve in a new TLAB + * @param log specifies if logging is enabled * @return whether or not a new TLAB was allocated */ - static boolean refillTLAB(Word intArrayHub, Word intArrayMarkWord, int alignmentReserveInBytes) { + static boolean refillTLAB(Word intArrayHub, Word intArrayMarkWord, int alignmentReserveInBytes, boolean log) { Word thread = thread(); Word top = loadWordFromWord(thread, threadTlabTopOffset()); @@ -110,24 +109,26 @@ // calculate amount of free space Word tlabFreeSpaceInBytes = end.minus(top); - logf("refillTLAB: thread=%p\n", thread.toLong()); - logf("refillTLAB: top=%p\n", top.toLong()); - logf("refillTLAB: end=%p\n", end.toLong()); - logf("refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes.toLong()); + log(log, "refillTLAB: thread=%p\n", thread.toLong()); + log(log, "refillTLAB: top=%p\n", top.toLong()); + log(log, "refillTLAB: end=%p\n", end.toLong()); + log(log, "refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes.toLong()); // a DIV or SHR operations on Words would be handy here... Word tlabFreeSpaceInWords = Word.fromLong(tlabFreeSpaceInBytes.toLong() >>> log2WordSize()); // Retain TLAB and allocate object in shared space if // the amount free in the TLAB is too large to discard. - if (tlabFreeSpaceInWords.belowOrEqual(loadWordFromWord(thread, tlabRefillWasteLimitOffset()))) { - logf("refillTLAB: discarding TLAB\n", 0L); - + Word refillWasteLimit = loadWordFromWord(thread, tlabRefillWasteLimitOffset()); + if (tlabFreeSpaceInWords.belowOrEqual(refillWasteLimit)) { if (tlabStats()) { // increment number of refills storeInt(thread, 0, tlabNumberOfRefillsOffset(), loadIntFromWord(thread, tlabNumberOfRefillsOffset()) + 1); + log(log, "thread: %p -- number_of_refills %d\n", thread.toLong(), loadIntFromWord(thread, tlabNumberOfRefillsOffset())); // accumulate wastage - storeWord(thread, 0, tlabFastRefillWasteOffset(), loadWordFromWord(thread, tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords)); + Word wastage = loadWordFromWord(thread, tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords); + log(log, "thread: %p -- accumulated wastage %d\n", thread.toLong(), wastage.toLong()); + storeWord(thread, 0, tlabFastRefillWasteOffset(), wastage); } // if TLAB is currently allocated (top or end != null) then @@ -137,9 +138,6 @@ // just like the HotSpot assembler stubs, assumes that tlabFreeSpaceInInts fits in an int int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes.toLong() >>> 2; int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts; - logf("refillTLAB: alignmentReserveInBytes %d\n", alignmentReserveInBytes); - logf("refillTLAB: headerSize %d\n", headerSize); - logf("refillTLAB: filler.length %d\n", length); NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false); Word allocated = loadWordFromWord(thread, threadAllocatedBytesOffset()); @@ -151,25 +149,22 @@ Word tlabRefillSizeInWords = loadWordFromWord(thread, threadTlabSizeOffset()); Word tlabRefillSizeInBytes = Word.fromLong(tlabRefillSizeInWords.toLong() * wordSize()); // allocate new TLAB, address returned in top - top = edenAllocate(tlabRefillSizeInBytes); + top = edenAllocate(tlabRefillSizeInBytes, log); if (top != Word.zero()) { storeWord(thread, 0, threadTlabStartOffset(), top); storeWord(thread, 0, threadTlabTopOffset(), top); end = top.plus(tlabRefillSizeInBytes.minus(alignmentReserveInBytes)); storeWord(thread, 0, threadTlabEndOffset(), end); - logf("refillTLAB: top'=%p\n", top.toLong()); - logf("refillTLAB: start'=%p\n", top.toLong()); - logf("refillTLAB: end'=%p\n", end.toLong()); return true; } else { return false; } } else { // Retain TLAB - Word newRefillWasteLimit = loadWordFromWord(thread, tlabRefillWasteLimitOffset()).plus(tlabRefillWasteIncrement()); + Word newRefillWasteLimit = refillWasteLimit.plus(tlabRefillWasteIncrement()); storeWord(thread, 0, tlabRefillWasteLimitOffset(), newRefillWasteLimit); - logf("refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.toLong()); + log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.toLong()); if (tlabStats()) { storeInt(thread, 0, tlabSlowAllocationsOffset(), loadIntFromWord(thread, tlabSlowAllocationsOffset()) + 1); @@ -183,43 +178,49 @@ * Attempts to allocate a chunk of memory from Eden space. * * @param sizeInBytes the size of the chunk to allocate + * @param log specifies if logging is enabled * @return the allocated chunk or {@link Word#zero()} if allocation fails */ - static Word edenAllocate(Word sizeInBytes) { + static Word edenAllocate(Word sizeInBytes, boolean log) { Word heapTopAddress = Word.fromLong(heapTopAddress()); Word heapEndAddress = Word.fromLong(heapEndAddress()); - logf("edenAllocate: heapTopAddress %p\n", heapTopAddress.toLong()); - logf("edenAllocate: heapEndAddress %p\n", heapEndAddress.toLong()); while (true) { Word heapTop = loadWordFromWord(heapTopAddress, 0); Word newHeapTop = heapTop.plus(sizeInBytes); - logf("edenAllocate: heapTop %p\n", heapTop.toLong()); - logf("edenAllocate: newHeapTop %p\n", newHeapTop.toLong()); if (newHeapTop.belowOrEqual(heapTop)) { - logf("edenAllocate: fail 1\n", 0L); return Word.zero(); } Word heapEnd = loadWordFromWord(heapEndAddress, 0); - logf("edenAllocate: heapEnd %p\n", heapEnd.toLong()); if (newHeapTop.above(heapEnd)) { - logf("edenAllocate: fail 2\n", 0L); return Word.zero(); } if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop) == heapTop) { - logf("edenAllocate: success %p\n", heapTop.toLong()); return heapTop; } } } - private static final boolean LOGGING_ENABLED = Boolean.getBoolean("graal.logNewInstanceStub"); + @Fold + private static boolean forceSlowPath() { + return Boolean.getBoolean("graal.newInstanceStub.forceSlowPath"); + } - private static void logf(String format, long value) { - if (LOGGING_ENABLED) { + static void log(boolean enabled, String format, long value) { + if (enabled) { Log.printf(format, value); } } + static void log(boolean enabled, String format, long v1, long v2) { + if (enabled) { + Log.printf(format, v1, v2); + } + } + static void log(boolean enabled, String format, long v1, long v2, long v3) { + if (enabled) { + Log.printf(format, v1, v2, v3); + } + } } diff -r 26ffe1669cc8 -r 80b278b69b5e graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java Mon Dec 17 14:35:43 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java Mon Dec 17 14:36:30 2012 +0100 @@ -39,7 +39,7 @@ public static final Descriptor LOG_PRIMITIVE = new Descriptor("logPrimitive", false, Kind.Void, Kind.Int, Kind.Long, Kind.Boolean); public static final Descriptor LOG_OBJECT = new Descriptor("logObject", false, Kind.Void, Kind.Object, Kind.Int); - public static final Descriptor LOG_PRINTF = new Descriptor("logPrintf", false, Kind.Void, Kind.Object, Kind.Long); + public static final Descriptor LOG_PRINTF = new Descriptor("logPrintf", false, Kind.Void, Kind.Object, Kind.Long, Kind.Long, Kind.Long); // Note: Must be kept in sync with constants in c1_Runtime1.hpp private static final int LOG_OBJECT_NEWLINE = 0x01; @@ -53,7 +53,7 @@ private static native void log(@ConstantNodeParameter Descriptor logPrimitive, int typeChar, long value, boolean newline); @NodeIntrinsic(RuntimeCallNode.class) - private static native void printf(@ConstantNodeParameter Descriptor logPrintf, String format, long value); + private static native void printf(@ConstantNodeParameter Descriptor logPrintf, String format, long v1, long v2, long v3); public static void print(boolean value) { log(LOG_PRIMITIVE, Kind.Boolean.getTypeChar(), value ? 1L : 0L, false); @@ -84,9 +84,16 @@ * * @param format a C style printf format value that can contain at most one conversion specifier (i.e., a sequence * of characters starting with '%'). + * @param value the value associated with the conversion specifier */ public static void printf(String format, long value) { - printf(LOG_PRINTF, format, value); + printf(LOG_PRINTF, format, value, 0L, 0L); + } + public static void printf(String format, long v1, long v2) { + printf(LOG_PRINTF, format, v1, v2, 0L); + } + public static void printf(String format, long v1, long v2, long v3) { + printf(LOG_PRINTF, format, v1, v2, v3); } public static void print(float value) { diff -r 26ffe1669cc8 -r 80b278b69b5e src/cpu/x86/vm/graalRuntime_x86.cpp --- a/src/cpu/x86/vm/graalRuntime_x86.cpp Mon Dec 17 14:35:43 2012 +0100 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Mon Dec 17 14:36:30 2012 +0100 @@ -186,6 +186,36 @@ return call_RT(oop_result1, metadata_result, entry, 3); } +int GraalStubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3, Register arg4) { +#ifdef _LP64 + // if there is any conflict use the stack + if (arg1 == c_rarg2 || arg1 == c_rarg3 || arg1 == c_rarg4 || + arg2 == c_rarg1 || arg2 == c_rarg3 || arg2 == c_rarg4 || + arg3 == c_rarg1 || arg3 == c_rarg2 || arg3 == c_rarg4 || + arg4 == c_rarg1 || arg4 == c_rarg2 || arg4 == c_rarg3) { + push(arg4); + push(arg3); + push(arg2); + push(arg1); + pop(c_rarg1); + pop(c_rarg2); + pop(c_rarg3); + pop(c_rarg4); + } else { + mov(c_rarg1, arg1); + mov(c_rarg2, arg2); + mov(c_rarg3, arg3); + mov(c_rarg4, arg4); + } +#else + push(arg4); + push(arg3); + push(arg2); + push(arg1); +#endif // _LP64 + return call_RT(oop_result1, metadata_result, entry, 4); +} + // Implementation of GraalStubFrame class GraalStubFrame: public StackObj { @@ -1022,7 +1052,7 @@ __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_log_printf, j_rarg0, j_rarg1, j_rarg2); + int call_offset = __ call_RT(noreg, noreg, (address)graal_log_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); diff -r 26ffe1669cc8 -r 80b278b69b5e src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Mon Dec 17 14:35:43 2012 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Mon Dec 17 14:36:30 2012 +0100 @@ -551,11 +551,11 @@ report_vm_error(__FILE__, __LINE__, error_msg, detail_msg); JRT_END -JRT_ENTRY(void, GraalRuntime::graal_log_printf(JavaThread* thread, oop format, jlong val)) +JRT_ENTRY(void, GraalRuntime::graal_log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3)) ResourceMark rm; assert(format != NULL && java_lang_String::is_instance(format), "must be"); char *buf = java_lang_String::as_utf8_string(format); - tty->print(buf, val); + tty->print(buf, v1, v2, v3); JRT_END JRT_ENTRY(void, GraalRuntime::graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) diff -r 26ffe1669cc8 -r 80b278b69b5e src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Mon Dec 17 14:35:43 2012 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Mon Dec 17 14:36:30 2012 +0100 @@ -70,6 +70,7 @@ int call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1); int call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2); int call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3); + int call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3, Register arg4); }; // set frame size and return address offset to these values in blobs @@ -144,7 +145,7 @@ static void graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock); static void graal_monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); static void graal_vm_error(JavaThread* thread, oop where, oop format, jlong value); - static void graal_log_printf(JavaThread* thread, oop format, jlong value); + static void graal_log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); static void graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); static jint graal_identity_hash_code(JavaThread* thread, oopDesc* objd); diff -r 26ffe1669cc8 -r 80b278b69b5e src/share/vm/memory/threadLocalAllocBuffer.cpp --- a/src/share/vm/memory/threadLocalAllocBuffer.cpp Mon Dec 17 14:35:43 2012 +0100 +++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp Mon Dec 17 14:36:30 2012 +0100 @@ -92,8 +92,9 @@ global_stats()->update_fast_refill_waste(_fast_refill_waste); } else { + // (ds) _gc_waste can be non-zero (see above) even if _number_of_refills is 0 assert(_number_of_refills == 0 && _fast_refill_waste == 0 && - _slow_refill_waste == 0 && _gc_waste == 0, + _slow_refill_waste == 0/* && _gc_waste == 0*/, "tlab stats == 0"); } global_stats()->update_slow_allocations(_slow_allocations);