From ad8510d648d74f1c0c3930d9e8e6660246596093 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Fri, 27 Mar 2015 10:20:53 +0000 Subject: [PATCH] Bug 1146696 - Don't assume there are no arenas available after last ditch GC r=terrence --- js/src/gc/Allocator.cpp | 14 +++++++++----- js/src/gc/GCRuntime.h | 6 ++++-- js/src/jit-test/tests/gc/bug-1146696.js | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 js/src/jit-test/tests/gc/bug-1146696.js diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp index 46746e18a926..27597bb50934 100644 --- a/js/src/gc/Allocator.cpp +++ b/js/src/gc/Allocator.cpp @@ -232,7 +232,7 @@ GCRuntime::tryNewTenuredThing(ExclusiveContext *cx, AllocKind kind, size_t thing { T *t = reinterpret_cast(cx->arenas()->allocateFromFreeList(kind, thingSize)); if (!t) - t = reinterpret_cast(refillFreeListFromAnyThread(cx, kind)); + t = reinterpret_cast(refillFreeListFromAnyThread(cx, kind, thingSize)); checkIncrementalZoneState(cx, t); TraceTenuredAlloc(t, kind); @@ -241,19 +241,19 @@ GCRuntime::tryNewTenuredThing(ExclusiveContext *cx, AllocKind kind, size_t thing template /* static */ void * -GCRuntime::refillFreeListFromAnyThread(ExclusiveContext *cx, AllocKind thingKind) +GCRuntime::refillFreeListFromAnyThread(ExclusiveContext *cx, AllocKind thingKind, size_t thingSize) { MOZ_ASSERT(cx->arenas()->freeLists[thingKind].isEmpty()); if (cx->isJSContext()) - return refillFreeListFromMainThread(cx->asJSContext(), thingKind); + return refillFreeListFromMainThread(cx->asJSContext(), thingKind, thingSize); return refillFreeListOffMainThread(cx, thingKind); } template /* static */ void * -GCRuntime::refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind) +GCRuntime::refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind, size_t thingSize) { JSRuntime *rt = cx->runtime(); MOZ_ASSERT(!rt->isHeapBusy(), "allocating while under GC"); @@ -277,7 +277,11 @@ GCRuntime::refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind) } // Retry the allocation after the last-ditch GC. - thing = tryRefillFreeListFromMainThread(cx, thingKind); + // Note that due to GC callbacks we might already have allocated an arena + // for this thing kind! + thing = cx->arenas()->allocateFromFreeList(thingKind, thingSize); + if (!thing) + thing = tryRefillFreeListFromMainThread(cx, thingKind); if (thing) return thing; diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index f8d525996b00..4d476d20f5d7 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -879,9 +879,11 @@ class GCRuntime template static void checkIncrementalZoneState(ExclusiveContext *cx, T *t); template - static void *refillFreeListFromAnyThread(ExclusiveContext *cx, AllocKind thingKind); + static void *refillFreeListFromAnyThread(ExclusiveContext *cx, AllocKind thingKind, + size_t thingSize); template - static void *refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind); + static void *refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind, + size_t thingSize); static void *tryRefillFreeListFromMainThread(JSContext *cx, AllocKind thingKind); static void *refillFreeListOffMainThread(ExclusiveContext *cx, AllocKind thingKind); diff --git a/js/src/jit-test/tests/gc/bug-1146696.js b/js/src/jit-test/tests/gc/bug-1146696.js new file mode 100644 index 000000000000..fc08642431b9 --- /dev/null +++ b/js/src/jit-test/tests/gc/bug-1146696.js @@ -0,0 +1,18 @@ +// |jit-test| error: out of memory +dbg1 = new Debugger(); +root2 = newGlobal(); +dbg1.memory.onGarbageCollection = function(){} +dbg1.addDebuggee(root2); +for (var j = 0; j < 9999; ++j) { + try { + a + } catch (e) {} +} +gcparam("maxBytes", gcparam("gcBytes") + 1); +g(); +function g() { + var x = ""; + function f() {} + eval(''); + g(); +}