Backed out changeset aa3c5d257b1e (bug 1490042) for causing topcrash bug 1491530.

This commit is contained in:
Ryan VanderMeulen 2018-09-17 13:25:33 -04:00
Родитель 4d3821f569
Коммит 7dfaaa045e
11 изменённых файлов: 79 добавлений и 195 удалений

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

@ -975,23 +975,6 @@ GCPreserveCode(JSContext* cx, unsigned argc, Value* vp)
#ifdef JS_GC_ZEAL
static bool
ParseGCZealMode(JSContext* cx, const CallArgs& args, uint8_t* zeal)
{
uint32_t value;
if (!ToUint32(cx, args.get(0), &value)) {
return false;
}
if (value > uint32_t(gc::ZealMode::Limit)) {
JS_ReportErrorASCII(cx, "gczeal argument out of range");
return false;
}
*zeal = static_cast<uint8_t>(value);
return true;
}
static bool
GCZeal(JSContext* cx, unsigned argc, Value* vp)
{
@ -1003,8 +986,13 @@ GCZeal(JSContext* cx, unsigned argc, Value* vp)
return false;
}
uint8_t zeal;
if (!ParseGCZealMode(cx, args, &zeal)) {
uint32_t zeal;
if (!ToUint32(cx, args.get(0), &zeal)) {
return false;
}
if (zeal > uint32_t(gc::ZealMode::Limit)) {
JS_ReportErrorASCII(cx, "gczeal argument out of range");
return false;
}
@ -1015,28 +1003,7 @@ GCZeal(JSContext* cx, unsigned argc, Value* vp)
}
}
JS_SetGCZeal(cx, zeal, frequency);
args.rval().setUndefined();
return true;
}
static bool
UnsetGCZeal(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() > 1) {
RootedObject callee(cx, &args.callee());
ReportUsageErrorASCII(cx, callee, "Too many arguments");
return false;
}
uint8_t zeal;
if (!ParseGCZealMode(cx, args, &zeal)) {
return false;
}
JS_UnsetGCZeal(cx, zeal);
JS_SetGCZeal(cx, (uint8_t)zeal, frequency);
args.rval().setUndefined();
return true;
}
@ -5713,14 +5680,9 @@ JS_FN_HELP("streamsAreEnabled", StreamsAreEnabled, 0, 0,
#ifdef JS_GC_ZEAL
JS_FN_HELP("gczeal", GCZeal, 2, 0,
"gczeal(mode, [frequency])",
"gczeal(level, [N])",
gc::ZealModeHelpText),
JS_FN_HELP("unsetgczeal", UnsetGCZeal, 2, 0,
"unsetgczeal(mode)",
" Turn off a single zeal mode set with gczeal() and don't finish any ongoing\n"
" collection that may be happening."),
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
"schedulegc([num | obj | string])",
" If num is given, schedule a GC after num allocations.\n"

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

@ -1149,41 +1149,6 @@ GCRuntime::setZeal(uint8_t zeal, uint32_t frequency)
nextScheduled = schedule ? frequency : 0;
}
void
GCRuntime::unsetZeal(uint8_t zeal)
{
MOZ_ASSERT(zeal <= unsigned(ZealMode::Limit));
ZealMode zealMode = ZealMode(zeal);
if (temporaryAbortIfWasmGc(rt->mainContextFromOwnThread())) {
return;
}
if (!hasZealMode(zealMode)) {
return;
}
if (verifyPreData) {
VerifyBarriers(rt, PreBarrierVerifier);
}
if (zealMode == ZealMode::GenerationalGC) {
evictNursery(JS::gcreason::DEBUG_GC);
nursery().leaveZealMode();
}
clearZealMode(zealMode);
if (zealModeBits == 0) {
if (isIncrementalGCInProgress()) {
finishGC(JS::gcreason::DEBUG_GC);
}
zealFrequency = 0;
nextScheduled = 0;
}
}
void
GCRuntime::setNextScheduled(uint32_t count)
{
@ -2651,10 +2616,10 @@ GCRuntime::sweepTypesAfterCompacting(Zone* zone)
AutoClearTypeInferenceStateOnOOM oom(zone);
for (auto script = zone->cellIter<JSScript>(); !script.done(); script.next()) {
AutoSweepTypeScript sweep(script, oom);
AutoSweepTypeScript sweep(script, &oom);
}
for (auto group = zone->cellIter<ObjectGroup>(); !group.done(); group.next()) {
AutoSweepObjectGroup sweep(group, oom);
AutoSweepObjectGroup sweep(group, &oom);
}
zone->types.endSweep(rt);
@ -6274,24 +6239,24 @@ SweepThing(Shape* shape)
}
static void
SweepThing(JSScript* script, AutoClearTypeInferenceStateOnOOM& oom)
SweepThing(JSScript* script, AutoClearTypeInferenceStateOnOOM* oom)
{
AutoSweepTypeScript sweep(script, oom);
}
static void
SweepThing(ObjectGroup* group, AutoClearTypeInferenceStateOnOOM& oom)
SweepThing(ObjectGroup* group, AutoClearTypeInferenceStateOnOOM* oom)
{
AutoSweepObjectGroup sweep(group, oom);
}
template <typename T, typename... Args>
static bool
SweepArenaList(Arena** arenasToSweep, SliceBudget& sliceBudget, Args&&... args)
SweepArenaList(Arena** arenasToSweep, SliceBudget& sliceBudget, Args... args)
{
while (Arena* arena = *arenasToSweep) {
for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) {
SweepThing(i.get<T>(), std::forward<Args>(args)...);
SweepThing(i.get<T>(), args...);
}
*arenasToSweep = (*arenasToSweep)->next;
@ -6323,11 +6288,11 @@ GCRuntime::sweepTypeInformation(FreeOp* fop, SliceBudget& budget, Zone* zone)
AutoClearTypeInferenceStateOnOOM oom(zone);
if (!SweepArenaList<JSScript>(&al.gcScriptArenasToUpdate.ref(), budget, oom)) {
if (!SweepArenaList<JSScript>(&al.gcScriptArenasToUpdate.ref(), budget, &oom)) {
return NotFinished;
}
if (!SweepArenaList<ObjectGroup>(&al.gcObjectGroupArenasToUpdate.ref(), budget, oom)) {
if (!SweepArenaList<ObjectGroup>(&al.gcObjectGroupArenasToUpdate.ref(), budget, &oom)) {
return NotFinished;
}
@ -8104,7 +8069,8 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
return;
}
stats().writeLogMessage("GC starting in state %s", StateName(incrementalState));
stats().writeLogMessage("GC starting in state %s",
StateName(incrementalState));
AutoTraceLog logGC(TraceLoggerForCurrentThread(), TraceLogger_GC);
AutoStopVerifyingBarriers av(rt, IsShutdownGC(reason));
@ -8161,7 +8127,7 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
MOZ_RELEASE_ASSERT(CheckGrayMarkingState(rt));
}
#endif
stats().writeLogMessage("GC ending in state %s", StateName(incrementalState));
stats().writeLogMessage("GC ending");
}
js::AutoEnqueuePendingParseTasksAfterGC::~AutoEnqueuePendingParseTasksAfterGC()

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

