[MLton-commit] r6442

spoons at mlton.org spoons at mlton.org
Mon Mar 3 07:27:16 PST 2008


Support processor-local array allocation.

Array allocation has a special path in the runtime (since arrays
may be allocated directly into the older generation).  This change
reorganizes the code so that in cases where an array would be
allocated in the nursery, the runtime avoids taking a global lock.

----------------------------------------------------------------------

U   mlton/branches/shared-heap-multicore/runtime/gc/array-allocate.c

----------------------------------------------------------------------

Modified: mlton/branches/shared-heap-multicore/runtime/gc/array-allocate.c
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/gc/array-allocate.c	2008-03-03 15:26:28 UTC (rev 6441)
+++ mlton/branches/shared-heap-multicore/runtime/gc/array-allocate.c	2008-03-03 15:27:16 UTC (rev 6442)
@@ -18,11 +18,12 @@
   pointer frontier;
   pointer last;
   pointer result;
+  bool holdLock;
 
   splitHeader(s, header, NULL, NULL, &bytesNonObjptrs, &numObjptrs);
-  if (DEBUG)
-    fprintf (stderr, "GC_arrayAllocate (%zu, "FMTARRLEN", "FMTHDR")\n",
-             ensureBytesFree, numElements, header);
+  if (DEBUG or s->controls->messages)
+    fprintf (stderr, "GC_arrayAllocate (%zu, "FMTARRLEN", "FMTHDR") [%d]\n",
+             ensureBytesFree, numElements, header, Proc_processorNumber (s));
   bytesPerElement = bytesNonObjptrs + (numObjptrs * OBJPTR_SIZE);
   arraySizeMax =
     (uintmax_t)bytesPerElement * (uintmax_t)numElements + GC_ARRAY_HEADER_SIZE;
@@ -47,30 +48,47 @@
              uintmaxToCommaString(arraySize),
              uintmaxToCommaString(arraySizeAligned),
              uintmaxToCommaString(ensureBytesFree));
-  if (arraySizeAligned >= s->controls.oldGenArraySize) {
+
+  /* Determine whether we will perform this allocation locally or not */
+  holdLock = arraySizeAligned >= s->controls->oldGenArraySize;
+
+  if (holdLock) {
+    /* Global alloc */
+    s->syncReason = SYNC_OLD_GEN_ARRAY;
+    ENTER0 (s);
     if (not hasHeapBytesFree (s, arraySizeAligned, ensureBytesFree)) {
-      enter (s);
       performGC (s, arraySizeAligned, ensureBytesFree, FALSE, TRUE);
-      leave (s);
     }
-    frontier = s->heap.start + s->heap.oldGenSize;
-    s->heap.oldGenSize += arraySizeAligned;
-    s->cumulativeStatistics.bytesAllocated += arraySizeAligned;
+    assert (hasHeapBytesFree (s, arraySizeAligned, ensureBytesFree));
+    frontier = s->heap->start + s->heap->oldGenSize;
+    assert (isFrontierAligned (s, frontier));
+
+    /* This must be updated while holding the lock! */
+    s->heap->oldGenSize += arraySizeAligned;
+    assert (s->heap->start + s->heap->oldGenSize <= s->heap->nursery);
+    s->cumulativeStatistics->bytesAllocated += arraySizeAligned;
+    /* NB LEAVE appears below since no heap invariant holds while the
+       oldGenSize has been updated but the array remains uninitialized. */
   } else {
+    /* Local alloc */
     size_t bytesRequested;
     pointer newFrontier;
 
     bytesRequested = arraySizeAligned + ensureBytesFree;
     if (not hasHeapBytesFree (s, 0, bytesRequested)) {
-      enter (s);
-      performGC (s, 0, bytesRequested, FALSE, TRUE);
-      leave (s);
+      /* Local alloc may still require getting the lock, but we will release
+         it before initialization. */
+      ensureHasHeapBytesFreeAndOrInvariantForMutator (s, FALSE, FALSE, FALSE,
+                                                      0, bytesRequested);
     }
+    assert (hasHeapBytesFree (s, 0, bytesRequested));
     frontier = s->frontier;
     newFrontier = frontier + arraySizeAligned;
     assert (isFrontierAligned (s, newFrontier));
     s->frontier = newFrontier;
   }
+
+  /* Now do the initialization */
   last = frontier + arraySize;
   *((GC_arrayCounter*)(frontier)) = 0;
   frontier = frontier + GC_ARRAY_COUNTER_SIZE;
@@ -106,8 +124,8 @@
   }
   GC_profileAllocInc (s, arraySizeAligned);
   if (DEBUG_ARRAY) {
-    fprintf (stderr, "GC_arrayAllocate done.  result = "FMTPTR"  frontier = "FMTPTR"\n",
-             (uintptr_t)result, (uintptr_t)s->frontier);
+    fprintf (stderr, "GC_arrayAllocate done.  result = "FMTPTR"  frontier = "FMTPTR" [%d]\n",
+             (uintptr_t)result, (uintptr_t)s->frontier, Proc_processorNumber (s));
     displayGCState (s, stderr);
   }
   assert (ensureBytesFree <= (size_t)(s->limitPlusSlop - s->frontier));
@@ -115,5 +133,10 @@
    * unless we did the GC, we never set s->currentThread->stack->used
    * to reflect what the mutator did with stackTop.
    */
+
+  if (holdLock) {
+    LEAVE1 (s, result);
+  }
+
   return result;
 }       




More information about the MLton-commit mailing list