Bug 1647319 - Use NestedIterator to implement public iterators for realms and compartments r=sfink
☠☠ backed out by 17e8b5e9f8f9 ☠ ☠
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 23 Jun 2020 08:30:57 +0000
changeset 600839 0e900e18ead7ea87acc2cdc68ddb5e7b1054da6a
parent 600838 bd0b3614efcf062451ed9443fdae06e5cf43b808
child 600840 32b62f886374909e479a29c345ff4b238da09192
push id13310
push userffxbld-merge
push dateMon, 29 Jun 2020 14:50:06 +0000
treeherdermozilla-beta@15a59a0afa5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1647319
milestone79.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 1647319 - Use NestedIterator to implement public iterators for realms and compartments r=sfink Differential Revision: https://phabricator.services.mozilla.com/D80484
js/src/gc/PublicIterators.h
--- a/js/src/gc/PublicIterators.h
+++ b/js/src/gc/PublicIterators.h
@@ -10,16 +10,17 @@
 
 #ifndef gc_PublicIterators_h
 #define gc_PublicIterators_h
 
 #include "mozilla/Maybe.h"
 
 #include "jstypes.h"
 #include "gc/GCRuntime.h"
+#include "gc/IteratorUtils.h"
 #include "gc/Zone.h"
 #include "vm/Compartment.h"
 #include "vm/Runtime.h"
 
 struct JSRuntime;
 
 namespace JS {
 class JS_PUBLIC_API Realm;
@@ -108,18 +109,16 @@ class ZonesIter {
 // parse threads.
 class AllZonesIter : public ZonesIter {
  public:
   AllZonesIter(gc::GCRuntime* gc) : ZonesIter(gc, WithAtoms) {}
   AllZonesIter(JSRuntime* rt) : AllZonesIter(&rt->gc) {}
 };
 
 struct CompartmentsInZoneIter {
-  using ItemType = JS::Compartment;
-
   explicit CompartmentsInZoneIter(JS::Zone* zone) : zone(zone) {
     it = zone->compartments().begin();
   }
 
   bool done() const {
     MOZ_ASSERT(it);
     return it < zone->compartments().begin() ||
            it >= zone->compartments().end();
@@ -144,16 +143,17 @@ struct CompartmentsInZoneIter {
 
 class RealmsInCompartmentIter {
   JS::Compartment* comp;
   JS::Realm** it;
 
  public:
   explicit RealmsInCompartmentIter(JS::Compartment* comp) : comp(comp) {
     it = comp->realms().begin();
+    MOZ_ASSERT(!done(), "Compartments must have at least one realm");
   }
 
   bool done() const {
     MOZ_ASSERT(it);
     return it < comp->realms().begin() || it >= comp->realms().end();
   }
   void next() {
     MOZ_ASSERT(!done());
@@ -164,100 +164,34 @@ class RealmsInCompartmentIter {
     MOZ_ASSERT(!done());
     return *it;
   }
 
   operator JS::Realm*() const { return get(); }
   JS::Realm* operator->() const { return get(); }
 };
 
-class RealmsInZoneIter {
-  CompartmentsInZoneIter comp;
-  mozilla::Maybe<RealmsInCompartmentIter> realm;
-
- public:
-  using ItemType = JS::Realm;
-
-  explicit RealmsInZoneIter(JS::Zone* zone) : comp(zone) {
-    settleOnCompartment();
-  }
-
-  void settleOnCompartment() {
-    if (!comp.done()) {
-      realm.emplace(comp.get());
-      MOZ_ASSERT(!realm->done(), "compartment must have at least one realm");
-    }
-  }
-
-  bool done() const {
-    MOZ_ASSERT(comp.done() == realm.isNothing());
-    return comp.done();
-  }
-  void next() {
-    MOZ_ASSERT(!done());
-
-    realm->next();
-
-    if (realm->done()) {
-      realm.reset();
-      comp.next();
-      settleOnCompartment();
-    }
-  }
-
-  JS::Realm* get() const { return realm->get(); }
-
-  operator JS::Realm*() const { return get(); }
-  JS::Realm* operator->() const { return get(); }
-};
+using RealmsInZoneIter =
+    NestedIterator<CompartmentsInZoneIter, RealmsInCompartmentIter>;
 
 // This iterator iterates over all the compartments or realms in a given set of
 // zones. The set of zones is determined by iterating ZoneIterT. The set of
 // compartments or realms is determined by InnerIterT.
 template <class ZonesIterT, class InnerIterT>
-class CompartmentsOrRealmsIterT {
-  using T = typename InnerIterT::ItemType;
-
+class CompartmentsOrRealmsIterT
+    : public NestedIterator<ZonesIterT, InnerIterT> {
   gc::AutoEnterIteration iterMarker;
-  ZonesIterT zone;
-  mozilla::Maybe<InnerIterT> inner;
 
  public:
   explicit CompartmentsOrRealmsIterT(gc::GCRuntime* gc)
-      : iterMarker(gc), zone(gc, SkipAtoms) {
-    if (!zone.done()) {
-      inner.emplace(zone);
-    }
-  }
+      : NestedIterator<ZonesIterT, InnerIterT>(gc), iterMarker(gc) {}
   explicit CompartmentsOrRealmsIterT(JSRuntime* rt)
       : CompartmentsOrRealmsIterT(&rt->gc) {}
-
-  bool done() const { return zone.done(); }
-
-  void next() {
-    MOZ_ASSERT(!done());
-    MOZ_ASSERT(!inner.ref().done());
-    inner->next();
-    if (inner->done()) {
-      inner.reset();
-      zone.next();
-      if (!zone.done()) {
-        inner.emplace(zone);
-      }
-    }
-  }
-
-  T* get() const {
-    MOZ_ASSERT(!done());
-    return *inner;
-  }
-
-  operator T*() const { return get(); }
-  T* operator->() const { return get(); }
 };
 
 using CompartmentsIter =
-    CompartmentsOrRealmsIterT<ZonesIter, CompartmentsInZoneIter>;
-using RealmsIter = CompartmentsOrRealmsIterT<ZonesIter, RealmsInZoneIter>;
+    CompartmentsOrRealmsIterT<NonAtomZonesIter, CompartmentsInZoneIter>;
+using RealmsIter =
+    CompartmentsOrRealmsIterT<NonAtomZonesIter, RealmsInZoneIter>;
 
 }  // namespace js
 
 #endif  // gc_PublicIterators_h