Bug 1486727 - Move some inline method defintions out of gc/Zone.h into new Zone-inl.h r=sfink

This commit is contained in:
Jon Coppeard 2018-08-29 13:23:56 +01:00
Родитель b77761050d
Коммит 235348e9ef
8 изменённых файлов: 227 добавлений и 136 удалений

Просмотреть файл

@ -18,6 +18,8 @@
#include "vm/SymbolType.h"
#include "wasm/WasmJS.h"
#include "gc/Zone-inl.h"
namespace js {
bool

Просмотреть файл

@ -251,6 +251,7 @@
#include "gc/Marking-inl.h"
#include "gc/Nursery-inl.h"
#include "gc/PrivateIterators-inl.h"
#include "gc/Zone-inl.h"
#include "vm/GeckoProfiler-inl.h"
#include "vm/JSObject-inl.h"
#include "vm/JSScript-inl.h"

Просмотреть файл

@ -37,6 +37,7 @@
#include "gc/GC-inl.h"
#include "gc/Nursery-inl.h"
#include "gc/PrivateIterators-inl.h"
#include "gc/Zone-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/Realm-inl.h"
#include "vm/StringType-inl.h"

Просмотреть файл

@ -32,6 +32,7 @@
#include "vm/TypeInference.h"
#include "gc/Marking-inl.h"
#include "gc/Zone-inl.h"
#include "vm/NativeObject-inl.h"
using namespace js;

161
js/src/gc/Zone-inl.h Normal file
Просмотреть файл

@ -0,0 +1,161 @@
/* -*- 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_Zone_inl_h
#define gc_Zone_inl_h
#include "gc/Zone.h"
#ifdef DEBUG
inline bool
JS::Zone::requireGCTracer() const
{
JSRuntime* rt = runtimeFromAnyThread();
return RuntimeHeapIsMajorCollecting() && !rt->gc.isHeapCompacting() && gcState_ != NoGC;
}
#endif
inline void
JS::Zone::updateAllGCMallocCountersOnGCStart()
{
gcMallocCounter.updateOnGCStart();
jitCodeCounter.updateOnGCStart();
}
inline void
JS::Zone::updateAllGCMallocCountersOnGCEnd(const js::AutoLockGC& lock)
{
auto& gc = runtimeFromAnyThread()->gc;
gcMallocCounter.updateOnGCEnd(gc.tunables, lock);
jitCodeCounter.updateOnGCEnd(gc.tunables, lock);
}
inline js::gc::TriggerKind
JS::Zone::shouldTriggerGCForTooMuchMalloc()
{
auto& gc = runtimeFromAnyThread()->gc;
return std::max(gcMallocCounter.shouldTriggerGC(gc.tunables),
jitCodeCounter.shouldTriggerGC(gc.tunables));
}
/* static */ inline js::HashNumber
JS::Zone::UniqueIdToHash(uint64_t uid)
{
return mozilla::HashGeneric(uid);
}
inline bool
JS::Zone::getHashCode(js::gc::Cell* cell, js::HashNumber* hashp)
{
uint64_t uid;
if (!getOrCreateUniqueId(cell, &uid))
return false;
*hashp = UniqueIdToHash(uid);
return true;
}
inline bool
JS::Zone::maybeGetUniqueId(js::gc::Cell* cell, uint64_t* uidp)
{
MOZ_ASSERT(uidp);
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
// Get an existing uid, if one has been set.
auto p = uniqueIds().lookup(cell);
if (p)
*uidp = p->value();
return p.found();
}
inline bool
JS::Zone::getOrCreateUniqueId(js::gc::Cell* cell, uint64_t* uidp)
{
MOZ_ASSERT(uidp);
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this) || js::CurrentThreadIsPerformingGC());
// Get an existing uid, if one has been set.
auto p = uniqueIds().lookupForAdd(cell);
if (p) {
*uidp = p->value();
return true;
}
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
// Set a new uid on the cell.
*uidp = js::gc::NextCellUniqueId(runtimeFromAnyThread());
if (!uniqueIds().add(p, cell, *uidp))
return false;
// If the cell was in the nursery, hopefully unlikely, then we need to
// tell the nursery about it so that it can sweep the uid if the thing
// does not get tenured.
if (IsInsideNursery(cell) &&
!runtimeFromMainThread()->gc.nursery().addedUniqueIdToCell(cell))
{
uniqueIds().remove(cell);
return false;
}
return true;
}
inline js::HashNumber
JS::Zone::getHashCodeInfallible(js::gc::Cell* cell)
{
return UniqueIdToHash(getUniqueIdInfallible(cell));
}
inline uint64_t
JS::Zone::getUniqueIdInfallible(js::gc::Cell* cell)
{
uint64_t uid;
js::AutoEnterOOMUnsafeRegion oomUnsafe;
if (!getOrCreateUniqueId(cell, &uid))
oomUnsafe.crash("failed to allocate uid");
return uid;
}
inline bool
JS::Zone::hasUniqueId(js::gc::Cell* cell)
{
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this) || js::CurrentThreadIsPerformingGC());
return uniqueIds().has(cell);
}
inline void
JS::Zone::transferUniqueId(js::gc::Cell* tgt, js::gc::Cell* src)
{
MOZ_ASSERT(src != tgt);
MOZ_ASSERT(!IsInsideNursery(tgt));
MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(runtimeFromMainThread()));
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
MOZ_ASSERT(!uniqueIds().has(tgt));
uniqueIds().rekeyIfMoved(src, tgt);
}
inline void
JS::Zone::removeUniqueId(js::gc::Cell* cell)
{
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
uniqueIds().remove(cell);
}
inline void
JS::Zone::adoptUniqueIds(JS::Zone* source)
{
js::AutoEnterOOMUnsafeRegion oomUnsafe;
for (js::gc::UniqueIdMap::Enum e(source->uniqueIds()); !e.empty(); e.popFront()) {
MOZ_ASSERT(!uniqueIds().has(e.front().key()));
if (!uniqueIds().put(e.front().key(), e.front().value()))
oomUnsafe.crash("failed to transfer unique ids from off-thread");
}
source->uniqueIds().clear();
}
#endif // gc_Zone_inl_h