@ -299,7 +299,6 @@ class GCRuntime
}
void getZealBits(uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled);
void setZeal(uint8_t zeal, uint32_t frequency);
void unsetZeal(uint8_t zeal);
bool parseAndSetZeal(const char* str);
void setNextScheduled(uint32_t count);
void verifyPreBarriers();

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

@ -1,34 +0,0 @@
// |jit-test| --no-ion; --no-baseline
if (!("gcstate" in this))
quit();
gczeal(0);
// Create a bunch of ObjectGroups with TypeNewScript attached.
const count = 1000;
let c = [];
let a = [];
for (let i = 0; i < count; i++) {
c[i] = function() { this.a = 1; this.b = 0; this.c = 2; };
a[i] = new c[i];
}
// Start an incremental GC and run until we're about to sweep type information.
assertEq(gcstate(), "NotActive");
gczeal(20);
startgc(1);
// Run incremental slices with simulated OOM set up to provoke OOM when sweeping
// types.
assertEq(gcstate(), "Sweep");
gczeal(10);
unsetgczeal(20);
while (gcstate() == "Sweep") {
oomAfterAllocations(2);
gcslice(1);
resetOOMFailure();
}
// Ensure our type information stays alive.
let x = c.length + a.length;

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

@ -6411,12 +6411,6 @@ JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency)
cx->runtime()->gc.setZeal(zeal, frequency);
}
JS_PUBLIC_API(void)
JS_UnsetGCZeal(JSContext* cx, uint8_t zeal)
{
cx->runtime()->gc.unsetZeal(zeal);
}
JS_PUBLIC_API(void)
JS_ScheduleGC(JSContext* cx, uint32_t count)
{

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

@ -4383,9 +4383,6 @@ JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_
extern JS_PUBLIC_API(void)
JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency);
extern JS_PUBLIC_API(void)
JS_UnsetGCZeal(JSContext* cx, uint8_t zeal);
extern JS_PUBLIC_API(void)
JS_ScheduleGC(JSContext* cx, uint32_t count);
#endif

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

