Bug 1157829 - The markAndScan functions are now just an additional assertion; r=sfink
authorTerrence Cole <terrence@mozilla.com>
Thu, 23 Apr 2015 11:05:46 -0700
changeset 241319 2cb0f73999f485873ec72926dec2742d93da13b0
parent 241318 2f2e5313ca8e4523ccda2a381e662d116fa89919
child 241320 333aaffb8ad7eb94ff1a1cdc9f9e4cd76e16b61c
push id28658
push usercbook@mozilla.com
push dateTue, 28 Apr 2015 10:01:27 +0000
treeherdermozilla-central@e0299ad29b85 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1157829
milestone40.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 1157829 - The markAndScan functions are now just an additional assertion; r=sfink
js/src/gc/Marking.cpp
js/src/gc/Tracer.h
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -324,18 +324,16 @@ typename PtrBaseGCType<T>::type*
 ConvertToBase(T* thingp)
 {
     return reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp);
 }
 
 template <typename T> void DispatchToTracer(JSTracer* trc, T* thingp, const char* name);
 template <typename T> T DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name);
 template <typename T> void DoMarking(GCMarker* gcmarker, T thing);
-static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell);
-static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val);
 
 template <typename T>
 void
 js::TraceEdge(JSTracer* trc, BarrieredBase<T>* thingp, const char* name)
 {
     DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name);
 }
 
@@ -580,16 +578,25 @@ js::GCMarker::markAndPush(StackTag tag, 
 }
 namespace js {
 template <> void GCMarker::traverse(JSObject* thing) { markAndPush(ObjectTag, thing); }
 template <> void GCMarker::traverse(ObjectGroup* thing) { markAndPush(GroupTag, thing); }
 template <> void GCMarker::traverse(jit::JitCode* thing) { markAndPush(JitCodeTag, thing); }
 } // namespace js
 
 template <typename T>
+void
+GCMarker::traverse(JSObject* source, T* target)
+{
+    MOZ_ASSERT_IF(!ThingIsPermanentAtomOrWellKnownSymbol(target),
+                  runtime()->isAtomsZone(target->zone()) || target->zone() == source->zone());
+    traverse(target);
+}
+
+template <typename T>
 bool
 js::GCMarker::mark(T* thing)
 {
     CheckTracedThing(this, thing);
     JS_COMPARTMENT_ASSERT(runtime(), thing);
     MOZ_ASSERT(!IsInsideNursery(gc::TenuredCell::fromPointer(thing)));
     return gc::ParticipatesInCC<T>::value
            ? gc::TenuredCell::fromPointer(thing)->markIfUnmarked(markColor())
@@ -1425,38 +1432,16 @@ GCMarker::processMarkStackOther(uintptr_
             pushValueArray(obj, vp, end);
         else
             repush(obj);
     } else if (tag == JitCodeTag) {
         reinterpret_cast<jit::JitCode*>(addr)->traceChildren(this);
     }
 }
 
-MOZ_ALWAYS_INLINE void
-GCMarker::markAndScanString(JSObject* source, JSString* str)
-{
-    if (!str->isPermanentAtom()) {
-        JS_COMPARTMENT_ASSERT(runtime(), str);
-        MOZ_ASSERT(runtime()->isAtomsZone(str->zone()) || str->zone() == source->zone());
-        if (str->markIfUnmarked())
-            eagerlyMarkChildren(str);
-    }
-}
-
-MOZ_ALWAYS_INLINE void
-GCMarker::markAndScanSymbol(JSObject* source, JS::Symbol* sym)
-{
-    if (!sym->isWellKnownSymbol()) {
-        JS_COMPARTMENT_ASSERT(runtime(), sym);
-        MOZ_ASSERT(runtime()->isAtomsZone(sym->zone()) || sym->zone() == source->zone());
-        if (sym->markIfUnmarked())
-            eagerlyMarkChildren(sym);
-    }
-}
-
 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.
      */
