forked from mirrors/gecko-dev
Backed out 4 changesets (bug 1831072) for causing process crashes on Android 7 CLOSED TREE
Backed out changeset 424a49289df8 (bug 1831072) Backed out changeset cc81053765a7 (bug 1831072) Backed out changeset 7bec43b87e1d (bug 1831072) Backed out changeset 8e0f85038c59 (bug 1831072)
This commit is contained in:
parent
6a99f49fca
commit
2004dce9a4
13 changed files with 91 additions and 46 deletions
|
|
@ -7163,7 +7163,7 @@ static bool ClearMarkQueue(JSContext* cx, unsigned argc, Value* vp) {
|
|||
|
||||
static bool NurseryStringsEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(cx->zone()->allocNurseryStrings());
|
||||
args.rval().setBoolean(cx->zone()->allocNurseryStrings);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@ using namespace js;
|
|||
using namespace gc;
|
||||
|
||||
void Zone::updateNurseryAllocFlags(const Nursery& nursery) {
|
||||
allocNurseryObjects_ = nursery.isEnabled();
|
||||
allocNurseryStrings_ = nursery.isEnabled() && nursery.canAllocateStrings() &&
|
||||
!nurseryStringsDisabled;
|
||||
allocNurseryBigInts_ = nursery.isEnabled() && nursery.canAllocateBigInts() &&
|
||||
!nurseryBigIntsDisabled;
|
||||
allocNurseryObjects = nursery.isEnabled();
|
||||
allocNurseryStrings = nursery.isEnabled() && nursery.canAllocateStrings() &&
|
||||
!nurseryStringsDisabled;
|
||||
allocNurseryBigInts = nursery.isEnabled() && nursery.canAllocateBigInts() &&
|
||||
!nurseryBigIntsDisabled;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC /* = CanGC */>
|
||||
|
|
@ -63,7 +63,7 @@ void* gc::CellAllocator::AllocateObjectCell(JSContext* cx, AllocKind kind,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (heap != TenuredHeap && cx->zone()->allocNurseryObjects()) {
|
||||
if (heap != TenuredHeap && cx->zone()->allocNurseryObjects) {
|
||||
if (!site) {
|
||||
site = cx->zone()->unknownAllocSite(JS::TraceKind::Object);
|
||||
}
|
||||
|
|
@ -140,7 +140,7 @@ void* GCRuntime::tryNewNurseryStringCell(JSContext* cx, size_t thingSize,
|
|||
|
||||
// Exceeding gcMaxBytes while tenuring can disable the Nursery, and
|
||||
// other heuristics can disable nursery strings for this zone.
|
||||
if (cx->nursery().isEnabled() && cx->zone()->allocNurseryStrings()) {
|
||||
if (cx->nursery().isEnabled() && cx->zone()->allocNurseryStrings) {
|
||||
return cx->nursery().allocateString(site, thingSize);
|
||||
}
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ void* gc::CellAllocator::AllocateStringCell(JSContext* cx, AllocKind kind,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (heap != TenuredHeap && cx->zone()->allocNurseryStrings()) {
|
||||
if (heap != TenuredHeap && cx->zone()->allocNurseryStrings) {
|
||||
void* ptr = rt->gc.tryNewNurseryStringCell<allowGC>(cx, size, kind);
|
||||
if (ptr) {
|
||||
return ptr;
|
||||
|
|
@ -208,7 +208,7 @@ void* GCRuntime::tryNewNurseryBigIntCell(JSContext* cx, size_t thingSize,
|
|||
|
||||
// Exceeding gcMaxBytes while tenuring can disable the Nursery, and
|
||||
// other heuristics can disable nursery BigInts for this zone.
|
||||
if (cx->nursery().isEnabled() && cx->zone()->allocNurseryBigInts()) {
|
||||
if (cx->nursery().isEnabled() && cx->zone()->allocNurseryBigInts) {
|
||||
return cx->nursery().allocateBigInt(site, thingSize);
|
||||
}
|
||||
}
|
||||
|
|
@ -229,7 +229,7 @@ void* gc::CellAllocator::AllocateBigIntCell(JSContext* cx, InitialHeap heap) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (heap != TenuredHeap && cx->zone()->allocNurseryBigInts()) {
|
||||
if (heap != TenuredHeap && cx->zone()->allocNurseryBigInts) {
|
||||
void* ptr = rt->gc.tryNewNurseryBigIntCell<allowGC>(cx, size, kind);
|
||||
if (ptr) {
|
||||
return ptr;
|
||||
|
|
|
|||
|
|
@ -3291,7 +3291,10 @@ void GCRuntime::maybeStopPretenuring() {
|
|||
double rate = double(zone->finalizedStrings) / double(numStrings);
|
||||
if (rate > tunables.stopPretenureStringThreshold()) {
|
||||
CancelOffThreadIonCompile(zone);
|
||||
zone->forceDiscardJitCode(rt->gcContext());
|
||||
bool preserving = zone->isPreservingCode();
|
||||
zone->setPreservingCode(false);
|
||||
zone->discardJitCode(rt->gcContext());
|
||||
zone->setPreservingCode(preserving);
|
||||
for (RealmsInZoneIter r(zone); !r.done(); r.next()) {
|
||||
if (jit::JitRealm* jitRealm = r->jitRealm()) {
|
||||
jitRealm->discardStubs();
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ void js::ReleaseAllJITCode(JS::GCContext* gcx) {
|
|||
js::CancelOffThreadIonCompile(gcx->runtime());
|
||||
|
||||
for (ZonesIter zone(gcx->runtime(), SkipAtoms); !zone.done(); zone.next()) {
|
||||
zone->forceDiscardJitCode(gcx);
|
||||
zone->setPreservingCode(false);
|
||||
zone->discardJitCode(gcx);
|
||||
}
|
||||
|
||||
for (RealmsIter realm(gcx->runtime()); !realm.done(); realm.next()) {
|
||||
|
|
|
|||
|
|
@ -862,6 +862,17 @@ void js::Nursery::renderProfileJSON(JSONPrinter& json) const {
|
|||
stats().allocsSinceMinorGCTenured());
|
||||
}
|
||||
|
||||
if (stats().getStat(gcstats::STAT_NURSERY_STRING_REALMS_DISABLED)) {
|
||||
json.property(
|
||||
"nursery_string_realms_disabled",
|
||||
stats().getStat(gcstats::STAT_NURSERY_STRING_REALMS_DISABLED));
|
||||
}
|
||||
if (stats().getStat(gcstats::STAT_NURSERY_BIGINT_REALMS_DISABLED)) {
|
||||
json.property(
|
||||
"nursery_bigint_realms_disabled",
|
||||
stats().getStat(gcstats::STAT_NURSERY_BIGINT_REALMS_DISABLED));
|
||||
}
|
||||
|
||||
json.beginObjectProperty("phase_times");
|
||||
|
||||
#define EXTRACT_NAME(name, text) #name,
|
||||
|
|
@ -1542,8 +1553,11 @@ size_t js::Nursery::doPretenuring(JSRuntime* rt, JS::GCReason reason,
|
|||
reason, JS::GCReason::FULL_CELL_PTR_BIGINT_BUFFER);
|
||||
}
|
||||
|
||||
mozilla::Maybe<AutoGCSession> session;
|
||||
uint32_t numStringsTenured = 0;
|
||||
uint32_t numNurseryStringRealmsDisabled = 0;
|
||||
uint32_t numBigIntsTenured = 0;
|
||||
uint32_t numNurseryBigIntRealmsDisabled = 0;
|
||||
for (ZonesIter zone(gc, SkipAtoms); !zone.done(); zone.next()) {
|
||||
// For some tests in JetStream2 and Kraken, the tenuredRate is high but the
|
||||
// number of allocated strings is low. So we calculate the tenuredRate only
|
||||
|
|
@ -1558,19 +1572,28 @@ size_t js::Nursery::doPretenuring(JSRuntime* rt, JS::GCReason reason,
|
|||
allocThreshold ? double(zoneTenuredStrings) / double(zoneNurseryStrings)
|
||||
: 0.0;
|
||||
bool disableNurseryStrings =
|
||||
pretenureStr && zone->allocNurseryStrings() &&
|
||||
pretenureStr && zone->allocNurseryStrings &&
|
||||
tenuredRate > tunables().pretenureStringThreshold();
|
||||
bool disableNurseryBigInts = pretenureBigInt &&
|
||||
zone->allocNurseryBigInts() &&
|
||||
bool disableNurseryBigInts = pretenureBigInt && zone->allocNurseryBigInts &&
|
||||
zone->tenuredBigInts >= 30 * 1000;
|
||||
if (disableNurseryStrings || disableNurseryBigInts) {
|
||||
if (!session.isSome()) {
|
||||
session.emplace(gc, JS::HeapState::MinorCollecting);
|
||||
}
|
||||
CancelOffThreadIonCompile(zone);
|
||||
zone->forceDiscardJitCode(rt->gcContext());
|
||||
bool preserving = zone->isPreservingCode();
|
||||
zone->setPreservingCode(false);
|
||||
zone->discardJitCode(rt->gcContext());
|
||||
zone->setPreservingCode(preserving);
|
||||
for (RealmsInZoneIter r(zone); !r.done(); r.next()) {
|
||||
if (jit::JitRealm* jitRealm = r->jitRealm()) {
|
||||
jitRealm->discardStubs();
|
||||
if (disableNurseryStrings) {
|
||||
jitRealm->setStringsCanBeInNursery(false);
|
||||
numNurseryStringRealmsDisabled++;
|
||||
}
|
||||
if (disableNurseryBigInts) {
|
||||
numNurseryBigIntRealmsDisabled++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1586,7 +1609,12 @@ size_t js::Nursery::doPretenuring(JSRuntime* rt, JS::GCReason reason,
|
|||
numBigIntsTenured += zone->tenuredBigInts;
|
||||
zone->tenuredBigInts = 0;
|
||||
}
|
||||
session.reset(); // End the minor GC session, if running one.
|
||||
stats().setStat(gcstats::STAT_NURSERY_STRING_REALMS_DISABLED,
|
||||
numNurseryStringRealmsDisabled);
|
||||
stats().setStat(gcstats::STAT_STRINGS_TENURED, numStringsTenured);
|
||||
stats().setStat(gcstats::STAT_NURSERY_BIGINT_REALMS_DISABLED,
|
||||
numNurseryBigIntRealmsDisabled);
|
||||
stats().setStat(gcstats::STAT_BIGINTS_TENURED, numBigIntsTenured);
|
||||
|
||||
return sitesPretenured;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ JS_PUBLIC_API void JS::SetSiteBasedPretenuringEnabled(bool enable) {
|
|||
SiteBasedPretenuringEnabled = enable;
|
||||
}
|
||||
|
||||
class PretenuringNursery::MaybeGCSession
|
||||
: public mozilla::Maybe<AutoGCSession> {};
|
||||
|
||||
bool PretenuringNursery::canCreateAllocSite() {
|
||||
MOZ_ASSERT(allocSitesCreated <= MaxAllocSitesPerMinorGC);
|
||||
return SiteBasedPretenuringEnabled &&
|
||||
|
|
@ -80,6 +83,8 @@ size_t PretenuringNursery::doPretenuring(GCRuntime* gc, JS::GCReason reason,
|
|||
bool validPromotionRate,
|
||||
double promotionRate, bool reportInfo,
|
||||
size_t reportThreshold) {
|
||||
MaybeGCSession session;
|
||||
|
||||
size_t sitesActive = 0;
|
||||
size_t sitesPretenured = 0;
|
||||
size_t sitesInvalidated = 0;
|
||||
|
|
@ -123,7 +128,7 @@ size_t PretenuringNursery::doPretenuring(GCRuntime* gc, JS::GCReason reason,
|
|||
|
||||
if (site->isNormal()) {
|
||||
processSite(gc, site, sitesActive, sitesPretenured, sitesInvalidated,
|
||||
reportInfo, reportThreshold);
|
||||
session, reportInfo, reportThreshold);
|
||||
}
|
||||
|
||||
site = next;
|
||||
|
|
@ -156,7 +161,8 @@ size_t PretenuringNursery::doPretenuring(GCRuntime* gc, JS::GCReason reason,
|
|||
void PretenuringNursery::processSite(GCRuntime* gc, AllocSite* site,
|
||||
size_t& sitesActive,
|
||||
size_t& sitesPretenured,
|
||||
size_t& sitesInvalidated, bool reportInfo,
|
||||
size_t& sitesInvalidated,
|
||||
MaybeGCSession& session, bool reportInfo,
|
||||
size_t reportThreshold) {
|
||||
sitesActive++;
|
||||
|
||||
|
|
@ -180,6 +186,11 @@ void PretenuringNursery::processSite(GCRuntime* gc, AllocSite* site,
|
|||
|
||||
// We can optimize JIT code before we realise that a site should be
|
||||
// pretenured. Make sure we invalidate any existing optimized code.
|
||||
|
||||
if (!session.isSome()) {
|
||||
session.emplace(gc, JS::HeapState::MinorCollecting);
|
||||
}
|
||||
|
||||
if (site->hasScript()) {
|
||||
wasInvalidated = site->invalidateScript(gc);
|
||||
if (wasInvalidated) {
|
||||
|
|
|
|||
|
|
@ -334,9 +334,11 @@ class PretenuringNursery {
|
|||
void* addressOfAllocatedSites() { return &allocatedSites; }
|
||||
|
||||
private:
|
||||
class MaybeGCSession;
|
||||
void processSite(GCRuntime* gc, AllocSite* site, size_t& sitesActive,
|
||||
size_t& sitesPretenured, size_t& sitesInvalidated,
|
||||
bool reportInfo, size_t reportThreshold);
|
||||
MaybeGCSession& session, bool reportInfo,
|
||||
size_t reportThreshold);
|
||||
void processCatchAllSite(AllocSite* site, bool reportInfo,
|
||||
size_t reportThreshold);
|
||||
void updateAllocCounts(AllocSite* site);
|
||||
|
|
|
|||
|
|
@ -67,9 +67,17 @@ enum Stat {
|
|||
// Number of strings deduplicated.
|
||||
STAT_STRINGS_DEDUPLICATED,
|
||||
|
||||
// Number of realms that had nursery strings disabled due to large numbers
|
||||
// being tenured.
|
||||
STAT_NURSERY_STRING_REALMS_DISABLED,
|
||||
|
||||
// Number of BigInts tenured.
|
||||
STAT_BIGINTS_TENURED,
|
||||
|
||||
// Number of realms that had nursery BigInts disabled due to large numbers
|
||||
// being tenured.
|
||||
STAT_NURSERY_BIGINT_REALMS_DISABLED,
|
||||
|
||||
STAT_LIMIT
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -161,9 +161,8 @@ JS::Zone::Zone(JSRuntime* rt, Kind kind)
|
|||
tenuredBigInts(0),
|
||||
markedStrings(0),
|
||||
finalizedStrings(0),
|
||||
allocNurseryObjects_(true),
|
||||
allocNurseryStrings_(true),
|
||||
allocNurseryBigInts_(true),
|
||||
allocNurseryStrings(true),
|
||||
allocNurseryBigInts(true),
|
||||
suppressAllocationMetadataBuilder(false),
|
||||
pretenuring(this),
|
||||
compartments_(),
|
||||
|
|
@ -386,17 +385,14 @@ void Zone::checkStringWrappersAfterMovingGC() {
|
|||
#endif
|
||||
|
||||
void Zone::discardJitCode(JS::GCContext* gcx, const DiscardOptions& options) {
|
||||
if (!isPreservingCode()) {
|
||||
forceDiscardJitCode(gcx, options);
|
||||
}
|
||||
}
|
||||
|
||||
void Zone::forceDiscardJitCode(JS::GCContext* gcx,
|
||||
const DiscardOptions& options) {
|
||||
if (!jitZone()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPreservingCode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.discardJitScripts && options.discardBaselineCode) {
|
||||
lastDiscardedCodeTime_ = mozilla::TimeStamp::Now();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,14 +181,12 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
|
|||
js::MainThreadData<bool> nurseryStringsDisabled;
|
||||
js::MainThreadData<bool> nurseryBigIntsDisabled;
|
||||
|
||||
private:
|
||||
// Flags dynamically updated based on more than one condition, including the
|
||||
// flags above.
|
||||
js::MainThreadData<bool> allocNurseryObjects_;
|
||||
js::MainThreadData<bool> allocNurseryStrings_;
|
||||
js::MainThreadData<bool> allocNurseryBigInts_;
|
||||
js::MainThreadData<bool> allocNurseryObjects;
|
||||
js::MainThreadData<bool> allocNurseryStrings;
|
||||
js::MainThreadData<bool> allocNurseryBigInts;
|
||||
|
||||
public:
|
||||
// When true, skip calling the metadata callback. We use this:
|
||||
// - to avoid invoking the callback recursively;
|
||||
// - to avoid observing lazy prototype setup (which confuses callbacks that
|
||||
|
|
@ -329,10 +327,6 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
|
|||
void discardJitCode(JS::GCContext* gcx,
|
||||
const DiscardOptions& options = DiscardOptions());
|
||||
|
||||
// Discard JIT code regardless of isPreservingCode().
|
||||
void forceDiscardJitCode(JS::GCContext* gcx,
|
||||
const DiscardOptions& options = DiscardOptions());
|
||||
|
||||
void resetAllocSitesAndInvalidate(bool resetNurserySites,
|
||||
bool resetPretenuredSites);
|
||||
|
||||
|
|
@ -471,9 +465,6 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
|
|||
void fixupScriptMapsAfterMovingGC(JSTracer* trc);
|
||||
|
||||
void updateNurseryAllocFlags(const js::Nursery& nursery);
|
||||
bool allocNurseryObjects() const { return allocNurseryObjects_; }
|
||||
bool allocNurseryStrings() const { return allocNurseryStrings_; }
|
||||
bool allocNurseryBigInts() const { return allocNurseryBigInts_; }
|
||||
|
||||
mozilla::LinkedList<detail::WeakCacheBase>& weakCaches() {
|
||||
return weakCaches_.ref();
|
||||
|
|
|
|||
|
|
@ -5764,7 +5764,10 @@ bool CacheIRCompiler::emitStoreTypedArrayElement(ObjOperandId objId,
|
|||
|
||||
static gc::InitialHeap InitialBigIntHeap(JSContext* cx) {
|
||||
JS::Zone* zone = cx->zone();
|
||||
return zone->allocNurseryBigInts() ? gc::DefaultHeap : gc::TenuredHeap;
|
||||
bool canNurseryAllocate =
|
||||
zone->runtimeFromAnyThread()->gc.nursery().canAllocateBigInts() &&
|
||||
zone->allocNurseryBigInts;
|
||||
return canNurseryAllocate ? gc::DefaultHeap : gc::TenuredHeap;
|
||||
}
|
||||
|
||||
static void EmitAllocateBigInt(MacroAssembler& masm, Register result,
|
||||
|
|
|
|||
|
|
@ -172,11 +172,13 @@ void* CompileZone::addressOfNurseryAllocatedSites() {
|
|||
}
|
||||
|
||||
bool CompileZone::canNurseryAllocateStrings() {
|
||||
return zone()->allocNurseryStrings();
|
||||
return zone()->runtimeFromAnyThread()->gc.nursery().canAllocateStrings() &&
|
||||
zone()->allocNurseryStrings;
|
||||
}
|
||||
|
||||
bool CompileZone::canNurseryAllocateBigInts() {
|
||||
return zone()->allocNurseryBigInts();
|
||||
return zone()->runtimeFromAnyThread()->gc.nursery().canAllocateBigInts() &&
|
||||
zone()->allocNurseryBigInts;
|
||||
}
|
||||
|
||||
gc::AllocSite* CompileZone::catchAllAllocSite(JS::TraceKind traceKind,
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ bool Realm::ensureJitRealmExists(JSContext* cx) {
|
|||
return false;
|
||||
}
|
||||
|
||||
jitRealm->initialize(zone()->allocNurseryStrings());
|
||||
jitRealm->initialize(zone()->allocNurseryStrings);
|
||||
|
||||
jitRealm_ = std::move(jitRealm);
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Reference in a new issue