Просмотреть файл

@ -4,7 +4,7 @@
* 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 "gc/Zone.h"
#include "gc/Zone-inl.h"
#include "gc/FreeOp.h"
#include "gc/Policy.h"
@ -465,6 +465,41 @@ Zone::traceAtomCache(JSTracer* trc)
}
}
void*
Zone::onOutOfMemory(js::AllocFunction allocFunc, size_t nbytes, void* reallocPtr)
{
if (!js::CurrentThreadCanAccessRuntime(runtime_))
return nullptr;
return runtimeFromMainThread()->onOutOfMemory(allocFunc, nbytes, reallocPtr);
}
void
Zone::reportAllocationOverflow()
{
js::ReportAllocationOverflow(nullptr);
}
void
JS::Zone::maybeTriggerGCForTooMuchMalloc(js::gc::MemoryCounter& counter, TriggerKind trigger)
{
JSRuntime* rt = runtimeFromAnyThread();
if (!js::CurrentThreadCanAccessRuntime(rt))
return;
bool wouldInterruptGC = rt->gc.isIncrementalGCInProgress() && !isCollecting();
if (wouldInterruptGC && !counter.shouldResetIncrementalGC(rt->gc.tunables))
return;
if (!rt->gc.triggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC,
counter.bytes(), counter.maxBytes()))
{
return;
}
counter.recordTrigger(trigger);
}
ZoneList::ZoneList()
: head(nullptr), tail(nullptr)
{}

Просмотреть файл

