tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PublicIterators.h (4183B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /*
      8 * Iterators for various data structures.
      9 */
     10 
     11 #ifndef gc_PublicIterators_h
     12 #define gc_PublicIterators_h
     13 
     14 #include "jstypes.h"
     15 #include "gc/GCRuntime.h"
     16 #include "gc/IteratorUtils.h"
     17 #include "gc/Zone.h"
     18 #include "vm/Compartment.h"
     19 #include "vm/Runtime.h"
     20 
     21 namespace JS {
     22 class JS_PUBLIC_API Realm;
     23 }
     24 
     25 namespace js {
     26 
     27 enum ZoneSelector { WithAtoms, SkipAtoms };
     28 
     29 // Iterate over all zones in the runtime. May or may not include the atoms zone.
     30 class ZonesIter {
     31  gc::AutoEnterIteration iterMarker;
     32  JS::Zone** it;
     33  JS::Zone** const end;
     34 
     35 public:
     36  ZonesIter(gc::GCRuntime* gc, ZoneSelector selector)
     37      : iterMarker(gc), it(gc->zones().begin()), end(gc->zones().end()) {
     38    if (selector == SkipAtoms) {
     39      while (!done() && get()->isAtomsZone()) {
     40        next();
     41      }
     42    }
     43  }
     44  ZonesIter(JSRuntime* rt, ZoneSelector selector)
     45      : ZonesIter(&rt->gc, selector) {}
     46 
     47  bool done() const { return it == end; }
     48 
     49  void next() {
     50    MOZ_ASSERT(!done());
     51    it++;
     52  }
     53 
     54  JS::Zone* get() const {
     55    MOZ_ASSERT(!done());
     56    return *it;
     57  }
     58 
     59  operator JS::Zone*() const { return get(); }
     60  JS::Zone* operator->() const { return get(); }
     61 };
     62 
     63 // Iterate over all zones in the runtime apart from the atoms zone.
     64 class NonAtomZonesIter : public ZonesIter {
     65 public:
     66  explicit NonAtomZonesIter(gc::GCRuntime* gc) : ZonesIter(gc, SkipAtoms) {}
     67  explicit NonAtomZonesIter(JSRuntime* rt) : NonAtomZonesIter(&rt->gc) {}
     68 };
     69 
     70 // Iterate over all zones in the runtime, except those which may be in use by
     71 // parse threads.
     72 class AllZonesIter : public ZonesIter {
     73 public:
     74  explicit AllZonesIter(gc::GCRuntime* gc) : ZonesIter(gc, WithAtoms) {}
     75  explicit AllZonesIter(JSRuntime* rt) : AllZonesIter(&rt->gc) {}
     76 };
     77 
     78 struct CompartmentsInZoneIter {
     79  explicit CompartmentsInZoneIter(JS::Zone* zone) : zone(zone) {
     80    it = zone->compartments().begin();
     81  }
     82 
     83  bool done() const {
     84    MOZ_ASSERT(it);
     85    return it < zone->compartments().begin() ||
     86           it >= zone->compartments().end();
     87  }
     88  void next() {
     89    MOZ_ASSERT(!done());
     90    it++;
     91  }
     92 
     93  JS::Compartment* get() const {
     94    MOZ_ASSERT(it);
     95    return *it;
     96  }
     97 
     98  operator JS::Compartment*() const { return get(); }
     99  JS::Compartment* operator->() const { return get(); }
    100 
    101 private:
    102  JS::Zone* zone;
    103  JS::Compartment** it;
    104 };
    105 
    106 class RealmsInCompartmentIter {
    107  JS::Compartment* comp;
    108  JS::Realm** it;
    109 
    110 public:
    111  explicit RealmsInCompartmentIter(JS::Compartment* comp) : comp(comp) {
    112    it = comp->realms().begin();
    113    MOZ_ASSERT(!done(), "Compartments must have at least one realm");
    114  }
    115 
    116  bool done() const {
    117    MOZ_ASSERT(it);
    118    return it < comp->realms().begin() || it >= comp->realms().end();
    119  }
    120  void next() {
    121    MOZ_ASSERT(!done());
    122    it++;
    123  }
    124 
    125  JS::Realm* get() const {
    126    MOZ_ASSERT(!done());
    127    return *it;
    128  }
    129 
    130  operator JS::Realm*() const { return get(); }
    131  JS::Realm* operator->() const { return get(); }
    132 };
    133 
    134 using RealmsInZoneIter =
    135    NestedIterator<CompartmentsInZoneIter, RealmsInCompartmentIter>;
    136 
    137 // This iterator iterates over all the compartments or realms in a given set of
    138 // zones. The set of zones is determined by iterating ZoneIterT. The set of
    139 // compartments or realms is determined by InnerIterT.
    140 template <class ZonesIterT, class InnerIterT>
    141 class CompartmentsOrRealmsIterT
    142    : public NestedIterator<ZonesIterT, InnerIterT> {
    143  gc::AutoEnterIteration iterMarker;
    144 
    145 public:
    146  explicit CompartmentsOrRealmsIterT(gc::GCRuntime* gc)
    147      : NestedIterator<ZonesIterT, InnerIterT>(gc), iterMarker(gc) {}
    148  explicit CompartmentsOrRealmsIterT(JSRuntime* rt)
    149      : CompartmentsOrRealmsIterT(&rt->gc) {}
    150 };
    151 
    152 using CompartmentsIter =
    153    CompartmentsOrRealmsIterT<NonAtomZonesIter, CompartmentsInZoneIter>;
    154 using RealmsIter =
    155    CompartmentsOrRealmsIterT<NonAtomZonesIter, RealmsInZoneIter>;
    156 
    157 }  // namespace js
    158 
    159 #endif  // gc_PublicIterators_h