@ -1798,7 +1798,7 @@ class JSScript : public js::gc::TenuredCell
inline bool typesNeedsSweep() const;
void sweepTypes(const js::AutoSweepTypeScript& sweep,
js::AutoClearTypeInferenceStateOnOOM& oom);
js::AutoClearTypeInferenceStateOnOOM* oom);
inline js::GlobalObject& global() const;
js::GlobalObject& uninlinedGlobal() const;

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

@ -284,8 +284,7 @@ class ObjectGroup : public gc::TenuredCell
}
TypeNewScript* anyNewScript(const AutoSweepObjectGroup& sweep);
void detachNewScript(bool writeBarrier, ObjectGroup* replacement,
AutoClearTypeInferenceStateOnOOM& oom);
void detachNewScript(bool writeBarrier, ObjectGroup* replacement);
ObjectGroupFlags flagsDontCheckGeneration() const {
return flags_;
@ -470,7 +469,7 @@ class ObjectGroup : public gc::TenuredCell
void markStateChange(const AutoSweepObjectGroup& sweep, JSContext* cx);
void setFlags(const AutoSweepObjectGroup& sweep, JSContext* cx, ObjectGroupFlags flags);
void markUnknown(const AutoSweepObjectGroup& sweep, JSContext* cx);
void maybeClearNewScriptOnOOM(AutoClearTypeInferenceStateOnOOM& oom);
void maybeClearNewScriptOnOOM();
void clearNewScript(JSContext* cx, ObjectGroup* replacement = nullptr);
void print(const AutoSweepObjectGroup& sweep);
@ -479,7 +478,7 @@ class ObjectGroup : public gc::TenuredCell
void traceChildren(JSTracer* trc);
inline bool needsSweep();
void sweep(const AutoSweepObjectGroup& sweep, AutoClearTypeInferenceStateOnOOM& oom);
void sweep(const AutoSweepObjectGroup& sweep, AutoClearTypeInferenceStateOnOOM* oom);
private:
uint32_t generation() {

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

@ -446,6 +446,9 @@ struct AutoEnterAnalysis
// Prevent GC activity in the middle of analysis.
gc::AutoSuppressGC suppressGC;
// Allow clearing inference info on OOM during incremental sweeping.
mozilla::Maybe<AutoClearTypeInferenceStateOnOOM> oom;
// Pending recompilations to perform before execution of JIT code can resume.
RecompileInfoVector pendingRecompiles;
@ -1438,21 +1441,9 @@ ObjectGroup::getProperty(const AutoSweepObjectGroup& sweep, unsigned i)
return result;
}
inline
AutoSweepObjectGroup::AutoSweepObjectGroup(ObjectGroup* group)
#ifdef DEBUG
: group_(group)
#endif
{
if (group->needsSweep()) {
AutoClearTypeInferenceStateOnOOM oom(group->zone());
group->sweep(*this, oom);
}
}
inline
AutoSweepObjectGroup::AutoSweepObjectGroup(ObjectGroup* group,
AutoClearTypeInferenceStateOnOOM& oom)
AutoClearTypeInferenceStateOnOOM* oom)
#ifdef DEBUG
: group_(group)
#endif
@ -1472,19 +1463,8 @@ AutoSweepObjectGroup::~AutoSweepObjectGroup()
#endif
inline
AutoSweepTypeScript::AutoSweepTypeScript(JSScript* script)
#ifdef DEBUG
: script_(script)
#endif
{
if (script->typesNeedsSweep()) {
AutoClearTypeInferenceStateOnOOM oom(script->zone());
script->sweepTypes(*this, oom);
}
}
inline
AutoSweepTypeScript::AutoSweepTypeScript(JSScript* script, AutoClearTypeInferenceStateOnOOM& oom)
AutoSweepTypeScript::AutoSweepTypeScript(JSScript* script,
AutoClearTypeInferenceStateOnOOM* oom)
#ifdef DEBUG
: script_(script)
#endif

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

