Bug 1001159 (part 5) - Simplify FreeSpan computation in Arena::finalize(). r=billm.
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 29 Apr 2014 18:03:22 -0700
changeset 181542 be78a818fbd829f11b173a37a66d0c8e6ec6dd40
parent 181541 91b0fd14307e557b663a6e61572a9d831ad2077f
child 181543 5a056bb6be0cec7653834cee6ec0f50e4935cde3
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersbillm
bugs1001159
milestone32.0a1
Bug 1001159 (part 5) - Simplify FreeSpan computation in Arena::finalize(). r=billm.
js/src/jsgc.cpp
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -439,83 +439,79 @@ Arena::finalize(FreeOp *fop, AllocKind t
     JS_ASSERT(aheader.allocated());
     JS_ASSERT(thingKind == aheader.getAllocKind());
     JS_ASSERT(thingSize == aheader.getThingSize());
     JS_ASSERT(!aheader.hasDelayedMarking);
     JS_ASSERT(!aheader.markOverflow);
     JS_ASSERT(!aheader.allocatedDuringIncremental);
 
     uintptr_t thing = thingsStart(thingKind);
+    uintptr_t firstThingOrSuccessorOfLastMarkedThing = thing;
     uintptr_t lastByte = thingsEnd() - 1;
 
     FreeSpan nextFree(aheader.getFirstFreeSpan());
     nextFree.checkSpan();
 
     FreeSpan newListHead;
     FreeSpan *newListTail = &newListHead;
-    uintptr_t newFreeSpanStart = 0;
     size_t nmarked = 0;
     for (;; thing += thingSize) {
         JS_ASSERT(thing <= lastByte + 1);
         if (thing == nextFree.first) {
             JS_ASSERT(nextFree.last <= lastByte);
             if (nextFree.last == lastByte)
                 break;
             JS_ASSERT(Arena::isAligned(nextFree.last, thingSize));
-            if (!newFreeSpanStart)
-                newFreeSpanStart = thing;
             thing = nextFree.last;
             nextFree = *nextFree.nextSpan();
             nextFree.checkSpan();
         } else {
             T *t = reinterpret_cast<T *>(thing);
             if (t->isMarked()) {
-                nmarked++;
-                if (newFreeSpanStart) {
-                    JS_ASSERT(thing >= thingsStart(thingKind) + thingSize);
-                    newListTail->first = newFreeSpanStart;
+                if (thing != firstThingOrSuccessorOfLastMarkedThing) {
+                    // We just finished passing over one or more free things,
+                    // so record a new FreeSpan.
+                    newListTail->first = firstThingOrSuccessorOfLastMarkedThing;
                     newListTail->last = thing - thingSize;
                     newListTail = newListTail->nextSpanUnchecked(thingSize);
-                    newFreeSpanStart = 0;
                 }
+                firstThingOrSuccessorOfLastMarkedThing = thing + thingSize;
+                nmarked++;
             } else {
-                if (!newFreeSpanStart)
-                    newFreeSpanStart = thing;
                 t->finalize(fop);
                 JS_POISON(t, JS_SWEPT_TENURED_PATTERN, thingSize);
             }
         }
     }
 
+    // Complete the last FreeSpan.
+    newListTail->first = firstThingOrSuccessorOfLastMarkedThing;
+    newListTail->last = lastByte;
+
     if (nmarked == 0) {
         JS_ASSERT(newListTail == &newListHead);
-        JS_ASSERT(!newFreeSpanStart ||
-                  newFreeSpanStart == thingsStart(thingKind));
+        JS_ASSERT(newListTail->first == thingsStart(thingKind));
         JS_EXTRA_POISON(data, JS_SWEPT_TENURED_PATTERN, sizeof(data));
         return true;
     }
 
-    newListTail->first = newFreeSpanStart ? newFreeSpanStart : nextFree.first;
-    JS_ASSERT(Arena::isAligned(newListTail->first, thingSize));
-    newListTail->last = lastByte;
-
 #ifdef DEBUG
     size_t nfree = 0;
     for (const FreeSpan *span = &newListHead; span != newListTail; span = span->nextSpan()) {
         span->checkSpan();
         JS_ASSERT(Arena::isAligned(span->first, thingSize));
         JS_ASSERT(Arena::isAligned(span->last, thingSize));
         nfree += (span->last - span->first) / thingSize + 1;
-        JS_ASSERT(nfree + nmarked <= thingsPerArena(thingSize));
     }
+    JS_ASSERT(Arena::isAligned(newListTail->first, thingSize));
+    JS_ASSERT(newListTail->last == lastByte);
     nfree += (newListTail->last + 1 - newListTail->first) / thingSize;
     JS_ASSERT(nfree + nmarked == thingsPerArena(thingSize));
 #endif
     aheader.setFirstFreeSpan(&newListHead);
-
     return false;
 }
 
 /*
  * Insert an arena into the list in appropriate position and update the cursor
  * to ensure that any arena before the cursor is full.
  */
 void ArenaList::insert(ArenaHeader *a)