mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-06-12 17:31:05 +00:00
222 lines
5.4 KiB
C++
222 lines
5.4 KiB
C++
/* -*- 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/. */
|
|
|
|
#ifndef gc_GCInternals_h
|
|
#define gc_GCInternals_h
|
|
|
|
#include "mozilla/ArrayUtils.h"
|
|
#include "mozilla/PodOperations.h"
|
|
|
|
#include "jscntxt.h"
|
|
|
|
#include "gc/Zone.h"
|
|
#include "vm/HelperThreads.h"
|
|
#include "vm/Runtime.h"
|
|
|
|
namespace js {
|
|
namespace gc {
|
|
|
|
void
|
|
MarkPersistentRootedChains(JSTracer* trc);
|
|
|
|
class MOZ_RAII AutoCopyFreeListToArenas
|
|
{
|
|
JSRuntime* runtime;
|
|
ZoneSelector selector;
|
|
|
|
public:
|
|
AutoCopyFreeListToArenas(JSRuntime* rt, ZoneSelector selector);
|
|
~AutoCopyFreeListToArenas();
|
|
};
|
|
|
|
struct MOZ_RAII AutoFinishGC
|
|
{
|
|
explicit AutoFinishGC(JSRuntime* rt);
|
|
};
|
|
|
|
/*
|
|
* This class should be used by any code that needs to exclusive access to the
|
|
* heap in order to trace through it...
|
|
*/
|
|
class MOZ_RAII AutoTraceSession
|
|
{
|
|
public:
|
|
explicit AutoTraceSession(JSRuntime* rt, JS::HeapState state = JS::HeapState::Tracing);
|
|
~AutoTraceSession();
|
|
|
|
protected:
|
|
AutoLockForExclusiveAccess lock;
|
|
JSRuntime* runtime;
|
|
|
|
private:
|
|
AutoTraceSession(const AutoTraceSession&) = delete;
|
|
void operator=(const AutoTraceSession&) = delete;
|
|
|
|
JS::HeapState prevState;
|
|
AutoSPSEntry pseudoFrame;
|
|
};
|
|
|
|
struct MOZ_RAII AutoPrepareForTracing
|
|
{
|
|
AutoFinishGC finish;
|
|
AutoTraceSession session;
|
|
AutoCopyFreeListToArenas copy;
|
|
|
|
AutoPrepareForTracing(JSRuntime* rt, ZoneSelector selector);
|
|
};
|
|
|
|
class IncrementalSafety
|
|
{
|
|
const char* reason_;
|
|
|
|
explicit IncrementalSafety(const char* reason) : reason_(reason) {}
|
|
|
|
public:
|
|
static IncrementalSafety Safe() { return IncrementalSafety(nullptr); }
|
|
static IncrementalSafety Unsafe(const char* reason) { return IncrementalSafety(reason); }
|
|
|
|
explicit operator bool() const {
|
|
return reason_ == nullptr;
|
|
}
|
|
|
|
const char* reason() {
|
|
MOZ_ASSERT(reason_);
|
|
return reason_;
|
|
}
|
|
};
|
|
|
|
IncrementalSafety
|
|
IsIncrementalGCSafe(JSRuntime* rt);
|
|
|
|
#ifdef JS_GC_ZEAL
|
|
|
|
class MOZ_RAII AutoStopVerifyingBarriers
|
|
{
|
|
GCRuntime* gc;
|
|
bool restartPreVerifier;
|
|
|
|
public:
|
|
AutoStopVerifyingBarriers(JSRuntime* rt, bool isShutdown)
|
|
: gc(&rt->gc)
|
|
{
|
|
restartPreVerifier = gc->endVerifyPreBarriers() && !isShutdown;
|
|
}
|
|
|
|
~AutoStopVerifyingBarriers() {
|
|
// Nasty special case: verification runs a minor GC, which *may* nest
|
|
// inside of an outer minor GC. This is not allowed by the
|
|
// gc::Statistics phase tree. So we pause the "real" GC, if in fact one
|
|
// is in progress.
|
|
gcstats::Phase outer = gc->stats.currentPhase();
|
|
if (outer != gcstats::PHASE_NONE)
|
|
gc->stats.endPhase(outer);
|
|
MOZ_ASSERT((gc->stats.currentPhase() == gcstats::PHASE_NONE) ||
|
|
(gc->stats.currentPhase() == gcstats::PHASE_GC_BEGIN) ||
|
|
(gc->stats.currentPhase() == gcstats::PHASE_GC_END));
|
|
|
|
if (restartPreVerifier)
|
|
gc->startVerifyPreBarriers();
|
|
|
|
if (outer != gcstats::PHASE_NONE)
|
|
gc->stats.beginPhase(outer);
|
|
}
|
|
};
|
|
#else
|
|
struct MOZ_RAII AutoStopVerifyingBarriers
|
|
{
|
|
AutoStopVerifyingBarriers(JSRuntime*, bool) {}
|
|
};
|
|
#endif /* JS_GC_ZEAL */
|
|
|
|
#ifdef JSGC_HASH_TABLE_CHECKS
|
|
void
|
|
CheckHashTablesAfterMovingGC(JSRuntime* rt);
|
|
#endif
|
|
|
|
struct MovingTracer : JS::CallbackTracer
|
|
{
|
|
explicit MovingTracer(JSRuntime* rt) : CallbackTracer(rt, TraceWeakMapKeysValues) {}
|
|
|
|
void onObjectEdge(JSObject** objp) override;
|
|
void onChild(const JS::GCCellPtr& thing) override {
|
|
MOZ_ASSERT(!RelocationOverlay::isCellForwarded(thing.asCell()));
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
TracerKind getTracerKind() const override { return TracerKind::Moving; }
|
|
#endif
|
|
};
|
|
|
|
class MOZ_RAII AutoMaybeStartBackgroundAllocation
|
|
{
|
|
private:
|
|
JSRuntime* runtime;
|
|
|
|
public:
|
|
AutoMaybeStartBackgroundAllocation()
|
|
: runtime(nullptr)
|
|
{}
|
|
|
|
void tryToStartBackgroundAllocation(JSRuntime* rt) {
|
|
runtime = rt;
|
|
}
|
|
|
|
~AutoMaybeStartBackgroundAllocation() {
|
|
if (runtime)
|
|
runtime->gc.startBackgroundAllocTaskIfIdle();
|
|
}
|
|
};
|
|
|
|
// In debug builds, set/unset the GC sweeping flag for the current thread.
|
|
struct MOZ_RAII AutoSetThreadIsSweeping
|
|
{
|
|
#ifdef DEBUG
|
|
AutoSetThreadIsSweeping()
|
|
: threadData_(js::TlsPerThreadData.get())
|
|
{
|
|
MOZ_ASSERT(!threadData_->gcSweeping);
|
|
threadData_->gcSweeping = true;
|
|
}
|
|
|
|
~AutoSetThreadIsSweeping() {
|
|
MOZ_ASSERT(threadData_->gcSweeping);
|
|
threadData_->gcSweeping = false;
|
|
}
|
|
|
|
private:
|
|
PerThreadData* threadData_;
|
|
#else
|
|
AutoSetThreadIsSweeping() {}
|
|
#endif
|
|
};
|
|
|
|
// Structure for counting how many times objects in a particular group have
|
|
// been tenured during a minor collection.
|
|
struct TenureCount
|
|
{
|
|
ObjectGroup* group;
|
|
int count;
|
|
};
|
|
|
|
// Keep rough track of how many times we tenure objects in particular groups
|
|
// during minor collections, using a fixed size hash for efficiency at the cost
|
|
// of potential collisions.
|
|
struct TenureCountCache
|
|
{
|
|
TenureCount entries[16];
|
|
|
|
TenureCountCache() { mozilla::PodZero(this); }
|
|
|
|
TenureCount& findEntry(ObjectGroup* group) {
|
|
return entries[PointerHasher<ObjectGroup*, 3>::hash(group) % mozilla::ArrayLength(entries)];
|
|
}
|
|
};
|
|
|
|
} /* namespace gc */
|
|
} /* namespace js */
|
|
|
|
#endif /* gc_GCInternals_h */
|