Bug 731837 - Fix GC mark time regression from IGC (r=igor,a=lsblakk) FIREFOX_BETA_13_BASE
authorBill McCloskey <wmccloskey@mozilla.com>
Mon, 23 Apr 2012 17:26:35 -0700
changeset 90759 480c0fe7f5919e901a58b5e269f719a1c0b897ff
parent 90758 afbc5301a0f1d9a437e46e21e3bdf728358d3676
child 90760 1a76ee11763b3aa730e6d6010f6c660caa57e8d8
push idunknown
push userunknown
push dateunknown
reviewersigor, lsblakk
bugs731837
milestone13.0a2
Bug 731837 - Fix GC mark time regression from IGC (r=igor,a=lsblakk)
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsgcmark.cpp
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2463,17 +2463,18 @@ MaybeGC(JSContext *cx)
                 GC_NORMAL, gcreason::MAYBEGC);
         return;
     }
 
     if (comp->gcBytes > 8192 &&
         comp->gcBytes >= 3 * (comp->gcTriggerBytes / 4) &&
         rt->gcIncrementalState == NO_INCREMENTAL)
     {
-        GCSlice(cx, NULL, GC_NORMAL, gcreason::MAYBEGC);
+        GCSlice(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL,
+                GC_NORMAL, gcreason::MAYBEGC);
         return;
     }
 
     if (comp->gcMallocAndFreeBytes > comp->gcTriggerMallocAndFreeBytes) {
         GCSlice(cx, rt->gcMode == JSGC_MODE_GLOBAL ? NULL : comp, GC_NORMAL, gcreason::MAYBEGC);
         return;
     }
 
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1852,19 +1852,16 @@ struct GCMarker : public JSTracer {
         JS_ASSERT(!(addr & StackTagMask));
         if (!stack.push(addr | uintptr_t(tag)))
             delayMarkingChildren(ptr);
     }
 
     void pushValueArray(JSObject *obj, void *start, void *end) {
         checkCompartment(obj);
 
-        if (start == end)
-            return;
-
         JS_ASSERT(start <= end);
         uintptr_t tagged = reinterpret_cast<uintptr_t>(obj) | GCMarker::ValueArrayTag;
         uintptr_t startAddr = reinterpret_cast<uintptr_t>(start);
         uintptr_t endAddr = reinterpret_cast<uintptr_t>(end);
 
         /*
          * Push in the reverse order so obj will be on top. If we cannot push
          * the array, we trigger delay marking for the whole object.
@@ -1875,16 +1872,17 @@ struct GCMarker : public JSTracer {
 
     bool isMarkStackEmpty() {
         return stack.isEmpty();
     }
 
     bool restoreValueArray(JSObject *obj, void **vpp, void **endp);
     void saveValueRanges();
     inline void processMarkStackTop(SliceBudget &budget);
+    void processMarkStackOther(uintptr_t tag, uintptr_t addr);
 
     void appendGrayRoot(void *thing, JSGCTraceKind kind);
 
     /* The color is only applied to objects, functions and xml. */
     uint32_t color;
 
     DebugOnly<bool> started;
 
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -896,34 +896,36 @@ GCMarker::saveValueRanges()
             if (obj->getClass() == &ArrayClass) {
                 HeapSlot *vp = obj->getDenseArrayElements();
                 JS_ASSERT(arr->start >= vp &&
                           arr->end == vp + obj->getDenseArrayInitializedLength());
                 arr->index = arr->start - vp;
             } else {
                 HeapSlot *vp = obj->fixedSlots();
                 unsigned nfixed = obj->numFixedSlots();
-                if (arr->start >= vp && arr->start < vp + nfixed) {
+                if (arr->start == arr->end) {
+                    arr->index = obj->slotSpan();
+                } if (arr->start >= vp && arr->start < vp + nfixed) {
                     JS_ASSERT(arr->end == vp + Min(nfixed, obj->slotSpan()));
                     arr->index = arr->start - vp;
                 } else {
                     JS_ASSERT(arr->start >= obj->slots &&
                               arr->end == obj->slots + obj->slotSpan() - nfixed);
                     arr->index = (arr->start - obj->slots) + nfixed;
                 }
             }
             arr->clasp = obj->getClass();
             p[2] |= SavedValueArrayTag;
         } else if (tag == SavedValueArrayTag) {
             p -= 2;
         }
     }
 }
 
-bool
+JS_NEVER_INLINE bool
 GCMarker::restoreValueArray(JSObject *obj, void **vpp, void **endp)
 {
     uintptr_t start = stack.pop();
     js::Class *clasp = reinterpret_cast<js::Class *>(stack.pop());
 
     JS_ASSERT(obj->getClass() == clasp ||
               (clasp == &ArrayClass && obj->getClass() == &SlowArrayClass));
 
@@ -955,16 +957,35 @@ GCMarker::restoreValueArray(JSObject *ob
             *vpp = *endp = obj->slots;
         }
     }
 
     JS_ASSERT(*vpp <= *endp);
     return true;
 }
 
+void
+GCMarker::processMarkStackOther(uintptr_t tag, uintptr_t addr)
+{
+    if (tag == TypeTag) {
+        ScanTypeObject(this, reinterpret_cast<types::TypeObject *>(addr));
+    } else if (tag == SavedValueArrayTag) {
+        JS_ASSERT(!(addr & Cell::CellMask));
+        JSObject *obj = reinterpret_cast<JSObject *>(addr);
+        HeapValue *vp, *end;
+        if (restoreValueArray(obj, (void **)&vp, (void **)&end))
+            pushValueArray(obj, vp, end);
+        else
+            pushObject(obj);
+    } else {
+        JS_ASSERT(tag == XmlTag);
+        MarkChildren(this, reinterpret_cast<JSXML *>(addr));
+    }
+}
+
 inline void
 GCMarker::processMarkStackTop(SliceBudget &budget)
 {
     /*
      * The function uses explicit goto and implements the scanning of the
      * object directly. It allows to eliminate the tail recursion and
      * significantly improve the marking performance, see bug 641025.
      */
@@ -989,41 +1010,22 @@ GCMarker::processMarkStackTop(SliceBudge
     }
 
     if (tag == ObjectTag) {
         obj = reinterpret_cast<JSObject *>(addr);
         JS_COMPARTMENT_ASSERT(runtime, obj);
         goto scan_obj;
     }
 
-    if (tag == TypeTag) {
-        ScanTypeObject(this, reinterpret_cast<types::TypeObject *>(addr));
-    } else if (tag == SavedValueArrayTag) {
-        JS_ASSERT(!(addr & Cell::CellMask));
-        obj = reinterpret_cast<JSObject *>(addr);
-        if (restoreValueArray(obj, (void **)&vp, (void **)&end))
-            goto scan_value_array;
-        else
-            goto scan_obj;
-    } else {
-        JS_ASSERT(tag == XmlTag);
-        MarkChildren(this, reinterpret_cast<JSXML *>(addr));
-    }
-    budget.step();
+    processMarkStackOther(tag, addr);
     return;
 
   scan_value_array:
     JS_ASSERT(vp <= end);
     while (vp != end) {
-        budget.step();
-        if (budget.isOverBudget()) {
-            pushValueArray(obj, vp, end);
-            return;
-        }
-
         const Value &v = *vp++;
         if (v.isString()) {
             JSString *str = v.toString();
             JS_COMPARTMENT_ASSERT_STR(runtime, str);
             if (str->markIfUnmarked())
                 ScanString(this, str);
         } else if (v.isObject()) {
             JSObject *obj2 = &v.toObject();