Backed out changeset 97150f502eeb (bug 1102858) for breaking b2g builds
authorJon Coppeard <jcoppeard@mozilla.com>
Mon, 01 Dec 2014 07:18:58 -0800
changeset 218170 febe82aa4ed2400971d581e266c9d2684f2d5550
parent 218169 34ef51eca3bb528cbe71da4b21e8758c9b28a9da
child 218171 be23ef5730dce08c3d636fc670a5bf85c56b3f3b
push id27919
push userphilringnalda@gmail.com
push dateTue, 02 Dec 2014 03:07:26 +0000
treeherdermozilla-central@265e01c7ff55 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1102858
milestone37.0a1
backs out97150f502eeb2d19c5fe648875a8c48aba5e985f
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
Backed out changeset 97150f502eeb (bug 1102858) for breaking b2g builds
js/src/gc/RootMarking.cpp
js/src/jsgc.cpp
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -449,17 +449,17 @@ js::gc::GCRuntime::markRuntime(JSTracer 
 
     MOZ_ASSERT(!rt->mainThread.suppressGC);
 
     if (traceOrMark == MarkRuntime) {
         for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
             if (!c->zone()->isCollecting())
                 c->markCrossCompartmentWrappers(trc);
         }
-        Debugger::markAllCrossCompartmentEdges(trc);
+        Debugger::markCrossCompartmentDebuggerObjectReferents(trc);
     }
 
     AutoGCRooter::traceAll(trc);
 
     if (!rt->isBeingDestroyed()) {
         MarkExactStackRoots(rt, trc);
         rt->markSelfHostingGlobal(trc);
     }
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2657,17 +2657,17 @@ GCRuntime::updatePointersToRelocatedCell
     if (CanUseExtraThreads())
         updateAllCellPointersParallel(source);
     else
         updateAllCellPointersSerial(&trc, source);
 
     // Mark roots to update them.
     markRuntime(&trc, MarkRuntime);
     Debugger::markAll(&trc);
