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