mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 926678 - Ensure GC gets triggered when gcMallocBytes drops below zero r=billm
This commit is contained in:
parent
3203317e2b
commit
8afde533eb
@ -127,7 +127,14 @@ Zone::setGCMaxMallocBytes(size_t value)
|
|||||||
void
|
void
|
||||||
Zone::onTooMuchMalloc()
|
Zone::onTooMuchMalloc()
|
||||||
{
|
{
|
||||||
TriggerZoneGC(this, gcreason::TOO_MUCH_MALLOC);
|
if (TriggerZoneGC(this, gcreason::TOO_MUCH_MALLOC)) {
|
||||||
|
/*
|
||||||
|
* Set gcMallocBytes to stop updateMallocCounter() calling this method
|
||||||
|
* again before the counter is reset by GC.
|
||||||
|
*/
|
||||||
|
gcMallocBytes = PTRDIFF_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -272,10 +272,8 @@ struct Zone : public JS::shadow::Zone,
|
|||||||
* Note: this code may be run from worker threads. We
|
* Note: this code may be run from worker threads. We
|
||||||
* tolerate any thread races when updating gcMallocBytes.
|
* tolerate any thread races when updating gcMallocBytes.
|
||||||
*/
|
*/
|
||||||
ptrdiff_t oldCount = gcMallocBytes;
|
gcMallocBytes -= ptrdiff_t(nbytes);
|
||||||
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
|
if (JS_UNLIKELY(isTooMuchMalloc()))
|
||||||
gcMallocBytes = newCount;
|
|
||||||
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
|
|
||||||
onTooMuchMalloc();
|
onTooMuchMalloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1930,29 +1930,31 @@ TriggerOperationCallback(JSRuntime *rt, JS::gcreason::Reason reason)
|
|||||||
rt->triggerOperationCallback(JSRuntime::TriggerCallbackMainThread);
|
rt->triggerOperationCallback(JSRuntime::TriggerCallbackMainThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
js::TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason)
|
js::TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason)
|
||||||
{
|
{
|
||||||
/* Wait till end of parallel section to trigger GC. */
|
/* Wait till end of parallel section to trigger GC. */
|
||||||
if (InParallelSection()) {
|
if (InParallelSection()) {
|
||||||
ForkJoinSlice::Current()->requestGC(reason);
|
ForkJoinSlice::Current()->requestGC(reason);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't trigger GCs when allocating under the operation callback lock. */
|
/* Don't trigger GCs when allocating under the operation callback lock. */
|
||||||
if (rt->currentThreadOwnsOperationCallbackLock())
|
if (rt->currentThreadOwnsOperationCallbackLock())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||||
|
|
||||||
if (rt->isHeapBusy())
|
/* GC is already running. */
|
||||||
return;
|
if (rt->isHeapCollecting())
|
||||||
|
return true;
|
||||||
|
|
||||||
JS::PrepareForFullGC(rt);
|
JS::PrepareForFullGC(rt);
|
||||||
TriggerOperationCallback(rt, reason);
|
TriggerOperationCallback(rt, reason);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
js::TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason)
|
js::TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1961,35 +1963,37 @@ js::TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason)
|
|||||||
*/
|
*/
|
||||||
if (InParallelSection()) {
|
if (InParallelSection()) {
|
||||||
ForkJoinSlice::Current()->requestZoneGC(zone, reason);
|
ForkJoinSlice::Current()->requestZoneGC(zone, reason);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zones in use by a thread with an exclusive context can't be collected. */
|
/* Zones in use by a thread with an exclusive context can't be collected. */
|
||||||
if (zone->usedByExclusiveThread)
|
if (zone->usedByExclusiveThread)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
JSRuntime *rt = zone->runtimeFromMainThread();
|
JSRuntime *rt = zone->runtimeFromMainThread();
|
||||||
|
|
||||||
/* Don't trigger GCs when allocating under the operation callback lock. */
|
/* Don't trigger GCs when allocating under the operation callback lock. */
|
||||||
if (rt->currentThreadOwnsOperationCallbackLock())
|
if (rt->currentThreadOwnsOperationCallbackLock())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (rt->isHeapBusy())
|
/* GC is already running. */
|
||||||
return;
|
if (rt->isHeapCollecting())
|
||||||
|
return true;
|
||||||
|
|
||||||
if (rt->gcZeal() == ZealAllocValue) {
|
if (rt->gcZeal() == ZealAllocValue) {
|
||||||
TriggerGC(rt, reason);
|
TriggerGC(rt, reason);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rt->isAtomsZone(zone)) {
|
if (rt->isAtomsZone(zone)) {
|
||||||
/* We can't do a zone GC of the atoms compartment. */
|
/* We can't do a zone GC of the atoms compartment. */
|
||||||
TriggerGC(rt, reason);
|
TriggerGC(rt, reason);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrepareZoneForGC(zone);
|
PrepareZoneForGC(zone);
|
||||||
TriggerOperationCallback(rt, reason);
|
TriggerOperationCallback(rt, reason);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -687,11 +687,11 @@ extern void
|
|||||||
TraceRuntime(JSTracer *trc);
|
TraceRuntime(JSTracer *trc);
|
||||||
|
|
||||||
/* Must be called with GC lock taken. */
|
/* Must be called with GC lock taken. */
|
||||||
extern void
|
extern bool
|
||||||
TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason);
|
TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason);
|
||||||
|
|
||||||
/* Must be called with GC lock taken. */
|
/* Must be called with GC lock taken. */
|
||||||
extern void
|
extern bool
|
||||||
TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason);
|
TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
|
@ -724,10 +724,8 @@ void
|
|||||||
JSRuntime::updateMallocCounter(JS::Zone *zone, size_t nbytes)
|
JSRuntime::updateMallocCounter(JS::Zone *zone, size_t nbytes)
|
||||||
{
|
{
|
||||||
/* We tolerate any thread races when updating gcMallocBytes. */
|
/* We tolerate any thread races when updating gcMallocBytes. */
|
||||||
ptrdiff_t oldCount = gcMallocBytes;
|
gcMallocBytes -= ptrdiff_t(nbytes);
|
||||||
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
|
if (JS_UNLIKELY(gcMallocBytes <= 0))
|
||||||
gcMallocBytes = newCount;
|
|
||||||
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
|
|
||||||
onTooMuchMalloc();
|
onTooMuchMalloc();
|
||||||
else if (zone)
|
else if (zone)
|
||||||
zone->updateMallocCounter(nbytes);
|
zone->updateMallocCounter(nbytes);
|
||||||
@ -736,8 +734,16 @@ JSRuntime::updateMallocCounter(JS::Zone *zone, size_t nbytes)
|
|||||||
JS_FRIEND_API(void)
|
JS_FRIEND_API(void)
|
||||||
JSRuntime::onTooMuchMalloc()
|
JSRuntime::onTooMuchMalloc()
|
||||||
{
|
{
|
||||||
if (CurrentThreadCanAccessRuntime(this))
|
if (!CurrentThreadCanAccessRuntime(this))
|
||||||
TriggerGC(this, JS::gcreason::TOO_MUCH_MALLOC);
|
return;
|
||||||
|
|
||||||
|
if (TriggerGC(this, JS::gcreason::TOO_MUCH_MALLOC)) {
|
||||||
|
/*
|
||||||
|
* Set gcMallocBytes to stop updateMallocCounter() calling this method
|
||||||
|
* again before the counter is reset by GC.
|
||||||
|
*/
|
||||||
|
gcMallocBytes = PTRDIFF_MAX;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(void *)
|
JS_FRIEND_API(void *)
|
||||||
|
Loading…
Reference in New Issue
Block a user