Bug 1338623 - Don't assert on gray debugger proxy targets that will eventaully become black r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 03 Mar 2017 10:45:47 +0000
changeset 374835 ed21480d66e66fb04b09cd0eeba991e179fc7928
parent 374834 237caed7236d209f45b39dc1e5ab12692087ea51
child 374836 4e196d802c7be7f3a3c147cc6c5b6406656584b1
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1338623
milestone54.0a1
Bug 1338623 - Don't assert on gray debugger proxy targets that will eventaully become black r=sfink
js/src/gc/Marking.cpp
js/src/gc/Marking.h
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2565,30 +2565,35 @@ GCMarker::sizeOfExcludingThis(mozilla::M
     size_t size = stack.sizeOfExcludingThis(mallocSizeOf);
     for (ZonesIter zone(runtime(), WithAtoms); !zone.done(); zone.next())
         size += zone->gcGrayRoots().sizeOfExcludingThis(mallocSizeOf);
     return size;
 }
 
 #ifdef DEBUG
 Zone*
-GCMarker::stackContainsCrossZonePointerTo(const TenuredCell* target) const
+GCMarker::stackContainsCrossZonePointerTo(const Cell* target) const
 {
     MOZ_ASSERT(!JS::CurrentThreadIsHeapCollecting());
 
+    Zone* targetZone = target->asTenured().zone();
+
     for (MarkStackIter iter(stack); !iter.done(); iter.next()) {
         if (iter.peekTag() != MarkStack::ObjectTag)
             continue;
 
         auto source = iter.peekPtr().as<JSObject>();
-        if (source->is<ProxyObject>() &&
-            source->as<ProxyObject>().target() == static_cast<const Cell*>(target) &&
-            source->zone() != target->zone())
+        Zone* sourceZone = source->zone();
+        if (sourceZone == targetZone)
+            continue;
+
+        if ((source->is<ProxyObject>() && source->as<ProxyObject>().target() == target) ||
+            Debugger::isDebuggerCrossCompartmentEdge(source, target))
         {
-            return source->zone();
+            return sourceZone;
         }
     }
 
     return nullptr;
 }
 #endif // DEBUG
 
 
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -299,17 +299,17 @@ class GCMarker : public JSTracer
     void setGCMode(JSGCMode mode) { stack.setGCMode(mode); }
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
 #ifdef DEBUG
 
     bool shouldCheckCompartments() { return strictCompartmentChecking; }
 
-    Zone* stackContainsCrossZonePointerTo(const gc::TenuredCell* cell) const;
+    Zone* stackContainsCrossZonePointerTo(const gc::Cell* cell) const;
 
 #endif
 
     void markEphemeronValues(gc::Cell* markedCell, gc::WeakEntryVector& entry);
 
     static GCMarker* fromTracer(JSTracer* trc) {
         MOZ_ASSERT(trc->isMarkingTracer());
         return static_cast<GCMarker*>(trc);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -11705,16 +11705,38 @@ JS::dbg::GetDebuggeeGlobals(JSContext* c
     }
 
     for (WeakGlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront())
         vector.infallibleAppend(static_cast<JSObject*>(r.front()));
 
     return true;
 }
 
+#ifdef DEBUG
+/* static */ bool
+Debugger::isDebuggerCrossCompartmentEdge(JSObject* obj, const gc::Cell* target)
+{
+    MOZ_ASSERT(target);
+
+    auto cls = obj->getClass();
+    const gc::Cell* referent = nullptr;
+    if (cls == &DebuggerScript_class) {
+        referent = GetScriptReferentCell(obj);
+    } else if (cls == &DebuggerSource_class) {
+        referent = GetSourceReferentRawObject(obj);
+    } else if (obj->is<DebuggerObject>()) {
+        referent = static_cast<gc::Cell*>(obj->as<DebuggerObject>().getPrivate());
+    } else if (obj->is<DebuggerEnvironment>()) {
+        referent = static_cast<gc::Cell*>(obj->as<DebuggerEnvironment>().getPrivate());
+    }
+
+    return referent == target;
+}
+#endif
+
 
 /*** JS::dbg::GarbageCollectionEvent **************************************************************/
 
 namespace JS {
 namespace dbg {
 
 /* static */ GarbageCollectionEvent::Ptr
 GarbageCollectionEvent::Create(JSRuntime* rt, ::js::gcstats::Statistics& stats, uint64_t gcNumber)
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -831,16 +831,19 @@ class Debugger : private mozilla::Linked
      * returns true. If not, it returns false.
      */
     static void traceIncomingCrossCompartmentEdges(JSTracer* tracer);
     static MOZ_MUST_USE bool markIteratively(GCMarker* marker);
     static void traceAllForMovingGC(JSTracer* trc);
     static void sweepAll(FreeOp* fop);
     static void detachAllDebuggersFromGlobal(FreeOp* fop, GlobalObject* global);
     static void findZoneEdges(JS::Zone* v, gc::ZoneComponentFinder& finder);
+#ifdef DEBUG
+    static bool isDebuggerCrossCompartmentEdge(JSObject* obj, const js::gc::Cell* cell);
+#endif
 
     // Checks it the current compartment is allowed to execute code.
     static inline MOZ_MUST_USE bool checkNoExecute(JSContext* cx, HandleScript script);
 
     /*
      * JSTrapStatus Overview
      * ---------------------
      *