changeset 7242:80b278b69b5e

Merge.
author Christian Haeubl <haeubl@ssw.jku.at>
date Mon, 17 Dec 2012 14:36:30 +0100
parents 26ffe1669cc8 (current diff) 885a6849ee9e (diff)
children 4979267ab857
files
diffstat 8 files changed, 114 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- 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,
--- 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"));
     }
 }
--- 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);
+        }
+    }
 }
--- 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) {
--- 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();
--- 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))
--- 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);
--- 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);