@@ -1499,59 +1484,59 @@ GCMarker::processMarkStackTop(SliceBudge
         budget.step();
         if (budget.isOverBudget()) {
             pushValueArray(obj, vp, end);
             return;
         }
 
         const Value& v = *vp++;
         if (v.isString()) {
-            markAndScanString(obj, v.toString());
+            traverse(obj, v.toString());
         } else if (v.isObject()) {
             JSObject* obj2 = &v.toObject();
             MOZ_ASSERT(obj->compartment() == obj2->compartment());
             if (mark(obj2)) {
                 // Save the rest of this value array for later and start scanning obj2's children.N
                 pushValueArray(obj, vp, end);
                 obj = obj2;
                 goto scan_obj;
             }
         } else if (v.isSymbol()) {
-            markAndScanSymbol(obj, v.toSymbol());
+            traverse(obj, v.toSymbol());
         }
     }
     return;
 
   scan_unboxed:
     {
         while (*unboxedTraceList != -1) {
             JSString* str = *reinterpret_cast<JSString**>(unboxedMemory + *unboxedTraceList);
-            markAndScanString(obj, str);
+            traverse(obj, str);
             unboxedTraceList++;
         }
         unboxedTraceList++;
         while (*unboxedTraceList != -1) {
             JSObject* obj2 = *reinterpret_cast<JSObject**>(unboxedMemory + *unboxedTraceList);
             MOZ_ASSERT_IF(obj2, obj->compartment() == obj2->compartment());
             if (obj2 && mark(obj2))
                 repush(obj2);
             unboxedTraceList++;
         }
         unboxedTraceList++;
         while (*unboxedTraceList != -1) {
             const Value& v = *reinterpret_cast<Value*>(unboxedMemory + *unboxedTraceList);
             if (v.isString()) {
-                markAndScanString(obj, v.toString());
+                traverse(obj, v.toString());
             } else if (v.isObject()) {
                 JSObject* obj2 = &v.toObject();
                 MOZ_ASSERT(obj->compartment() == obj2->compartment());
                 if (mark(obj2))
                     repush(obj2);
             } else if (v.isSymbol()) {
-                markAndScanSymbol(obj, v.toSymbol());
+                traverse(obj, v.toSymbol());
             }
             unboxedTraceList++;
         }
         return;
     }
 
   scan_obj:
     {
--- a/js/src/gc/Tracer.h
+++ b/js/src/gc/Tracer.h
@@ -155,16 +155,19 @@ class GCMarker : public JSTracer
 
     void start();
     void stop();
     void reset();
 
     // Mark the given GC thing and traverse its children at some point.
     template <typename T> void traverse(T* thing);
 
+    // Calls traverse on target after making additional assertions.
+    template <typename T> void traverse(JSObject* source, T* target);
+
     /*
      * Care must be taken changing the mark color from gray to black. The cycle
      * collector depends on the invariant that there are no black to gray edges
      * in the GC heap. This invariant lets the CC not trace through black
      * objects. If this invariant is violated, the cycle collector may free
      * objects that are still reachable.
      */
     void setMarkColorGray() {
@@ -280,19 +283,16 @@ class GCMarker : public JSTracer
         return stack.isEmpty();
     }
 
     bool restoreValueArray(NativeObject* obj, void** vpp, void** endp);
     void saveValueRanges();
     inline void processMarkStackTop(SliceBudget& budget);
     void processMarkStackOther(uintptr_t tag, uintptr_t addr);
 
-    void markAndScanString(JSObject* source, JSString* str);
-    void markAndScanSymbol(JSObject* source, JS::Symbol* sym);
-
     /* The color is only applied to objects and functions. */
     uint32_t color;
 
     /* Pointer to the top of the stack of arenas we are delaying marking on. */
     js::gc::ArenaHeader* unmarkedArenaStackTop;
 
     /* Count of arenas that are currently in the stack. */
     mozilla::DebugOnly<size_t> markLaterArenas;