@ -11,7 +11,6 @@
#include "mozilla/HashFunctions.h"
#include "gc/FindSCCs.h"
#include "gc/GCRuntime.h"
#include "js/GCHashTable.h"
#include "vm/MallocProvider.h"
#include "vm/Runtime.h"
@ -218,12 +217,8 @@ class Zone : public JS::shadow::Zone,
}
MOZ_MUST_USE void* onOutOfMemory(js::AllocFunction allocFunc, size_t nbytes,
void* reallocPtr = nullptr) {
if (!js::CurrentThreadCanAccessRuntime(runtime_))
return nullptr;
return runtimeFromMainThread()->onOutOfMemory(allocFunc, nbytes, reallocPtr);
}
void reportAllocationOverflow() { js::ReportAllocationOverflow(nullptr); }
void* reallocPtr = nullptr);
void reportAllocationOverflow();
void beginSweepTypes(bool releaseTypes);
@ -259,13 +254,6 @@ class Zone : public JS::shadow::Zone,
return needsIncrementalBarrier();
}
// If this returns true, all object tracing must be done with a GC marking
// tracer.
bool requireGCTracer() const {
JSRuntime* rt = runtimeFromAnyThread();
return RuntimeHeapIsMajorCollecting() && !rt->gc.isHeapCompacting() && gcState_ != NoGC;
}
bool shouldMarkInZone() const {
return needsIncrementalBarrier() || isGCMarking();
}
@ -274,12 +262,6 @@ class Zone : public JS::shadow::Zone,
// possibly at other times too.
uint64_t gcNumber();
bool compileBarriers() const { return compileBarriers(needsIncrementalBarrier()); }
bool compileBarriers(bool needsIncrementalBarrier) const {
return needsIncrementalBarrier ||
runtimeFromMainThread()->hasZealMode(js::gc::ZealMode::VerifierPre);
}
void setNeedsIncrementalBarrier(bool needs);
const uint32_t* addressOfNeedsIncrementalBarrier() const { return &needsIncrementalBarrier_; }
@ -292,6 +274,10 @@ class Zone : public JS::shadow::Zone,
void prepareForCompacting();
#ifdef DEBUG
// If this returns true, all object tracing must be done with a GC marking
// tracer.
bool requireGCTracer() const;
// For testing purposes, return the index of the sweep group which this zone
// was swept in in the last GC.
unsigned lastSweepGroupIndex() { return gcLastSweepGroupIndex; }
@ -443,22 +429,12 @@ class Zone : public JS::shadow::Zone,
if (MOZ_LIKELY(trigger == js::gc::NoTrigger) || trigger <= counter.triggered())
return;
if (!js::CurrentThreadCanAccessRuntime(rt))
return;
bool wouldInterruptGC = rt->gc.isIncrementalGCInProgress() && !isCollecting();
if (wouldInterruptGC && !counter.shouldResetIncrementalGC(rt->gc.tunables))
return;
if (!rt->gc.triggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC,
counter.bytes(), counter.maxBytes()))
{
return;
}
counter.recordTrigger(trigger);
maybeTriggerGCForTooMuchMalloc(counter, trigger);
}
void maybeTriggerGCForTooMuchMalloc(js::gc::MemoryCounter& counter,
js::gc::TriggerKind trigger);
js::MainThreadData<js::UniquePtr<js::RegExpZone>> regExps_;
public:
@ -484,20 +460,9 @@ class Zone : public JS::shadow::Zone,
updateMemoryCounter(jitCodeCounter, nbytes);
}
void updateAllGCMallocCountersOnGCStart() {
gcMallocCounter.updateOnGCStart();
jitCodeCounter.updateOnGCStart();
}
void updateAllGCMallocCountersOnGCEnd(const js::AutoLockGC& lock) {
auto& gc = runtimeFromAnyThread()->gc;
gcMallocCounter.updateOnGCEnd(gc.tunables, lock);
jitCodeCounter.updateOnGCEnd(gc.tunables, lock);
}
js::gc::TriggerKind shouldTriggerGCForTooMuchMalloc() {
auto& gc = runtimeFromAnyThread()->gc;
return std::max(gcMallocCounter.shouldTriggerGC(gc.tunables),
jitCodeCounter.shouldTriggerGC(gc.tunables));
}
void updateAllGCMallocCountersOnGCStart();
void updateAllGCMallocCountersOnGCEnd(const js::AutoLockGC& lock);
js::gc::TriggerKind shouldTriggerGCForTooMuchMalloc();
void keepAtoms() {
keepAtomsCount++;
@ -606,111 +571,34 @@ class Zone : public JS::shadow::Zone,
js::MainThreadData<unsigned> gcLastSweepGroupIndex;
#endif
static js::HashNumber UniqueIdToHash(uint64_t uid) {
return mozilla::HashGeneric(uid);
}
static js::HashNumber UniqueIdToHash(uint64_t uid);
// Creates a HashNumber based on getUniqueId. Returns false on OOM.
MOZ_MUST_USE bool getHashCode(js::gc::Cell* cell, js::HashNumber* hashp) {
uint64_t uid;
if (!getOrCreateUniqueId(cell, &uid))
return false;
*hashp = UniqueIdToHash(uid);
return true;
}
MOZ_MUST_USE bool getHashCode(js::gc::Cell* cell, js::HashNumber* hashp);
// Gets an existing UID in |uidp| if one exists.
MOZ_MUST_USE bool maybeGetUniqueId(js::gc::Cell* cell, uint64_t* uidp) {
MOZ_ASSERT(uidp);
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
// Get an existing uid, if one has been set.
auto p = uniqueIds().lookup(cell);
if (p)
*uidp = p->value();
return p.found();
}
MOZ_MUST_USE bool maybeGetUniqueId(js::gc::Cell* cell, uint64_t* uidp);
// Puts an existing UID in |uidp|, or creates a new UID for this Cell and
// puts that into |uidp|. Returns false on OOM.
MOZ_MUST_USE bool getOrCreateUniqueId(js::gc::Cell* cell, uint64_t* uidp) {
MOZ_ASSERT(uidp);
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this) || js::CurrentThreadIsPerformingGC());
MOZ_MUST_USE bool getOrCreateUniqueId(js::gc::Cell* cell, uint64_t* uidp);
// Get an existing uid, if one has been set.
auto p = uniqueIds().lookupForAdd(cell);
if (p) {
*uidp = p->value();
return true;
}
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
// Set a new uid on the cell.
*uidp = js::gc::NextCellUniqueId(runtimeFromAnyThread());
if (!uniqueIds().add(p, cell, *uidp))
return false;
// If the cell was in the nursery, hopefully unlikely, then we need to
// tell the nursery about it so that it can sweep the uid if the thing
// does not get tenured.
if (IsInsideNursery(cell) &&
!runtimeFromMainThread()->gc.nursery().addedUniqueIdToCell(cell))
{
uniqueIds().remove(cell);
return false;
}
return true;
}
js::HashNumber getHashCodeInfallible(js::gc::Cell* cell) {
return UniqueIdToHash(getUniqueIdInfallible(cell));
}
uint64_t getUniqueIdInfallible(js::gc::Cell* cell) {
uint64_t uid;
js::AutoEnterOOMUnsafeRegion oomUnsafe;
if (!getOrCreateUniqueId(cell, &uid))
oomUnsafe.crash("failed to allocate uid");
return uid;
}
js::HashNumber getHashCodeInfallible(js::gc::Cell* cell);
uint64_t getUniqueIdInfallible(js::gc::Cell* cell);
// Return true if this cell has a UID associated with it.
MOZ_MUST_USE bool hasUniqueId(js::gc::Cell* cell) {
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this) || js::CurrentThreadIsPerformingGC());
return uniqueIds().has(cell);
}
MOZ_MUST_USE bool hasUniqueId(js::gc::Cell* cell);
// Transfer an id from another cell. This must only be called on behalf of a
// moving GC. This method is infallible.
void transferUniqueId(js::gc::Cell* tgt, js::gc::Cell* src) {
MOZ_ASSERT(src != tgt);
MOZ_ASSERT(!IsInsideNursery(tgt));
MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(runtimeFromMainThread()));
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
MOZ_ASSERT(!uniqueIds().has(tgt));
uniqueIds().rekeyIfMoved(src, tgt);
}
void transferUniqueId(js::gc::Cell* tgt, js::gc::Cell* src);
// Remove any unique id associated with this Cell.
void removeUniqueId(js::gc::Cell* cell) {
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
uniqueIds().remove(cell);
}
void removeUniqueId(js::gc::Cell* cell);
// When finished parsing off-thread, transfer any UIDs we created in the
// off-thread zone into the target zone.
void adoptUniqueIds(JS::Zone* source) {
js::AutoEnterOOMUnsafeRegion oomUnsafe;
for (js::gc::UniqueIdMap::Enum e(source->uniqueIds()); !e.empty(); e.popFront()) {
MOZ_ASSERT(!uniqueIds().has(e.front().key()));
if (!uniqueIds().put(e.front().key(), e.front().value()))
oomUnsafe.crash("failed to transfer unique ids from off-thread");
}
source->uniqueIds().clear();
}
void adoptUniqueIds(JS::Zone* source);
#ifdef JSGC_HASH_TABLE_CHECKS
// Assert that the UniqueId table has been redirected successfully.

Просмотреть файл

@ -11,6 +11,8 @@
#include "jsapi-tests/tests.h"
#include "gc/Zone-inl.h"
static void
MinimizeHeap(JSContext* cx)
{