Bug 731837 - Fix GC mark time regression from IGC (r=igor,a=tracking-firefox)
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 17 Apr 2012 12:40:30 -0700
changeset 91892 c80635a1c62f6bb7c6f555f5edb2282aa4a616a9
parent 91883 6b917c007510a7c4f7c75d542a9419bbf396c80a
child 91893 36c22a5ddbe5d92cc55d0fbbcbf827cc4ad02067
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersigor, tracking-firefox
bugs731837
milestone14.0a1
Bug 731837 - Fix GC mark time regression from IGC (r=igor,a=tracking-firefox)
js/src/jsgc.h
js/src/jsgcmark.cpp
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1855,19 +1855,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.
@@ -1878,16 +1875,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
@@ -913,17 +913,19 @@ 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();
+                } else 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;
                 }
             }
@@ -972,16 +974,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.
      */
@@ -1006,41 +1027,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();