From eb57959ceb60109122ff40ce0c4ffd7b21f19dee Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Mon, 30 Mar 2015 11:03:35 +0100 Subject: [PATCH] Bug 1146696 - Don't assume there are no arenas available after last ditch GC. r=terrence --HG-- extra : rebase_source : 20fc89a49cda291b70b1155f78bf9aac51cb94e9 --- js/src/gc/Allocator.cpp | 14 +++++++++----- js/src/gc/GCRuntime.h | 6 ++++-- js/src/jit-test/tests/gc/bug-1146696.js | 24 ++++++++++++++++++++++++ 3 files changed, 37 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 5b9b0cb2157c..fe38f7fab470 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 0f624557bdfe..cbb172ede242 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..afe003260262 --- /dev/null +++ b/js/src/jit-test/tests/gc/bug-1146696.js @@ -0,0 +1,24 @@ +// |jit-test| --no-ggc +gc(); +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") + 8000); +try { + function g(i) { + if (i == 0) + return; + var x = ""; + function f() {} + eval(''); + g(i - 1); + } + g(100); +} catch (e) { +}