Back out bug 1308039 - GC interrupt callbacks (a=backout)

This reverts commit 1fc1a2e080a1d9012f0ad651243766540daf139f.

MozReview-Commit-ID: BvHIIj1t3M8
This commit is contained in:
Bill McCloskey 2017-01-06 11:55:10 -08:00
Родитель 2f7dff12ca
Коммит fbf4345dc9
5 изменённых файлов: 13 добавлений и 139 удалений

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

@ -721,18 +721,6 @@ PokeGC(JSContext* cx);
extern JS_FRIEND_API(void)
NotifyDidPaint(JSContext* cx);
// GC Interrupt callbacks are run during GC. You should not run JS code or use
// the JS engine at all while the callback is running. Otherwise they resemble
// normal JS interrupt callbacks.
typedef bool
(* GCInterruptCallback)(JSContext* cx);
extern JS_FRIEND_API(bool)
AddGCInterruptCallback(JSContext* cx, GCInterruptCallback callback);
extern JS_FRIEND_API(void)
RequestGCInterruptCallback(JSContext* cx);
} /* namespace JS */
#endif /* js_GCAPI_h */

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

@ -7,8 +7,6 @@
#ifndef js_SliceBudget_h
#define js_SliceBudget_h
#include "mozilla/Atomics.h"
#include <stdint.h>
namespace js {
@ -38,7 +36,7 @@ class JS_PUBLIC_API(SliceBudget)
static const int64_t unlimitedDeadline = INT64_MAX;
static const intptr_t unlimitedStartCounter = INTPTR_MAX;
bool checkOverBudget(JSContext* maybeCx);
bool checkOverBudget();
SliceBudget();
@ -50,7 +48,7 @@ class JS_PUBLIC_API(SliceBudget)
WorkBudget workBudget;
int64_t deadline; /* in microseconds */
mozilla::Atomic<intptr_t, mozilla::Relaxed> counter;
intptr_t counter;
static const intptr_t CounterReset = 1000;
@ -66,44 +64,19 @@ class JS_PUBLIC_API(SliceBudget)
/* Instantiate as SliceBudget(WorkBudget(n)). */
explicit SliceBudget(WorkBudget work);
// Need an explicit copy constructor because Atomic fails to provide one.
SliceBudget(const SliceBudget& other)
: timeBudget(other.timeBudget),
workBudget(other.workBudget),
deadline(other.deadline),
counter(other.counter)
{}
// Need an explicit operator= because Atomic fails to provide one.
SliceBudget& operator=(const SliceBudget& other) {
timeBudget = other.timeBudget;
workBudget = other.workBudget;
deadline = other.deadline;
counter = intptr_t(other.counter);
return *this;
}
void makeUnlimited() {
deadline = unlimitedDeadline;
counter = unlimitedStartCounter;
}
// Request that checkOverBudget be called the next time isOverBudget is
// called.
void requestFullCheck() {
counter = 0;
}
void step(intptr_t amt = 1) {
counter -= amt;
}
// Only need to pass maybeCx if the GC interrupt callback should be checked
// (and possibly invoked).
bool isOverBudget(JSContext* maybeCx = nullptr) {
bool isOverBudget() {
if (counter > 0)
return false;
return checkOverBudget(maybeCx);
return checkOverBudget();
}
bool isWorkBudget() const { return deadline == 0; }

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

@ -24,7 +24,6 @@ namespace js {
class AutoLockGC;
class AutoLockHelperThreadState;
class SliceBudget;
class VerifyPreTracer;
namespace gc {
@ -858,19 +857,6 @@ class GCRuntime
bool isVerifyPreBarriersEnabled() const { return false; }
#endif
// GC interrupt callbacks.
bool addInterruptCallback(JS::GCInterruptCallback callback);
void requestInterruptCallback();
bool checkInterruptCallback(JSContext* cx) {
if (interruptCallbackRequested) {
invokeInterruptCallback(cx);
return true;
}
return false;
}
void invokeInterruptCallback(JSContext* cx);
// Free certain LifoAlloc blocks when it is safe to do so.
void freeUnusedLifoBlocksAfterSweeping(LifoAlloc* lifo);
void freeAllLifoBlocksAfterSweeping(LifoAlloc* lifo);
@ -1086,13 +1072,6 @@ class GCRuntime
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> numArenasFreeCommitted;
VerifyPreTracer* verifyPreData;
// GC interrupt callbacks.
using GCInterruptCallbackVector = js::Vector<JS::GCInterruptCallback, 2, js::SystemAllocPolicy>;
GCInterruptCallbackVector interruptCallbacks;
mozilla::Atomic<bool, mozilla::Relaxed> interruptCallbackRequested;
SliceBudget* currentBudget;
private:
bool chunkAllocationSinceLastGC;
int64_t lastGCTime;

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

@ -1559,15 +1559,13 @@ GCMarker::drainMarkStack(SliceBudget& budget)
auto acc = mozilla::MakeScopeExit([&] {strictCompartmentChecking = false;});
#endif
JSContext* cx = runtime()->contextFromMainThread();
if (budget.isOverBudget(cx))
if (budget.isOverBudget())
return false;
for (;;) {
while (!stack.isEmpty()) {
processMarkStackTop(budget);
if (budget.isOverBudget(cx)) {
if (budget.isOverBudget()) {
saveValueRanges();
return false;
}
@ -1642,8 +1640,6 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
uintptr_t tag = addr & StackTagMask;
addr &= ~StackTagMask;
JSContext* cx = runtime()->contextFromMainThread();
// Dispatch
switch (tag) {
case ValueArrayTag: {
@ -1697,7 +1693,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
MOZ_ASSERT(vp <= end);
while (vp != end) {
budget.step();
if (budget.isOverBudget(cx)) {
if (budget.isOverBudget()) {
pushValueArray(obj, vp, end);
return;
}
@ -1727,7 +1723,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
AssertZoneIsMarking(obj);
budget.step();
if (budget.isOverBudget(cx)) {
if (budget.isOverBudget()) {
repush(obj);
return;
}
@ -2175,7 +2171,7 @@ GCMarker::markDelayedChildren(SliceBudget& budget)
markDelayedChildren(arena);
budget.step(150);
if (budget.isOverBudget(runtime()->contextFromMainThread()))
if (budget.isOverBudget())
return false;
} while (unmarkedArenaStackTop);
MOZ_ASSERT(!markLaterArenas);

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

@ -511,8 +511,6 @@ FinalizeTypedArenas(FreeOp* fop,
size_t thingSize = Arena::thingSize(thingKind);
size_t thingsPerArena = Arena::thingsPerArena(thingKind);
JSContext* cx = fop->onMainThread() ? fop->runtime()->contextFromMainThread() : nullptr;
while (Arena* arena = *src) {
*src = arena->next;
size_t nmarked = arena->finalize<T>(fop, thingKind, thingSize);
@ -526,7 +524,7 @@ FinalizeTypedArenas(FreeOp* fop,
fop->runtime()->gc.releaseArena(arena, maybeLock.ref());
budget.step(thingsPerArena);
if (budget.isOverBudget(cx))
if (budget.isOverBudget())
return false;
}
@ -815,8 +813,6 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
nextCellUniqueId_(LargestTaggedNullCellPointer + 1), // Ensure disjoint from null tagged pointers.
numArenasFreeCommitted(0),
verifyPreData(nullptr),
interruptCallbackRequested(false),
currentBudget(nullptr),
chunkAllocationSinceLastGC(false),
lastGCTime(PRMJ_Now()),
mode(JSGC_MODE_INCREMENTAL),
@ -2911,11 +2907,8 @@ SliceBudget::describe(char* buffer, size_t maxlen) const
}
bool
SliceBudget::checkOverBudget(JSContext* cx)
SliceBudget::checkOverBudget()
{
if (cx)
cx->gc.checkInterruptCallback(cx);
bool over = PRMJ_Now() >= deadline;
if (!over)
counter = CounterReset;
@ -5509,7 +5502,7 @@ GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget,
updatePointersToRelocatedCells(zone, lock);
zone->setGCState(Zone::Finished);
zonesToMaybeCompact.removeFront();
if (sliceBudget.isOverBudget(rt->contextFromMainThread()))
if (sliceBudget.isOverBudget())
break;
}
@ -5891,7 +5884,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
* now exhasted.
*/
beginSweepPhase(destroyingRuntime, lock);
if (budget.isOverBudget(rt->contextFromMainThread()))
if (budget.isOverBudget())
break;
/*
@ -6316,16 +6309,6 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
if (!checkIfGCAllowedInCurrentState(reason))
return;
interruptCallbackRequested = false;
{
AutoLockGC lock(rt);
currentBudget = &budget;
}
auto guard = mozilla::MakeScopeExit([&] {
AutoLockGC lock(rt);
currentBudget = nullptr;
});
AutoTraceLog logGC(TraceLoggerForMainThread(rt), TraceLogger_GC);
AutoStopVerifyingBarriers av(rt, IsShutdownGC(reason));
AutoEnqueuePendingParseTasksAfterGC aept(*this);
@ -7692,48 +7675,3 @@ js::gc::Cell::dump() const
dump(stderr);
}
#endif
bool
JS::AddGCInterruptCallback(JSContext* cx, GCInterruptCallback callback)
{
return cx->runtime()->gc.addInterruptCallback(callback);
}
void
JS::RequestGCInterruptCallback(JSContext* cx)
{
cx->runtime()->gc.requestInterruptCallback();
}
bool
GCRuntime::addInterruptCallback(JS::GCInterruptCallback callback)
{
return interruptCallbacks.append(callback);
}
void
GCRuntime::requestInterruptCallback()
{
AutoLockGC lock(rt);
if (currentBudget) {
interruptCallbackRequested = true;
currentBudget->requestFullCheck();
}
}
void
GCRuntime::invokeInterruptCallback(JSContext* cx)
{
interruptCallbackRequested = false;
stats.suspendPhases();
JS::AutoAssertNoGC nogc(cx);
JS::AutoAssertOnBarrier nobarrier(cx);
JS::AutoSuppressGCAnalysis suppress(cx);
for (JS::GCInterruptCallback callback : interruptCallbacks) {
(*callback)(cx);
}
stats.resumePhases();
}