/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * 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/. */

#include "jscompartment.h"
#include "jsgc.h"

#include "gc/GCInternals.h"
#include "js/HashTable.h"
#include "vm/Runtime.h"

#include "jscntxtinlines.h"
#include "jsgcinlines.h"

// Unified leak fix:
#include "builtin/ModuleObject.h"

using namespace js;
using namespace js::gc;

void
js::TraceRuntime(JSTracer* trc)
{
    MOZ_ASSERT(!trc->isMarkingTracer());

    JSRuntime* rt = trc->runtime();
    rt->gc.evictNursery();
    AutoPrepareForTracing prep(rt, WithAtoms);
    gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_TRACE_HEAP);
    rt->gc.markRuntime(trc);
}

static void
IterateCompartmentsArenasCells(JSRuntime* rt, Zone* zone, void* data,
                               JSIterateCompartmentCallback compartmentCallback,
                               IterateArenaCallback arenaCallback,
                               IterateCellCallback cellCallback)
{
    for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
        (*compartmentCallback)(rt, data, comp);

    for (auto thingKind : AllAllocKinds()) {
        JS::TraceKind traceKind = MapAllocToTraceKind(thingKind);
        size_t thingSize = Arena::thingSize(thingKind);

        for (ArenaIter aiter(zone, thingKind); !aiter.done(); aiter.next()) {
            ArenaHeader* aheader = aiter.get();
            (*arenaCallback)(rt, data, aheader->getArena(), traceKind, thingSize);
            for (ArenaCellIterUnderGC iter(aheader); !iter.done(); iter.next())
                (*cellCallback)(rt, data, iter.getCell(), traceKind, thingSize);
        }
    }
}

void
js::IterateZonesCompartmentsArenasCells(JSRuntime* rt, void* data,
                                        IterateZoneCallback zoneCallback,
                                        JSIterateCompartmentCallback compartmentCallback,
                                        IterateArenaCallback arenaCallback,
                                        IterateCellCallback cellCallback)
{
    AutoPrepareForTracing prop(rt, WithAtoms);

    for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
        (*zoneCallback)(rt, data, zone);
        IterateCompartmentsArenasCells(rt, zone, data,
                                       compartmentCallback, arenaCallback, cellCallback);
    }
}

void
js::IterateZoneCompartmentsArenasCells(JSRuntime* rt, Zone* zone, void* data,
                                       IterateZoneCallback zoneCallback,
                                       JSIterateCompartmentCallback compartmentCallback,
                                       IterateArenaCallback arenaCallback,
                                       IterateCellCallback cellCallback)
{
    AutoPrepareForTracing prop(rt, WithAtoms);

    (*zoneCallback)(rt, data, zone);
    IterateCompartmentsArenasCells(rt, zone, data,
                                   compartmentCallback, arenaCallback, cellCallback);
}

void
js::IterateChunks(JSRuntime* rt, void* data, IterateChunkCallback chunkCallback)
{
    AutoPrepareForTracing prep(rt, SkipAtoms);

    for (auto chunk = rt->gc.allNonEmptyChunks(); !chunk.done(); chunk.next())
        chunkCallback(rt, data, chunk);
}

void
js::IterateScripts(JSRuntime* rt, JSCompartment* compartment,
                   void* data, IterateScriptCallback scriptCallback)
{
    rt->gc.evictNursery();
    AutoPrepareForTracing prep(rt, SkipAtoms);

    if (compartment) {
        for (ZoneCellIterUnderGC i(compartment->zone(), gc::AllocKind::SCRIPT); !i.done(); i.next()) {
            JSScript* script = i.get<JSScript>();
            if (script->compartment() == compartment)
                scriptCallback(rt, data, script);
        }
    } else {
        for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
            for (ZoneCellIterUnderGC i(zone, gc::AllocKind::SCRIPT); !i.done(); i.next())
                scriptCallback(rt, data, i.get<JSScript>());
        }
    }
}

void
js::IterateGrayObjects(Zone* zone, GCThingCallback cellCallback, void* data)
{
    zone->runtimeFromMainThread()->gc.evictNursery();
    AutoPrepareForTracing prep(zone->runtimeFromMainThread(), SkipAtoms);

    for (auto thingKind : ObjectAllocKinds()) {
        for (ZoneCellIterUnderGC i(zone, thingKind); !i.done(); i.next()) {
            JSObject* obj = i.get<JSObject>();
            if (obj->asTenured().isMarked(GRAY))
                cellCallback(data, JS::GCCellPtr(obj));
        }
    }
}

JS_PUBLIC_API(void)
JS_IterateCompartments(JSRuntime* rt, void* data,
                       JSIterateCompartmentCallback compartmentCallback)
{
    MOZ_ASSERT(!rt->isHeapBusy());

    AutoTraceSession session(rt);

    for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next())
        (*compartmentCallback)(rt, data, c);
}
