Bug 1569564 - Remove the original malloc counter infrastructure r=sfink

Differential Revision: https://phabricator.services.mozilla.com/D39735

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jon Coppeard 2019-07-31 09:13:36 +00:00
parent 9730094120
commit 2d89bbf3df
20 changed files with 6 additions and 253 deletions

View File

@ -2502,10 +2502,6 @@ void nsJSContext::EnsureStatics() {
FetchUtil::ReportJSStreamError);
// Set these global xpconnect options...
Preferences::RegisterCallbackAndCall(SetMemoryPrefChangedCallbackMB,
"javascript.options.mem.high_water_mark",
(void*)JSGC_MAX_MALLOC_BYTES);
Preferences::RegisterCallbackAndCall(SetMemoryPrefChangedCallbackMB,
"javascript.options.mem.max",
(void*)JSGC_MAX_BYTES);

View File

@ -27,7 +27,6 @@ struct JSSettings {
enum {
// All the GC parameters that we support.
JSSettings_JSGC_MAX_BYTES = 0,
JSSettings_JSGC_MAX_MALLOC_BYTES,
JSSettings_JSGC_HIGH_FREQUENCY_TIME_LIMIT,
JSSettings_JSGC_LOW_FREQUENCY_HEAP_GROWTH,
JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN,

View File

@ -432,14 +432,6 @@ void LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) {
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "high_water_mark");
if (memPrefName == matchName || (gRuntimeServiceDuringInit && index == 1)) {
int32_t prefValue = GetWorkerPref(matchName, 128);
UpdateOtherJSGCMemoryOption(rts, JSGC_MAX_MALLOC_BYTES,
uint32_t(prefValue) * 1024 * 1024);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_high_frequency_time_limit_ms");
if (memPrefName == matchName || (gRuntimeServiceDuringInit && index == 2)) {

View File

@ -80,14 +80,6 @@ typedef enum JSGCParamKey {
*/
JSGC_MAX_BYTES = 0,
/**
* Initial value for the malloc bytes threshold.
*
* Pref: javascript.options.mem.high_water_mark
* Default: TuningDefaults::MaxMallocBytes
*/
JSGC_MAX_MALLOC_BYTES = 1,
/**
* Maximum size of the generational GC nurseries.
*

View File

@ -494,7 +494,6 @@ static bool MinorGC(JSContext* cx, unsigned argc, Value* vp) {
#define FOR_EACH_GC_PARAM(_) \
_("maxBytes", JSGC_MAX_BYTES, true) \
_("maxMallocBytes", JSGC_MAX_MALLOC_BYTES, true) \
_("minNurseryBytes", JSGC_MIN_NURSERY_BYTES, true) \
_("maxNurseryBytes", JSGC_MAX_NURSERY_BYTES, true) \
_("gcBytes", JSGC_BYTES, false) \
@ -587,7 +586,6 @@ static bool GCParameter(JSContext* cx, unsigned argc, Value* vp) {
if (disableOOMFunctions) {
switch (param) {
case JSGC_MAX_BYTES:
case JSGC_MAX_MALLOC_BYTES:
case JSGC_MAX_NURSERY_BYTES:
args.rval().setUndefined();
return true;

View File

@ -285,9 +285,6 @@ namespace TuningDefaults {
/* JSGC_ALLOCATION_THRESHOLD */
static const size_t GCZoneAllocThresholdBase = 30 * 1024 * 1024;
/* JSGC_MAX_MALLOC_BYTES */
static const size_t MaxMallocBytes = 128 * 1024 * 1024;
/*
* JSGC_MIN_NURSERY_BYTES
*
@ -303,15 +300,6 @@ static const float AllocThresholdFactor = 0.9f;
/* JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT */
static const float AllocThresholdFactorAvoidInterrupt = 0.9f;
/* no parameter */
static const float MallocThresholdGrowFactor = 1.5f;
/* no parameter */
static const float MallocThresholdShrinkFactor = 0.9f;
/* no parameter */
static const size_t MallocThresholdLimit = 1024 * 1024 * 1024;
/* JSGC_ZONE_ALLOC_DELAY_KB */
static const size_t ZoneAllocDelayBytes = 1024 * 1024;
@ -1345,7 +1333,6 @@ bool GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes) {
MOZ_ALWAYS_TRUE(tunables.setParameter(JSGC_MAX_BYTES, maxbytes, lock));
MOZ_ALWAYS_TRUE(
tunables.setParameter(JSGC_MAX_NURSERY_BYTES, maxNurseryBytes, lock));
setMaxMallocBytes(TuningDefaults::MaxMallocBytes, lock);
const char* size = getenv("JSGC_MARK_STACK_LIMIT");
if (size) {
@ -1442,9 +1429,6 @@ bool GCRuntime::setParameter(JSGCParamKey key, uint32_t value,
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
switch (key) {
case JSGC_MAX_MALLOC_BYTES:
setMaxMallocBytes(value, lock);
break;
case JSGC_SLICE_TIME_BUDGET_MS:
defaultTimeBudgetMS_ = value ? value : SliceBudget::UnlimitedTimeBudget;
break;
@ -1627,10 +1611,6 @@ bool GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value,
return true;
}
void GCSchedulingTunables::setMaxMallocBytes(size_t value) {
maxMallocBytes_ = std::min(value, TuningDefaults::MallocThresholdLimit);
}
void GCSchedulingTunables::setHighFrequencyLowLimit(size_t newLimit) {
highFrequencyLowLimitBytes_ = newLimit;
if (highFrequencyLowLimitBytes_ >= highFrequencyHighLimitBytes_) {
@ -1688,7 +1668,6 @@ void GCSchedulingTunables::setMaxEmptyChunkCount(uint32_t value) {
GCSchedulingTunables::GCSchedulingTunables()
: gcMaxBytes_(0),
maxMallocBytes_(TuningDefaults::MaxMallocBytes),
gcMinNurseryBytes_(TuningDefaults::GCMinNurseryBytes),
gcMaxNurseryBytes_(0),
gcZoneAllocThresholdBase_(TuningDefaults::GCZoneAllocThresholdBase),
@ -1722,9 +1701,6 @@ void GCRuntime::resetParameter(JSGCParamKey key, AutoLockGC& lock) {
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
switch (key) {
case JSGC_MAX_MALLOC_BYTES:
setMaxMallocBytes(TuningDefaults::MaxMallocBytes, lock);
break;
case JSGC_SLICE_TIME_BUDGET_MS:
defaultTimeBudgetMS_ = TuningDefaults::DefaultTimeBudgetMS;
break;
@ -1831,8 +1807,6 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) {
switch (key) {
case JSGC_MAX_BYTES:
return uint32_t(tunables.gcMaxBytes());
case JSGC_MAX_MALLOC_BYTES:
return uint32_t(tunables.maxMallocBytes());
case JSGC_MIN_NURSERY_BYTES:
MOZ_ASSERT(tunables.gcMinNurseryBytes() < UINT32_MAX);
return uint32_t(tunables.gcMinNurseryBytes());
@ -2091,10 +2065,6 @@ extern JS_FRIEND_API void js::RemoveRawValueRoot(JSContext* cx, Value* vp) {
cx->runtime()->gc.removeRoot(vp);
}
void GCRuntime::setMaxMallocBytes(size_t value, const AutoLockGC& lock) {
tunables.setMaxMallocBytes(value);
}
float ZoneThreshold::eagerAllocTrigger(bool highFrequencyGC) const {
float eagerTriggerFactor = highFrequencyGC
? HighFrequencyEagerAllocTriggerFactor
@ -2192,47 +2162,6 @@ void ZoneMallocThreshold::updateAfterGC(size_t lastBytes, size_t baseBytes,
computeZoneTriggerBytes(growthFactor, lastBytes, baseBytes, lock);
}
MemoryCounter::MemoryCounter()
: bytes_(0), maxBytes_(0), triggered_(NoTrigger) {}
void MemoryCounter::updateOnGCStart() {
// Record the current byte count at the start of GC.
bytesAtStartOfGC_ = bytes_;
}
void MemoryCounter::updateOnGCEnd(const GCSchedulingTunables& tunables,
const AutoLockGC& lock) {
// Update the trigger threshold at the end of GC and adjust the current
// byte count to reflect bytes allocated since the start of GC.
MOZ_ASSERT(bytes_ >= bytesAtStartOfGC_);
if (shouldTriggerGC(tunables)) {
maxBytes_ =
std::min(TuningDefaults::MallocThresholdLimit,
size_t(maxBytes_ * TuningDefaults::MallocThresholdGrowFactor));
} else {
maxBytes_ = std::max(
tunables.maxMallocBytes(),
size_t(maxBytes_ * TuningDefaults::MallocThresholdShrinkFactor));
}
bytes_ -= bytesAtStartOfGC_;
triggered_ = NoTrigger;
}
void MemoryCounter::setMax(size_t newMax, const AutoLockGC& lock) {
maxBytes_ = newMax;
}
void MemoryCounter::adopt(MemoryCounter& other) {
update(other.bytes());
other.bytes_ = 0;
other.triggered_ = NoTrigger;
}
void MemoryCounter::recordTrigger(TriggerKind trigger) {
MOZ_ASSERT(trigger > triggered_);
triggered_ = trigger;
}
/* Compacting GC */
bool js::gc::IsCurrentlyAnimating(const TimeStamp& lastAnimationTime,
@ -7536,15 +7465,6 @@ GCRuntime::IncrementalResult GCRuntime::budgetIncrementalGC(
}
}
if (zone->shouldTriggerGCForTooMuchMalloc() == NonIncrementalTrigger) {
CheckZoneIsScheduled(zone, reason, "malloc bytes");
budget.makeUnlimited();
stats().nonincremental(AbortReason::MallocBytesTrigger);
if (zone->wasGCStarted() && zone->gcState() > Zone::Sweep) {
resetReason = AbortReason::MallocBytesTrigger;
}
}
if (isIncrementalGCInProgress() &&
zone->isGCScheduled() != zone->wasGCStarted()) {
budget.makeUnlimited();
@ -7587,11 +7507,6 @@ static void ScheduleZones(GCRuntime* gc) {
zone->gcJitBytes.gcBytes() >= zone->gcJitThreshold.gcTriggerBytes()) {
zone->scheduleGC();
}
// This ensures we collect zones that have reached the malloc limit.
if (zone->shouldTriggerGCForTooMuchMalloc()) {
zone->scheduleGC();
}
}
}

View File

@ -372,8 +372,6 @@ class GCRuntime {
MOZ_MUST_USE bool addBlackRootsTracer(JSTraceDataOp traceOp, void* data);
void removeBlackRootsTracer(JSTraceDataOp traceOp, void* data);
void setMaxMallocBytes(size_t value, const AutoLockGC& lock);
void updateMemoryCountersOnGCStart();
void setGCCallback(JSGCCallback callback, void* data);

View File

@ -162,8 +162,8 @@
* maybeGC. The reason for this is that this check is made after the
* allocation and we cannot GC with an uninitialized thing in the heap.
*
* 11) Do an incremental, zonal GC with reason TOO_MUCH_MALLOC when we have
* malloced more than JSGC_MAX_MALLOC_BYTES in a zone since the last GC.
* 11) Do an incremental, zonal GC with reason TOO_MUCH_MALLOC when the total amount
* of malloced memory is greater than the malloc trigger limit for the zone.
*
*
* Size Limitation Triggers Explanation
@ -323,8 +323,6 @@ namespace gc {
struct Cell;
enum TriggerKind { NoTrigger = 0, IncrementalTrigger, NonIncrementalTrigger };
/*
* Encapsulates all of the GC tunables. These are effectively constant and
* should only be modified by setParameter.
@ -337,13 +335,6 @@ class GCSchedulingTunables {
*/
UnprotectedData<size_t> gcMaxBytes_;
/*
* JSGC_MAX_MALLOC_BYTES
*
* Initial malloc bytes threshold.
*/
UnprotectedData<size_t> maxMallocBytes_;
/*
* JSGC_MIN_NURSERY_BYTES
* JSGC_MAX_NURSERY_BYTES
@ -493,7 +484,6 @@ class GCSchedulingTunables {
GCSchedulingTunables();
size_t gcMaxBytes() const { return gcMaxBytes_; }
size_t maxMallocBytes() const { return maxMallocBytes_; }
size_t gcMinNurseryBytes() const { return gcMinNurseryBytes_; }
size_t gcMaxNurseryBytes() const { return gcMaxNurseryBytes_; }
size_t gcZoneAllocThresholdBase() const { return gcZoneAllocThresholdBase_; }
@ -546,8 +536,6 @@ class GCSchedulingTunables {
const AutoLockGC& lock);
void resetParameter(JSGCParamKey key, const AutoLockGC& lock);
void setMaxMallocBytes(size_t value);
private:
void setHighFrequencyLowLimit(size_t value);
void setHighFrequencyHighLimit(size_t value);
@ -581,60 +569,6 @@ class GCSchedulingState {
}
};
class MemoryCounter {
// Bytes counter to measure memory pressure for GC scheduling. It counts
// upwards from zero.
mozilla::Atomic<size_t, mozilla::ReleaseAcquire,
mozilla::recordreplay::Behavior::DontPreserve>
bytes_;
// GC trigger threshold for memory allocations.
size_t maxBytes_;
// The counter value at the start of a GC.
MainThreadData<size_t> bytesAtStartOfGC_;
// Which kind of GC has been triggered if any.
mozilla::Atomic<TriggerKind, mozilla::ReleaseAcquire,
mozilla::recordreplay::Behavior::DontPreserve>
triggered_;
public:
MemoryCounter();
size_t bytes() const { return bytes_; }
size_t maxBytes() const { return maxBytes_; }
TriggerKind triggered() const { return triggered_; }
void setMax(size_t newMax, const AutoLockGC& lock);
void update(size_t bytes) { bytes_ += bytes; }
void adopt(MemoryCounter& other);
TriggerKind shouldTriggerGC(const GCSchedulingTunables& tunables) const {
if (MOZ_LIKELY(bytes_ < maxBytes_ * tunables.allocThresholdFactor())) {
return NoTrigger;
}
if (bytes_ < maxBytes_) {
return IncrementalTrigger;
}
return NonIncrementalTrigger;
}
bool shouldResetIncrementalGC(const GCSchedulingTunables& tunables) const {
return bytes_ > maxBytes_ * tunables.allocThresholdFactorAvoidInterrupt();
}
void recordTrigger(TriggerKind trigger);
void updateOnGCStart();
void updateOnGCEnd(const GCSchedulingTunables& tunables,
const AutoLockGC& lock);
};
/*
* Tracks the used sizes for owned heap data and automatically maintains the
* memory usage relationship between GCRuntime and Zones.

View File

@ -557,29 +557,6 @@ void ZoneAllocator::reportAllocationOverflow() const {
js::ReportAllocationOverflow(nullptr);
}
void ZoneAllocator::maybeTriggerGCForTooMuchMalloc(
js::gc::MemoryCounter& counter, TriggerKind trigger) {
JSRuntime* rt = runtimeFromAnyThread();
if (!js::CurrentThreadCanAccessRuntime(rt)) {
return;
}
auto zone = JS::Zone::from(this);
bool wouldInterruptGC =
rt->gc.isIncrementalGCInProgress() && !zone->isCollecting();
if (wouldInterruptGC && !counter.shouldResetIncrementalGC(rt->gc.tunables)) {
return;
}
if (!rt->gc.triggerZoneGC(zone, JS::GCReason::TOO_MUCH_MALLOC,
counter.bytes(), counter.maxBytes())) {
return;
}
counter.recordTrigger(trigger);
}
#ifdef DEBUG
void MemoryTracker::adopt(MemoryTracker& other) {

View File

@ -46,8 +46,6 @@ class ZoneAllocator : public JS::shadow::Zone,
void* reallocPtr = nullptr);
void reportAllocationOverflow() const;
void updateMallocCounter(size_t nbytes) {}
void adoptMallocBytes(ZoneAllocator* other) {
gcMallocBytes.adopt(other->gcMallocBytes);
gcJitBytes.adopt(other->gcJitBytes);
@ -59,9 +57,6 @@ class ZoneAllocator : public JS::shadow::Zone,
void updateMemoryCountersOnGCStart();
void updateGCThresholds(gc::GCRuntime& gc, JSGCInvocationKind invocationKind,
const js::AutoLockGC& lock);
js::gc::TriggerKind shouldTriggerGCForTooMuchMalloc() {
return gc::NoTrigger;
}
// Memory accounting APIs for malloc memory owned by GC cells.
@ -160,22 +155,6 @@ class ZoneAllocator : public JS::shadow::Zone,
}
}
void updateMemoryCounter(js::gc::MemoryCounter& counter, size_t nbytes) {
JSRuntime* rt = runtimeFromAnyThread();
counter.update(nbytes);
auto trigger = counter.shouldTriggerGC(rt->gc.tunables);
if (MOZ_LIKELY(trigger == js::gc::NoTrigger) ||
trigger <= counter.triggered()) {
return;
}
maybeTriggerGCForTooMuchMalloc(counter, trigger);
}
void maybeTriggerGCForTooMuchMalloc(js::gc::MemoryCounter& counter,
js::gc::TriggerKind trigger);
public:
// Track GC heap size under this Zone.
js::gc::HeapSize zoneSize;

View File

@ -1,6 +0,0 @@
gcslice(0);
function testChangeParam(key) {
let prev = gcparam(key);
gcparam(key, prev);
}
testChangeParam("maxMallocBytes");

View File

@ -35,7 +35,6 @@ testGetParam("unusedChunks");
testGetParam("totalChunks");
testChangeParam("maxBytes");
testChangeParam("maxMallocBytes");
testChangeParam("mode");
testChangeParam("sliceTimeBudgetMS");
testChangeParam("markStackLimit");

View File

@ -1295,7 +1295,6 @@ JS_PUBLIC_API void JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx,
};
static const JSGCConfig minimal[] = {
{JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
{JSGC_SLICE_TIME_BUDGET_MS, 30},
{JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
{JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 40},
@ -1310,7 +1309,6 @@ JS_PUBLIC_API void JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx,
{JSGC_MODE, JSGC_MODE_ZONE_INCREMENTAL}};
static const JSGCConfig nominal[] = {
{JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
{JSGC_SLICE_TIME_BUDGET_MS, 30},
{JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000},
{JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500},

View File

@ -94,12 +94,6 @@ JSFlatString* StringBuffer::finishStringInternal(JSContext* cx) {
return nullptr;
}
/*
* The allocation was made on a TempAllocPolicy, so account for the string
* data on the string's zone.
*/
cx->updateMallocCounter(sizeof(CharT) * len);
return str;
}

View File

@ -1463,12 +1463,6 @@ void JSContext::resetJitStackLimit() {
void JSContext::initJitStackLimit() { resetJitStackLimit(); }
void JSContext::updateMallocCounter(size_t nbytes) {
if (zone()) {
zone()->updateMallocCounter(nbytes);
}
}
#ifdef JS_CRASH_DIAGNOSTICS
void ContextChecks::check(AbstractFramePtr frame, int argIndex) {
if (frame) {

View File

@ -264,12 +264,9 @@ struct JSContext : public JS::RootingContext,
if (!p) {
return nullptr;
}
updateMallocCounter(bytes);
return p;
}
void updateMallocCounter(size_t nbytes);
void reportAllocationOverflow() { js::ReportAllocationOverflow(this); }
void noteTenuredAlloc() { allocsThisZoneSinceMinorGC_++; }

View File

@ -1857,8 +1857,6 @@ class ScriptSource::LoadSourceMatcher {
return false;
}
cx_->updateMallocCounter(length * sizeof(Unit));
return true;
}

View File

@ -206,6 +206,10 @@ struct MallocProvider {
private:
Client* client() { return static_cast<Client*>(this); }
// The Default implementation is a no-op which can be overridden by the
// client.
void updateMallocCounter(size_t nbytes) {}
};
} /* namespace js */

View File

@ -390,7 +390,6 @@ MOZ_ALWAYS_INLINE JSExternalString* JSExternalString::new_(
}
str->init(chars, length, fin);
size_t nbytes = (length + 1) * sizeof(char16_t);
cx->updateMallocCounter(nbytes);
MOZ_ASSERT(str->isTenured());
js::AddCellMemory(str, nbytes, js::MemoryUse::StringContents);

View File

@ -1224,10 +1224,6 @@ pref("javascript.options.discardSystemSource", false);
// change the defaults here please also consider changing them in
// js/src/jsgc.cpp. They're documented in js/src/jsapi.h.
// JSGC_MAX_MALLOC_BYTES
// How much malloc memory can be allocated before triggering a GC, in MB.
pref("javascript.options.mem.high_water_mark", 128);
// JSGC_MAX_BYTES
// SpiderMonkey defaults to 2^32-1 bytes, but this is measured in MB so that
// cannot be represented directly in order to show it in about:config.