@ -3302,14 +3302,13 @@ ObjectGroup::anyNewScript(const AutoSweepObjectGroup& sweep)
}
void
ObjectGroup::detachNewScript(bool writeBarrier, ObjectGroup* replacement,
AutoClearTypeInferenceStateOnOOM& oom)
ObjectGroup::detachNewScript(bool writeBarrier, ObjectGroup* replacement)
{
// Clear the TypeNewScript from this ObjectGroup and, if it has been
// analyzed, remove it from the newObjectGroups table so that it will not be
// produced by calling 'new' on the associated function anymore.
// The TypeNewScript is not actually destroyed.
AutoSweepObjectGroup sweep(this, oom);
AutoSweepObjectGroup sweep(this);
TypeNewScript* newScript = anyNewScript(sweep);
MOZ_ASSERT(newScript);
@ -3321,7 +3320,7 @@ ObjectGroup::detachNewScript(bool writeBarrier, ObjectGroup* replacement,
}
JSObject* associated = MaybeForwarded(newScript->function());
if (replacement) {
AutoSweepObjectGroup sweepReplacement(replacement, oom);
AutoSweepObjectGroup sweepReplacement(replacement);
MOZ_ASSERT(replacement->newScript(sweepReplacement)->function() == newScript->function());
objectGroups.replaceDefaultNewGroup(nullptr, proto, associated, replacement);
} else {
@ -3339,7 +3338,7 @@ ObjectGroup::detachNewScript(bool writeBarrier, ObjectGroup* replacement,
}
void
ObjectGroup::maybeClearNewScriptOnOOM(AutoClearTypeInferenceStateOnOOM& oom)
ObjectGroup::maybeClearNewScriptOnOOM()
{
MOZ_ASSERT(zone()->isGCSweepingOrCompacting());
@ -3347,7 +3346,7 @@ ObjectGroup::maybeClearNewScriptOnOOM(AutoClearTypeInferenceStateOnOOM& oom)
return;
}
AutoSweepObjectGroup sweep(this, oom);
AutoSweepObjectGroup sweep(this);
TypeNewScript* newScript = anyNewScript(sweep);
if (!newScript) {
return;
@ -3356,7 +3355,7 @@ ObjectGroup::maybeClearNewScriptOnOOM(AutoClearTypeInferenceStateOnOOM& oom)
addFlags(sweep, OBJECT_FLAG_NEW_SCRIPT_CLEARED);
// This method is called during GC sweeping, so don't trigger pre barriers.
detachNewScript(/* writeBarrier = */ false, nullptr, oom);
detachNewScript(/* writeBarrier = */ false, nullptr);
js_delete(newScript);
}
@ -3364,8 +3363,7 @@ ObjectGroup::maybeClearNewScriptOnOOM(AutoClearTypeInferenceStateOnOOM& oom)
void
ObjectGroup::clearNewScript(JSContext* cx, ObjectGroup* replacement /* = nullptr*/)
{
AutoClearTypeInferenceStateOnOOM oom(zone());
AutoSweepObjectGroup sweep(this, oom);
AutoSweepObjectGroup sweep(this);
TypeNewScript* newScript = anyNewScript(sweep);
if (!newScript) {
return;
@ -3382,7 +3380,7 @@ ObjectGroup::clearNewScript(JSContext* cx, ObjectGroup* replacement /* = nullptr
newScript->function()->setNewScriptCleared();
}
detachNewScript(/* writeBarrier = */ true, replacement, oom);
detachNewScript(/* writeBarrier = */ true, replacement);
if (!cx->helperThread()) {
bool found = newScript->rollbackPartiallyInitializedObjects(cx, this);
@ -4746,6 +4744,23 @@ ObjectGroup::clearProperties(const AutoSweepObjectGroup& sweep)
propertySet = nullptr;
}
static void
EnsureHasAutoClearTypeInferenceStateOnOOM(AutoClearTypeInferenceStateOnOOM*& oom, Zone* zone,
Maybe<AutoClearTypeInferenceStateOnOOM>& fallback)
{
if (!oom) {
if (AutoEnterAnalysis* analysis = zone->types.activeAnalysis) {
if (analysis->oom.isNothing()) {
analysis->oom.emplace(zone);
}
oom = analysis->oom.ptr();
} else {
fallback.emplace(zone);
oom = &fallback.ref();
}
}
}
/*
* Before sweeping the arenas themselves, scan all groups in a compartment to
* fixup weak references: property type sets referencing dead JS and type
@ -4754,13 +4769,16 @@ ObjectGroup::clearProperties(const AutoSweepObjectGroup& sweep)
* objects are accessed before their contents have been swept.
*/
void
ObjectGroup::sweep(const AutoSweepObjectGroup& sweep, AutoClearTypeInferenceStateOnOOM& oom)
ObjectGroup::sweep(const AutoSweepObjectGroup& sweep, AutoClearTypeInferenceStateOnOOM* oom)
{
MOZ_ASSERT(generation() != zoneFromAnyThread()->types.generation);
setGeneration(zone()->types.generation);
AssertGCStateForSweep(zone());
Maybe<AutoClearTypeInferenceStateOnOOM> fallbackOOM;
EnsureHasAutoClearTypeInferenceStateOnOOM(oom, zone(), fallbackOOM);
AutoTouchingGrayThings tgt;
if (auto* layout = maybeUnboxedLayout(sweep)) {
@ -4835,12 +4853,12 @@ ObjectGroup::sweep(const AutoSweepObjectGroup& sweep, AutoClearTypeInferenceStat
(typeLifoAlloc, propertySet, propertyCount, newProp->id);
if (pentry) {
*pentry = newProp;
newProp->types.sweep(sweep, zone(), oom);
newProp->types.sweep(sweep, zone(), *oom);
continue;
}
}
oom.setOOM();
oom->setOOM();
addFlags(sweep, OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES);
clearProperties(sweep);
return;
@ -4863,9 +4881,9 @@ ObjectGroup::sweep(const AutoSweepObjectGroup& sweep, AutoClearTypeInferenceStat
JS_POISON(prop, JS_SWEPT_TI_PATTERN, sizeof(Property), MemCheckKind::MakeUndefined);
if (newProp) {
propertySet = (Property**) newProp;
newProp->types.sweep(sweep, zone(), oom);
newProp->types.sweep(sweep, zone(), *oom);
} else {
oom.setOOM();
oom->setOOM();
addFlags(sweep, OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES);
clearProperties(sweep);
return;
@ -4877,13 +4895,16 @@ ObjectGroup::sweep(const AutoSweepObjectGroup& sweep, AutoClearTypeInferenceStat
}
/* static */ void
JSScript::sweepTypes(const js::AutoSweepTypeScript& sweep, AutoClearTypeInferenceStateOnOOM& oom)
JSScript::sweepTypes(const js::AutoSweepTypeScript& sweep, AutoClearTypeInferenceStateOnOOM* oom)
{
MOZ_ASSERT(typesGeneration() != zone()->types.generation);
setTypesGeneration(zone()->types.generation);
AssertGCStateForSweep(zone());
Maybe<AutoClearTypeInferenceStateOnOOM> fallbackOOM;
EnsureHasAutoClearTypeInferenceStateOnOOM(oom, zone(), fallbackOOM);
TypeZone& types = zone()->types;
// Sweep the inlinedCompilations Vector.
@ -4923,10 +4944,10 @@ JSScript::sweepTypes(const js::AutoSweepTypeScript& sweep, AutoClearTypeInferenc
// Remove constraints and references to dead objects from stack type sets.
for (unsigned i = 0; i < num; i++) {
typeArray[i].sweep(sweep, zone(), oom);
typeArray[i].sweep(sweep, zone(), *oom);
}
if (oom.hadOOM()) {
if (oom->hadOOM()) {
// It's possible we OOM'd while copying freeze constraints, so they
// need to be regenerated.
bitFields_.hasFreezeConstraints_ = false;
@ -5014,12 +5035,12 @@ TypeZone::endSweep(JSRuntime* rt)
}
void
TypeZone::clearAllNewScriptsOnOOM(AutoClearTypeInferenceStateOnOOM& oom)
TypeZone::clearAllNewScriptsOnOOM()
{
for (auto iter = zone()->cellIter<ObjectGroup>(); !iter.done(); iter.next()) {
ObjectGroup* group = iter;
if (!IsAboutToBeFinalizedUnbarriered(&group)) {
group->maybeClearNewScriptOnOOM(oom);
group->maybeClearNewScriptOnOOM();
}
}
}
@ -5034,15 +5055,15 @@ AutoClearTypeInferenceStateOnOOM::AutoClearTypeInferenceStateOnOOM(Zone* zone)
AutoClearTypeInferenceStateOnOOM::~AutoClearTypeInferenceStateOnOOM()
{
zone->types.setSweepingTypes(false);
if (oom) {
JSRuntime* rt = zone->runtimeFromMainThread();
js::CancelOffThreadIonCompile(rt);
zone->setPreservingCode(false);
zone->discardJitCode(rt->defaultFreeOp(), /* discardBaselineCode = */ false);
zone->types.clearAllNewScriptsOnOOM(*this);
zone->types.clearAllNewScriptsOnOOM();
}
zone->types.setSweepingTypes(false);
}
#ifdef DEBUG

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

@ -84,8 +84,8 @@ class MOZ_RAII AutoSweepObjectGroup : public AutoSweepBase
#endif
public:
inline explicit AutoSweepObjectGroup(ObjectGroup* group);
inline AutoSweepObjectGroup(ObjectGroup* group, AutoClearTypeInferenceStateOnOOM& oom);
inline explicit AutoSweepObjectGroup(ObjectGroup* group,
AutoClearTypeInferenceStateOnOOM* oom = nullptr);
#ifdef DEBUG
inline ~AutoSweepObjectGroup();
@ -104,8 +104,8 @@ class MOZ_RAII AutoSweepTypeScript : public AutoSweepBase
#endif
public:
inline explicit AutoSweepTypeScript(JSScript* script);
inline AutoSweepTypeScript(JSScript* script, AutoClearTypeInferenceStateOnOOM& oom);
inline explicit AutoSweepTypeScript(JSScript* script,
AutoClearTypeInferenceStateOnOOM* oom = nullptr);
#ifdef DEBUG
inline ~AutoSweepTypeScript();
@ -414,7 +414,7 @@ class TypeZone
void beginSweep(bool releaseTypes);
void endSweep(JSRuntime* rt);
void clearAllNewScriptsOnOOM(AutoClearTypeInferenceStateOnOOM& oom);
void clearAllNewScriptsOnOOM();
/* Mark a script as needing recompilation once inference has finished. */
void addPendingRecompile(JSContext* cx, const RecompileInfo& info);