[INFER] Mark singleton JSObjects as well as TypeObjects when a GC is triggered during analysis, bug 678240.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 17 Aug 2011 13:16:11 -0700
changeset 76130 044290f5a31d7ee3216a5f884f827b11fb9faae2
parent 76129 2d95fc517e57fa1cecab8564b3832f3353742a81
child 76131 a4599ee114dcf8a03c788e9dc54bced248902d42
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
bugs678240
milestone8.0a1
[INFER] Mark singleton JSObjects as well as TypeObjects when a GC is triggered during analysis, bug 678240.
js/src/jscompartment.cpp
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -484,43 +484,61 @@ JSCompartment::markCrossCompartmentWrapp
 
     for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront())
         MarkValue(trc, e.front().key, "cross-compartment wrapper");
 }
 
 void
 JSCompartment::markTypes(JSTracer *trc)
 {
-    /* Mark all scripts and type objects in the compartment. */ 
+    /*
+     * Mark all scripts, type objects and singleton JS objects in the
+     * compartment. These can be referred to directly by type sets, which we
+     * cannot modify while code which depends on these type sets is active.
+     */
     JS_ASSERT(activeAnalysis);
 
     for (JSCList *cursor = scripts.next; cursor != &scripts; cursor = cursor->next) {
         JSScript *script = reinterpret_cast<JSScript *>(cursor);
         js_TraceScript(trc, script, NULL);
     }
 
-    gc::ArenaHeader *aheader = arenas[gc::FINALIZE_TYPE_OBJECT].getHead();
-    size_t thingSize = sizeof(types::TypeObject);
+    JS_STATIC_ASSERT(FINALIZE_FUNCTION_AND_OBJECT_LAST < FINALIZE_TYPE_OBJECT);
 
-    for (; aheader; aheader = aheader->next) {
-        gc::Arena *arena = aheader->getArena();
-        gc::FreeSpan firstSpan(aheader->getFirstFreeSpan());
-        const gc::FreeSpan *span = &firstSpan;
+    for (unsigned thingKind = FINALIZE_OBJECT0;
+         thingKind < FINALIZE_TYPE_OBJECT;
+         thingKind++) {
+        bool isObjectKind = thingKind <= FINALIZE_FUNCTION_AND_OBJECT_LAST;
+        if (!isObjectKind)
+            thingKind = FINALIZE_TYPE_OBJECT;
+
+        size_t thingSize = GCThingSizeMap[thingKind];
+        ArenaHeader *aheader = arenas[thingKind].getHead();
+
+        for (; aheader; aheader = aheader->next) {
+            Arena *arena = aheader->getArena();
+            FreeSpan firstSpan(aheader->getFirstFreeSpan());
+            const FreeSpan *span = &firstSpan;
 
-        for (uintptr_t thing = arena->thingsStart(thingSize); ; thing += thingSize) {
-            JS_ASSERT(thing <= arena->thingsEnd());
-            if (thing == span->first) {
-                if (!span->hasNext())
-                    break;
-                thing = span->last;
-                span = span->nextSpan();
-            } else {
-                types::TypeObject *object = reinterpret_cast<types::TypeObject *>(thing);
-                if (!object->isMarked())
-                    object->trace(trc);
+            for (uintptr_t thing = arena->thingsStart(thingSize); ; thing += thingSize) {
+                JS_ASSERT(thing <= arena->thingsEnd());
+                if (thing == span->first) {
+                    if (!span->hasNext())
+                        break;
+                    thing = span->last;
+                    span = span->nextSpan();
+                } else if (isObjectKind) {
+                    JSObject *object = reinterpret_cast<JSObject *>(thing);
+                    if (object->lastProp && object->hasSingletonType())
+                        MarkObject(trc, *object, "mark_types_singleton");
+                } else {
+                    types::TypeObject *object = reinterpret_cast<types::TypeObject *>(thing);
+                    if (!object->isMarked())
+                        object->trace(trc);
+                }
             }
         }
     }
 }
 
 void
 JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
 {