Bug 723350 - Improve last-ditch GC trigger. r=billm

This commit is contained in:
Till Schneidereit 2012-05-08 18:49:13 -04:00
parent 6fe7f5539e
commit 7a2a29c947
6 changed files with 17 additions and 51 deletions

View File

@ -757,7 +757,6 @@ JSRuntime::JSRuntime()
gcCallback(NULL),
gcSliceCallback(NULL),
gcFinalizeCallback(NULL),
gcMallocBytes(0),
gcBlackRootsTraceOp(NULL),
gcBlackRootsData(NULL),
gcGrayRootsTraceOp(NULL),

View File

@ -1102,22 +1102,10 @@ JSContext::runningWithTrustedPrincipals() const
void
JSRuntime::updateMallocCounter(JSContext *cx, size_t nbytes)
{
/* We tolerate any thread races when updating gcMallocBytes. */
ptrdiff_t oldCount = gcMallocBytes;
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
gcMallocBytes = newCount;
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
onTooMuchMalloc();
else if (cx && cx->compartment)
if (cx && cx->compartment)
cx->compartment->updateMallocCounter(nbytes);
}
JS_FRIEND_API(void)
JSRuntime::onTooMuchMalloc()
{
TriggerGC(this, gcreason::TOO_MUCH_MALLOC);
}
JS_FRIEND_API(void *)
JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
{

View File

@ -644,13 +644,6 @@ struct JSRuntime : js::RuntimeFriendFields
js::GCSliceCallback gcSliceCallback;
JSFinalizeCallback gcFinalizeCallback;
private:
/*
* Malloc counter to measure memory pressure for GC scheduling. It runs
* from gcMaxMallocBytes down to zero.
*/
volatile ptrdiff_t gcMallocBytes;
public:
/*
* The trace operations to trace embedding-specific GC roots. One is for
@ -855,17 +848,8 @@ struct JSRuntime : js::RuntimeFriendFields
JS_DECLARE_NEW_METHODS(malloc_, JS_ALWAYS_INLINE)
JS_DECLARE_DELETE_METHODS(free_, JS_ALWAYS_INLINE)
bool isGCMallocLimitReached() const { return gcMallocBytes <= 0; }
void resetGCMallocBytes() { gcMallocBytes = ptrdiff_t(gcMaxMallocBytes); }
void setGCMaxMallocBytes(size_t value) {
/*
* For compatibility treat any value that exceeds PTRDIFF_T_MAX to
* mean that value.
*/
gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
resetGCMallocBytes();
gcMaxMallocBytes = value;
}
/*
@ -877,12 +861,6 @@ struct JSRuntime : js::RuntimeFriendFields
* the caller must ensure that no deadlock possible during OOM reporting.
*/
void updateMallocCounter(JSContext *cx, size_t nbytes);
/*
* The function must be called outside the GC lock.
*/
JS_FRIEND_API(void) onTooMuchMalloc();
/*
* This should be called after system malloc/realloc returns NULL to try
* to recove some memory or to report an error. Failures in malloc and

View File

@ -535,17 +535,13 @@ JSCompartment::purge()
void
JSCompartment::resetGCMallocBytes()
{
gcMallocBytes = ptrdiff_t(gcMaxMallocBytes);
gcMallocBytes = gcMaxMallocBytes;
}
void
JSCompartment::setGCMaxMallocBytes(size_t value)
{
/*
* For compatibility treat any value that exceeds PTRDIFF_T_MAX to
* mean that value.
*/
gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
gcMaxMallocBytes = value;
resetGCMallocBytes();
}

View File

@ -178,7 +178,6 @@ struct JSCompartment
size_t gcBytes;
size_t gcTriggerBytes;
size_t gcMaxMallocBytes;
bool hold;
bool isSystemCompartment;
@ -245,7 +244,8 @@ struct JSCompartment
* gcMaxMallocBytes down to zero. This counter should be used only when it's
* not possible to know the size of a free.
*/
ptrdiff_t gcMallocBytes;
size_t gcMallocBytes;
size_t gcMaxMallocBytes;
enum { DebugFromC = 1, DebugFromJS = 2 };
@ -281,13 +281,19 @@ struct JSCompartment
void resetGCMallocBytes();
void setGCMaxMallocBytes(size_t value);
void updateMallocCounter(size_t nbytes) {
ptrdiff_t oldCount = gcMallocBytes;
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
size_t oldCount = gcMallocBytes;
size_t newCount = oldCount - nbytes;
gcMallocBytes = newCount;
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
// gcMallocBytes will wrap around and be bigger than gcMaxAllocBytes if a signed value
// would be < 0
if (JS_UNLIKELY(oldCount <= gcMaxMallocBytes && newCount > gcMaxMallocBytes))
onTooMuchMalloc();
}
bool isTooMuchMalloc() const {
return gcMallocBytes > gcMaxMallocBytes;
}
void onTooMuchMalloc();
void mallocInCompartment(size_t nbytes) {

View File

@ -1666,7 +1666,8 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
JSRuntime *rt = comp->rt;
JS_ASSERT(!rt->gcRunning);
bool runGC = rt->gcIncrementalState != NO_INCREMENTAL && comp->gcBytes > comp->gcTriggerBytes;
bool runGC = rt->gcIncrementalState != NO_INCREMENTAL &&
(comp->gcBytes > comp->gcTriggerBytes || comp->isTooMuchMalloc());
for (;;) {
if (JS_UNLIKELY(runGC)) {
PrepareCompartmentForGC(comp);
@ -3308,8 +3309,6 @@ AutoGCSession::AutoGCSession(JSRuntime *rt)
runtime->gcNumber++;
runtime->resetGCMallocBytes();
/* Clear gcMallocBytes for all compartments */
for (CompartmentsIter c(runtime); !c.done(); c.next())
c->resetGCMallocBytes();