Bug 755604 - Incrementalize JSCompartment::markTypes. r=billm
authorTill Schneidereit <tschneidereit@gmail.com>
Fri, 18 May 2012 13:35:43 -0400
changeset 98444 5232403e7b8f64b31d87b81b7b03570ec42af441
parent 98443 c3a321bf58ceda57d9985d87202bf0613f9cfe2e
child 98445 1e18c991b40c153406df36671984501f9c28b994
push id1116
push userlsblakk@mozilla.com
push dateMon, 16 Jul 2012 19:38:18 +0000
treeherdermozilla-beta@95f959a8b4dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs755604
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 755604 - Incrementalize JSCompartment::markTypes. r=billm
js/src/gc/Marking.cpp
js/src/jscompartment.cpp
js/src/jsgc.h
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -983,29 +983,59 @@ GCMarker::restoreValueArray(JSObject *ob
         }
     }
 
     JS_ASSERT(*vpp <= *endp);
     return true;
 }
 
 void
-GCMarker::processMarkStackOther(uintptr_t tag, uintptr_t addr)
+GCMarker::processMarkStackOther(SliceBudget &budget, 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 if (tag == ArenaTag) {
+        ArenaHeader *aheader = reinterpret_cast<ArenaHeader *>(addr);
+        AllocKind thingKind = aheader->getAllocKind();
+        size_t thingSize = Arena::thingSize(thingKind);
+
+        for ( ; aheader; aheader = aheader->next) {
+            Arena *arena = aheader->getArena();
+            FreeSpan firstSpan(aheader->getFirstFreeSpan());
+            const FreeSpan *span = &firstSpan;
+
+            for (uintptr_t thing = arena->thingsStart(thingKind); ; thing += thingSize) {
+                JS_ASSERT(thing <= arena->thingsEnd());
+                if (thing == span->first) {
+                    if (!span->hasNext())
+                        break;
+                    thing = span->last;
+                    span = span->nextSpan();
+                } else {
+                    JSObject *object = reinterpret_cast<JSObject *>(thing);
+                    if (object->hasSingletonType())
+                        pushObject(object);
+                    budget.step();
+                }
+            }
+            if (budget.isOverBudget()) {
+                pushArenaList(aheader);
+                return;
+            }
+        }
     }
+
 #if JS_HAS_XML_SUPPORT
     else {
         JS_ASSERT(tag == XmlTag);
         MarkChildren(this, reinterpret_cast<JSXML *>(addr));
     }
 #endif
 }
 
@@ -1038,17 +1068,17 @@ GCMarker::processMarkStackTop(SliceBudge
     }
 
     if (tag == ObjectTag) {
         obj = reinterpret_cast<JSObject *>(addr);
         JS_COMPARTMENT_ASSERT(runtime, obj);
         goto scan_obj;
     }
 
-    processMarkStackOther(tag, addr);
+    processMarkStackOther(budget, tag, addr);
     return;
 
   scan_value_array:
     JS_ASSERT(vp <= end);
     while (vp != end) {
         const Value &v = *vp++;
         if (v.isString()) {
             JSString *str = v.toString();
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -404,26 +404,20 @@ JSCompartment::markTypes(JSTracer *trc)
     JS_ASSERT(activeAnalysis || gcPreserveCode);
 
     for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
         MarkScriptRoot(trc, &script, "mark_types_script");
         JS_ASSERT(script == i.get<JSScript>());
     }
 
-    for (size_t thingKind = FINALIZE_OBJECT0;
-         thingKind < FINALIZE_OBJECT_LIMIT;
-         thingKind++) {
-        for (CellIterUnderGC i(this, AllocKind(thingKind)); !i.done(); i.next()) {
-            JSObject *object = i.get<JSObject>();
-            if (object->hasSingletonType()) {
-                MarkObjectRoot(trc, &object, "mark_types_singleton");
-                JS_ASSERT(object == i.get<JSObject>());
-            }
-        }
+    for (size_t thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) {
+        ArenaHeader *aheader = arenas.getFirstArena(static_cast<AllocKind>(thingKind));
+        if (aheader)
+            rt->gcMarker.pushArenaList(aheader);
     }
 
     for (CellIterUnderGC i(this, FINALIZE_TYPE_OBJECT); !i.done(); i.next()) {
         types::TypeObject *type = i.get<types::TypeObject>();
         MarkTypeObjectRoot(trc, &type, "mark_types_scan");
         JS_ASSERT(type == i.get<types::TypeObject>());
     }
 }
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -886,16 +886,17 @@ struct GCMarker : public JSTracer {
      * the explicit tags to distinguish them when it cannot be deduced from
      * the context of push or pop operation.
      */
     enum StackTag {
         ValueArrayTag,
         ObjectTag,
         TypeTag,
         XmlTag,
+        ArenaTag,
         SavedValueArrayTag,
         LastTag = SavedValueArrayTag
     };
 
     static const uintptr_t StackTagMask = 7;
 
     static void staticAsserts() {
         JS_STATIC_ASSERT(StackTagMask >= uintptr_t(LastTag));
@@ -912,16 +913,20 @@ struct GCMarker : public JSTracer {
     void start(JSRuntime *rt);
     void stop();
     void reset();
 
     void pushObject(JSObject *obj) {
         pushTaggedPtr(ObjectTag, obj);
     }
 
+    void pushArenaList(gc::ArenaHeader *firstArena) {
+        pushTaggedPtr(ArenaTag, firstArena);
+    }
+
     void pushType(types::TypeObject *type) {
         pushTaggedPtr(TypeTag, type);
     }
 
 #if JS_HAS_XML_SUPPORT
     void pushXML(JSXML *xml) {
         pushTaggedPtr(XmlTag, xml);
     }
@@ -1011,17 +1016,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 processMarkStackOther(SliceBudget &budget, 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;