michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "jscompartment.h" michael@0: #include "jsgc.h" michael@0: michael@0: #include "gc/GCInternals.h" michael@0: #include "js/HashTable.h" michael@0: #include "vm/Runtime.h" michael@0: michael@0: #include "jscntxtinlines.h" michael@0: #include "jsgcinlines.h" michael@0: michael@0: using namespace js; michael@0: using namespace js::gc; michael@0: michael@0: void michael@0: js::TraceRuntime(JSTracer *trc) michael@0: { michael@0: JS_ASSERT(!IS_GC_MARKING_TRACER(trc)); michael@0: michael@0: MinorGC(trc->runtime(), JS::gcreason::EVICT_NURSERY); michael@0: AutoPrepareForTracing prep(trc->runtime(), WithAtoms); michael@0: MarkRuntime(trc); michael@0: } michael@0: michael@0: static void michael@0: IterateCompartmentsArenasCells(JSRuntime *rt, Zone *zone, void *data, michael@0: JSIterateCompartmentCallback compartmentCallback, michael@0: IterateArenaCallback arenaCallback, michael@0: IterateCellCallback cellCallback) michael@0: { michael@0: for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) michael@0: (*compartmentCallback)(rt, data, comp); michael@0: michael@0: for (size_t thingKind = 0; thingKind != FINALIZE_LIMIT; thingKind++) { michael@0: JSGCTraceKind traceKind = MapAllocToTraceKind(AllocKind(thingKind)); michael@0: size_t thingSize = Arena::thingSize(AllocKind(thingKind)); michael@0: michael@0: for (ArenaIter aiter(zone, AllocKind(thingKind)); !aiter.done(); aiter.next()) { michael@0: ArenaHeader *aheader = aiter.get(); michael@0: (*arenaCallback)(rt, data, aheader->getArena(), traceKind, thingSize); michael@0: for (CellIterUnderGC iter(aheader); !iter.done(); iter.next()) michael@0: (*cellCallback)(rt, data, iter.getCell(), traceKind, thingSize); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: js::IterateZonesCompartmentsArenasCells(JSRuntime *rt, void *data, michael@0: IterateZoneCallback zoneCallback, michael@0: JSIterateCompartmentCallback compartmentCallback, michael@0: IterateArenaCallback arenaCallback, michael@0: IterateCellCallback cellCallback) michael@0: { michael@0: AutoPrepareForTracing prop(rt, WithAtoms); michael@0: michael@0: for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { michael@0: (*zoneCallback)(rt, data, zone); michael@0: IterateCompartmentsArenasCells(rt, zone, data, michael@0: compartmentCallback, arenaCallback, cellCallback); michael@0: } michael@0: } michael@0: michael@0: void michael@0: js::IterateZoneCompartmentsArenasCells(JSRuntime *rt, Zone *zone, void *data, michael@0: IterateZoneCallback zoneCallback, michael@0: JSIterateCompartmentCallback compartmentCallback, michael@0: IterateArenaCallback arenaCallback, michael@0: IterateCellCallback cellCallback) michael@0: { michael@0: AutoPrepareForTracing prop(rt, WithAtoms); michael@0: michael@0: (*zoneCallback)(rt, data, zone); michael@0: IterateCompartmentsArenasCells(rt, zone, data, michael@0: compartmentCallback, arenaCallback, cellCallback); michael@0: } michael@0: michael@0: void michael@0: js::IterateChunks(JSRuntime *rt, void *data, IterateChunkCallback chunkCallback) michael@0: { michael@0: AutoPrepareForTracing prep(rt, SkipAtoms); michael@0: michael@0: for (js::GCChunkSet::Range r = rt->gcChunkSet.all(); !r.empty(); r.popFront()) michael@0: chunkCallback(rt, data, r.front()); michael@0: } michael@0: michael@0: void michael@0: js::IterateScripts(JSRuntime *rt, JSCompartment *compartment, michael@0: void *data, IterateScriptCallback scriptCallback) michael@0: { michael@0: MinorGC(rt, JS::gcreason::EVICT_NURSERY); michael@0: AutoPrepareForTracing prep(rt, SkipAtoms); michael@0: michael@0: if (compartment) { michael@0: for (CellIterUnderGC i(compartment->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) { michael@0: JSScript *script = i.get(); michael@0: if (script->compartment() == compartment) michael@0: scriptCallback(rt, data, script); michael@0: } michael@0: } else { michael@0: for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { michael@0: for (CellIterUnderGC i(zone, gc::FINALIZE_SCRIPT); !i.done(); i.next()) michael@0: scriptCallback(rt, data, i.get()); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: js::IterateGrayObjects(Zone *zone, GCThingCallback cellCallback, void *data) michael@0: { michael@0: MinorGC(zone->runtimeFromMainThread(), JS::gcreason::EVICT_NURSERY); michael@0: AutoPrepareForTracing prep(zone->runtimeFromMainThread(), SkipAtoms); michael@0: michael@0: for (size_t finalizeKind = 0; finalizeKind <= FINALIZE_OBJECT_LAST; finalizeKind++) { michael@0: for (CellIterUnderGC i(zone, AllocKind(finalizeKind)); !i.done(); i.next()) { michael@0: JSObject *obj = i.get(); michael@0: if (obj->isMarked(GRAY)) michael@0: cellCallback(data, obj); michael@0: } michael@0: } michael@0: } michael@0: michael@0: JS_PUBLIC_API(void) michael@0: JS_IterateCompartments(JSRuntime *rt, void *data, michael@0: JSIterateCompartmentCallback compartmentCallback) michael@0: { michael@0: JS_ASSERT(!rt->isHeapBusy()); michael@0: michael@0: AutoTraceSession session(rt); michael@0: michael@0: for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) michael@0: (*compartmentCallback)(rt, data, c); michael@0: }