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 345893 ed21480d66e66fb04b09cd0eeba991e179fc7928
parent 345892 237caed7236d209f45b39dc1e5ab12692087ea51
child 345894 4e196d802c7be7f3a3c147cc6c5b6406656584b1
push id38337
push userkwierso@gmail.com
push dateSat, 04 Mar 2017 01:30:14 +0000
treeherderautoland@b691557cb7a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1338623
milestone54.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 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
      * ---------------------
      *