-    Debugger::markAllCrossCompartmentEdges(&trc);
+    Debugger::markCrossCompartmentDebuggerObjectReferents(&trc);
 
     for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
         WeakMapBase::markAll(c, &trc);
         if (c->watchpointMap)
             c->watchpointMap->markAll(&trc);
     }
 
     // Mark all gray roots, making sure we call the trace callback to get the
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -88,21 +88,16 @@ enum {
 
 extern const Class DebuggerSource_class;
 
 enum {
     JSSLOT_DEBUGSOURCE_OWNER,
     JSSLOT_DEBUGSOURCE_COUNT
 };
 
-static void DebuggerObject_trace(JSTracer *trc, JSObject *obj);
-static void DebuggerEnv_trace(JSTracer *trc, JSObject *obj);
-static void DebuggerScript_trace(JSTracer *trc, JSObject *obj);
-static void DebuggerSource_trace(JSTracer *trc, JSObject *obj);
-
 
 /*** Utils ***************************************************************************************/
 
 static inline bool
 EnsureFunctionHasScript(JSContext *cx, HandleFunction fun)
 {
     if (fun->isInterpretedLazy()) {
         AutoCompartment ac(cx, fun);
@@ -2073,53 +2068,63 @@ Debugger::setObservesAllExecution(JSCont
     return updateExecutionObservability(cx, obs, observing);
 }
 
 
 
 /*** Debugger JSObjects **************************************************************************/
 
 void
-Debugger::markCrossCompartmentEdges(JSTracer *trc)
-{
-    objects.markCrossCompartmentEdges<DebuggerObject_trace>(trc);
-    environments.markCrossCompartmentEdges<DebuggerEnv_trace>(trc);
-    scripts.markCrossCompartmentEdges<DebuggerScript_trace>(trc);
-    sources.markCrossCompartmentEdges<DebuggerSource_trace>(trc);
+Debugger::markKeysInCompartment(JSTracer *trc)
+{
+    /*
+     * WeakMap::Range is deliberately private, to discourage C++ code from
+     * enumerating WeakMap keys. However in this case we need access, so we
+     * make a base-class reference. Range is public in HashMap.
+     */
+    objects.markKeys(trc);
+    environments.markKeys(trc);
+    scripts.markKeys(trc);
+    sources.markKeys(trc);
 }
 
 /*
  * Ordinarily, WeakMap keys and values are marked because at some point it was
  * discovered that the WeakMap was live; that is, some object containing the
  * WeakMap was marked during mark phase.
  *
- * However, during zone GC, we have to do something about cross-compartment
- * edges in non-GC'd compartments. Since the source may be live, we
- * conservatively assume it is and mark the edge.
+ * However, during compartment GC, we have to do something about
+ * cross-compartment WeakMaps in non-GC'd compartments. If their keys and values
+ * might need to be marked, we have to do it manually.
  *
- * Each Debugger object keeps four cross-compartment WeakMaps: objects, scripts,
- * script source objects, and environments. They have the property that all
- * their values are in the same compartment as the Debugger object, but we have
- * to mark the keys and the private pointer in the wrapper object.
+ * Each Debugger object keeps found cross-compartment WeakMaps: objects, scripts,
+ * script source objects, and environments. They have the nice property that all
+ * their values are in the same compartment as the Debugger object, so we only
+ * need to mark the keys. We must simply mark all keys that are in a compartment
+ * being GC'd.
  *
- * We must scan all Debugger objects regardless of whether they *currently* have
- * any debuggees in a compartment being GC'd, because the WeakMap entries
- * persist even when debuggees are removed.
+ * We must scan all Debugger objects regardless of whether they *currently*
+ * have any debuggees in a compartment being GC'd, because the WeakMap
+ * entries persist even when debuggees are removed.
  *
  * This happens during the initial mark phase, not iterative marking, because
  * all the edges being reported here are strong references.
  */
 /* static */ void
-Debugger::markAllCrossCompartmentEdges(JSTracer *trc)
+Debugger::markCrossCompartmentDebuggerObjectReferents(JSTracer *trc)
 {
     JSRuntime *rt = trc->runtime();
 
+    /*
+     * Mark all objects in comp that are referents of Debugger.Objects in other
+     * compartments.
+     */
     for (Debugger *dbg = rt->debuggerList.getFirst(); dbg; dbg = dbg->getNext()) {
         if (!dbg->object->zone()->isCollecting())
-            dbg->markCrossCompartmentEdges(trc);
+            dbg->markKeysInCompartment(trc);
     }
 }
 
 /*
  * This method has two tasks:
  *   1. Mark Debugger objects that are unreachable except for debugger hooks that
  *      may yet be called.
  *   2. Mark breakpoint handlers.
@@ -2203,16 +2208,17 @@ Debugger::markAllIteratively(GCMarker *t
 /* static */ void
 Debugger::markAll(JSTracer *trc)
 {
     JSRuntime *rt = trc->runtime();
     for (Debugger *dbg = rt->debuggerList.getFirst(); dbg; dbg = dbg->getNext()) {
         GlobalObjectSet &debuggees = dbg->debuggees;
         for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
             GlobalObject *global = e.front();
+
             MarkObjectUnbarriered(trc, &global, "Global Object");
             if (global != e.front())
                 e.rekeyFront(global);
         }
 
         HeapPtrNativeObject &dbgobj = dbg->toJSObjectRef();
         MarkObject(trc, &dbgobj, "Debugger Object");
 
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -31,41 +31,39 @@ typedef enum JSTrapStatus {
 } JSTrapStatus;
 
 namespace js {
 
 class Breakpoint;
 class DebuggerMemory;
 
 /*
- * A weakmap from GC thing keys to JSObject values that supports the keys being
- * in different compartments to the values. All values must be in the same
- * compartment.
+ * A weakmap that supports the keys being in different compartments to the
+ * values, although all values must be in the same compartment.
+ *
+ * The Key and Value classes must support the compartment() method.
  *
  * The purpose of this is to allow the garbage collector to easily find edges
  * from debugee object compartments to debugger compartments when calculating
  * the compartment groups.  Note that these edges are the inverse of the edges
  * stored in the cross compartment map.
  *
  * The current implementation results in all debuggee object compartments being
  * swept in the same group as the debugger.  This is a conservative approach,
  * and compartments may be unnecessarily grouped, however it results in a
  * simpler and faster implementation.
  *
  * If InvisibleKeysOk is true, then the map can have keys in invisible-to-
  * debugger compartments. If it is false, we assert that such entries are never
  * created.
  */
-template <class UnbarrieredKey, bool InvisibleKeysOk=false>
-class DebuggerWeakMap : private WeakMap<PreBarriered<UnbarrieredKey>, RelocatablePtrObject>
+template <class Key, class Value, bool InvisibleKeysOk=false>
+class DebuggerWeakMap : private WeakMap<Key, Value, DefaultHasher<Key> >
 {
   private:
-    typedef PreBarriered<UnbarrieredKey> Key;
-    typedef RelocatablePtrObject Value;
-
     typedef HashMap<JS::Zone *,
                     uintptr_t,
                     DefaultHasher<JS::Zone *>,
                     RuntimeAllocPolicy> CountMap;
 
     CountMap zoneCounts;
 
   public:
@@ -109,20 +107,18 @@ class DebuggerWeakMap : private WeakMap<
 
     void remove(const Lookup &l) {
         MOZ_ASSERT(Base::has(l));
         Base::remove(l);
         decZoneCount(l->zone());
     }
 
   public:
-    template <void (traceValueEdges)(JSTracer *, JSObject *)>
-    void markCrossCompartmentEdges(JSTracer *tracer) {
+    void markKeys(JSTracer *tracer) {
         for (Enum e(*static_cast<Base *>(this)); !e.empty(); e.popFront()) {
-            traceValueEdges(tracer, e.front().value());
             Key key = e.front().key();
             gc::Mark(tracer, &key, "Debugger WeakMap key");
             if (key != e.front().key())
                 e.rekeyFront(key);
             key.unsafeSet(nullptr);
         }
     }
 
@@ -281,25 +277,25 @@ class Debugger : private mozilla::Linked
      */
     typedef HashMap<AbstractFramePtr,
                     RelocatablePtrNativeObject,
                     DefaultHasher<AbstractFramePtr>,
                     RuntimeAllocPolicy> FrameMap;
     FrameMap frames;
 
     /* An ephemeral map from JSScript* to Debugger.Script instances. */
-    typedef DebuggerWeakMap<JSScript*> ScriptWeakMap;
+    typedef DebuggerWeakMap<PreBarrieredScript, RelocatablePtrObject> ScriptWeakMap;
     ScriptWeakMap scripts;
 
     /* The map from debuggee source script objects to their Debugger.Source instances. */
-    typedef DebuggerWeakMap<JSObject*, true> SourceWeakMap;
+    typedef DebuggerWeakMap<PreBarrieredObject, RelocatablePtrObject, true> SourceWeakMap;
     SourceWeakMap sources;
 
     /* The map from debuggee objects to their Debugger.Object instances. */
-    typedef DebuggerWeakMap<JSObject*> ObjectWeakMap;
+    typedef DebuggerWeakMap<PreBarrieredObject, RelocatablePtrObject> ObjectWeakMap;
     ObjectWeakMap objects;
 
     /* The map from debuggee Envs to Debugger.Environment instances. */
     ObjectWeakMap environments;
 
     class FrameRange;
     class ScriptQuery;
     class ObjectQuery;
@@ -355,17 +351,17 @@ class Debugger : private mozilla::Linked
     JSTrapStatus parseResumptionValue(mozilla::Maybe<AutoCompartment> &ac, bool ok, const Value &rv,
                                       MutableHandleValue vp, bool callHook = true);
 
     GlobalObject *unwrapDebuggeeArgument(JSContext *cx, const Value &v);
 
     static void traceObject(JSTracer *trc, JSObject *obj);
     void trace(JSTracer *trc);
     static void finalize(FreeOp *fop, JSObject *obj);
-    void markCrossCompartmentEdges(JSTracer *tracer);
+    void markKeysInCompartment(JSTracer *tracer);
 
     static const Class jsclass;
 
     static Debugger *fromThisValue(JSContext *cx, const CallArgs &ca, const char *fnname);
     static bool getEnabled(JSContext *cx, unsigned argc, Value *vp);
     static bool setEnabled(JSContext *cx, unsigned argc, Value *vp);
     static bool getHookImpl(JSContext *cx, unsigned argc, Value *vp, Hook which);
     static bool setHookImpl(JSContext *cx, unsigned argc, Value *vp, Hook which);
@@ -505,17 +501,17 @@ class Debugger : private mozilla::Linked
      *       - it has a debugger hook installed
      *       - it has a breakpoint set on a live script
      *       - it has a watchpoint set on a live object.
      *
      * Debugger::markAllIteratively handles the last case. If it finds any
      * Debugger objects that are definitely live but not yet marked, it marks
      * them and returns true. If not, it returns false.
      */
-    static void markAllCrossCompartmentEdges(JSTracer *tracer);
+    static void markCrossCompartmentDebuggerObjectReferents(JSTracer *tracer);
     static bool markAllIteratively(GCMarker *trc);
     static void markAll(JSTracer *trc);
     static void sweepAll(FreeOp *fop);
     static void detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global);
     static void findCompartmentEdges(JS::Zone *v, gc::ComponentFinder<JS::Zone> &finder);
 
     /*
      * JSTrapStatus Overview