/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * GC-internal iterators for various data structures. */ #ifndef gc_PrivateIterators_inl_h #define gc_PrivateIterators_inl_h #include "gc/PublicIterators.h" #include "gc/GC-inl.h" namespace js { namespace gc { class ArenaCellIterUnderGC : public ArenaCellIter { public: explicit ArenaCellIterUnderGC(Arena* arena) : ArenaCellIter(arena) { MOZ_ASSERT(CurrentThreadIsPerformingGC()); } }; class ArenaCellIterUnderFinalize : public ArenaCellIter { public: explicit ArenaCellIterUnderFinalize(Arena* arena) : ArenaCellIter(arena) { MOZ_ASSERT(CurrentThreadIsGCFinalizing()); } }; class GrayObjectIter : public ZoneAllCellIter { public: explicit GrayObjectIter(JS::Zone* zone, AllocKind kind) : ZoneAllCellIter() { initForTenuredIteration(zone, kind); } JSObject* get() const { return ZoneAllCellIter::get(); } operator JSObject*() const { return get(); } JSObject* operator->() const { return get(); } }; class GCZonesIter { AllZonesIter zone; public: explicit GCZonesIter(GCRuntime* gc) : zone(gc) { MOZ_ASSERT(gc->heapState() != JS::HeapState::Idle); if (!done() && !zone->wasGCStarted()) { next(); } } explicit GCZonesIter(JSRuntime* rt) : GCZonesIter(&rt->gc) {} bool done() const { return zone.done(); } void next() { MOZ_ASSERT(!done()); do { zone.next(); } while (!zone.done() && !zone->wasGCStarted()); } JS::Zone* get() const { MOZ_ASSERT(!done()); return zone; } operator JS::Zone*() const { return get(); } JS::Zone* operator->() const { return get(); } }; using GCCompartmentsIter = CompartmentsOrRealmsIterT; using GCRealmsIter = CompartmentsOrRealmsIterT; /* Iterates over all zones in the current sweep group. */ class SweepGroupZonesIter { JS::Zone* current; public: explicit SweepGroupZonesIter(GCRuntime* gc) : current(gc->getCurrentSweepGroup()) { MOZ_ASSERT(CurrentThreadIsPerformingGC()); } explicit SweepGroupZonesIter(JSRuntime* rt) : SweepGroupZonesIter(&rt->gc) {} bool done() const { return !current; } void next() { MOZ_ASSERT(!done()); current = current->nextNodeInGroup(); } JS::Zone* get() const { MOZ_ASSERT(!done()); return current; } operator JS::Zone*() const { return get(); } JS::Zone* operator->() const { return get(); } }; using SweepGroupCompartmentsIter = CompartmentsOrRealmsIterT; using SweepGroupRealmsIter = CompartmentsOrRealmsIterT; // Iterate the free cells in an arena. See also ArenaCellIter which iterates // the allocated cells. class ArenaFreeCellIter { Arena* arena; size_t thingSize; FreeSpan span; uint_fast16_t thing; public: explicit ArenaFreeCellIter(Arena* arena) : arena(arena), thingSize(arena->getThingSize()), span(*arena->getFirstFreeSpan()), thing(span.first) { MOZ_ASSERT(arena); MOZ_ASSERT(thing < ArenaSize); } bool done() const { MOZ_ASSERT(thing < ArenaSize); return !thing; } TenuredCell* get() const { MOZ_ASSERT(!done()); return reinterpret_cast(uintptr_t(arena) + thing); } void next() { MOZ_ASSERT(!done()); MOZ_ASSERT(thing >= span.first && thing <= span.last); if (thing == span.last) { span = *span.nextSpan(arena); thing = span.first; } else { thing += thingSize; } MOZ_ASSERT(thing < ArenaSize); } operator TenuredCell*() const { return get(); } TenuredCell* operator->() const { return get(); } }; } // namespace gc } // namespace js #endif // gc_PrivateIterators_inl_h