From aaa99c61c514783e641a105f3b53d9cfc36c8412 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Sun, 31 Jul 2011 20:50:42 +0200 Subject: [PATCH] bug 684569 - remove support for custom chunk allocation. r=nnethercote --HG-- rename : js/src/jsapi-tests/testGCChunkAlloc.cpp => js/src/jsapi-tests/testGCOutOfMemory.cpp --- js/src/jsapi-tests/Makefile.in | 2 +- js/src/jsapi-tests/testGCChunkAlloc.cpp | 131 ----------------------- js/src/jsapi-tests/testGCOutOfMemory.cpp | 68 ++++++++++++ js/src/jsapi.cpp | 3 +- js/src/jscntxt.h | 8 -- js/src/jsgc.cpp | 4 +- js/src/jsgcchunk.cpp | 6 +- js/src/jsgcchunk.h | 36 +------ js/src/xpconnect/src/xpcjsruntime.cpp | 36 ------- 9 files changed, 76 insertions(+), 218 deletions(-) delete mode 100644 js/src/jsapi-tests/testGCChunkAlloc.cpp create mode 100644 js/src/jsapi-tests/testGCOutOfMemory.cpp diff --git a/js/src/jsapi-tests/Makefile.in b/js/src/jsapi-tests/Makefile.in index 4e57b175927e..98a251841c56 100644 --- a/js/src/jsapi-tests/Makefile.in +++ b/js/src/jsapi-tests/Makefile.in @@ -65,7 +65,7 @@ CPPSRCS = \ testExternalStrings.cpp \ testFuncCallback.cpp \ testFunctionProperties.cpp \ - testGCChunkAlloc.cpp \ + testGCOutOfMemory.cpp \ testGetPropertyDefault.cpp \ testIndexToString.cpp \ testIntString.cpp \ diff --git a/js/src/jsapi-tests/testGCChunkAlloc.cpp b/js/src/jsapi-tests/testGCChunkAlloc.cpp deleted file mode 100644 index d126c1d53b81..000000000000 --- a/js/src/jsapi-tests/testGCChunkAlloc.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=99: - * - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - * Contributor: Igor Bukanov - */ - -#include "tests.h" -#include "jsgcchunk.h" -#include "jscntxt.h" - -/* We allow to allocate 2 (system/user) chunks. */ - -static const int SYSTEM = 0; -static const int USER = 1; -static const int N_POOLS = 2; - -class CustomGCChunkAllocator: public js::GCChunkAllocator { - public: - CustomGCChunkAllocator() { pool[SYSTEM] = NULL; pool[USER] = NULL; } - void *pool[N_POOLS]; - - private: - - virtual void *doAlloc() { - if (!pool[SYSTEM] && !pool[USER]) - return NULL; - void *chunk = NULL; - if (pool[SYSTEM]) { - chunk = pool[SYSTEM]; - pool[SYSTEM] = NULL; - } else { - chunk = pool[USER]; - pool[USER] = NULL; - } - return chunk; - } - - virtual void doFree(void *chunk) { - JS_ASSERT(!pool[SYSTEM] || !pool[USER]); - if (!pool[SYSTEM]) { - pool[SYSTEM] = chunk; - } else { - pool[USER] = chunk; - } - } -}; - -static CustomGCChunkAllocator customGCChunkAllocator; - -static unsigned errorCount = 0; - -static void -ErrorCounter(JSContext *cx, const char *message, JSErrorReport *report) -{ - ++errorCount; -} - -BEGIN_TEST(testGCChunkAlloc) -{ - JS_SetErrorReporter(cx, ErrorCounter); - - jsvalRoot root(cx); - - /* - * We loop until out-of-memory happens during the chunk allocation. But - * we have to disable the jit since it cannot tolerate OOM during the - * chunk allocation. - */ - JS_ToggleOptions(cx, JSOPTION_JIT); - - static const char source[] = - "var max = 0; (function() {" - " var array = [];" - " for (; ; ++max)" - " array.push({});" - "})();"; - JSBool ok = JS_EvaluateScript(cx, global, source, strlen(source), "", 1, - root.addr()); - - /* Check that we get OOM. */ - CHECK(!ok); - CHECK(!JS_IsExceptionPending(cx)); - CHECK_EQUAL(errorCount, 1); - CHECK(!customGCChunkAllocator.pool[SYSTEM]); - CHECK(!customGCChunkAllocator.pool[USER]); - JS_GC(cx); - JS_ToggleOptions(cx, JSOPTION_JIT); - EVAL("(function() {" - " var array = [];" - " for (var i = max >> 1; i != 0;) {" - " --i;" - " array.push({});" - " }" - "})();", root.addr()); - CHECK_EQUAL(errorCount, 1); - return true; -} - -virtual JSRuntime * createRuntime() { - /* - * To test failure of chunk allocation allow to use GC twice the memory - * the single chunk contains. - */ - JSRuntime *rt = JS_NewRuntime(2 * js::GC_CHUNK_SIZE); - if (!rt) - return NULL; - - customGCChunkAllocator.pool[SYSTEM] = js::AllocGCChunk(); - customGCChunkAllocator.pool[USER] = js::AllocGCChunk(); - JS_ASSERT(customGCChunkAllocator.pool[SYSTEM]); - JS_ASSERT(customGCChunkAllocator.pool[USER]); - - rt->setCustomGCChunkAllocator(&customGCChunkAllocator); - return rt; -} - -virtual void destroyRuntime() { - JS_DestroyRuntime(rt); - - /* We should get the initial chunk back at this point. */ - JS_ASSERT(customGCChunkAllocator.pool[SYSTEM]); - JS_ASSERT(customGCChunkAllocator.pool[USER]); - js::FreeGCChunk(customGCChunkAllocator.pool[SYSTEM]); - js::FreeGCChunk(customGCChunkAllocator.pool[USER]); - customGCChunkAllocator.pool[SYSTEM] = NULL; - customGCChunkAllocator.pool[USER] = NULL; -} - -END_TEST(testGCChunkAlloc) diff --git a/js/src/jsapi-tests/testGCOutOfMemory.cpp b/js/src/jsapi-tests/testGCOutOfMemory.cpp new file mode 100644 index 000000000000..f737bb4cbcdb --- /dev/null +++ b/js/src/jsapi-tests/testGCOutOfMemory.cpp @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=99: + * + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: Igor Bukanov + */ + +#include "tests.h" +#include "jsgcchunk.h" +#include "jscntxt.h" + +static unsigned errorCount = 0; + +static void +ErrorCounter(JSContext *cx, const char *message, JSErrorReport *report) +{ + ++errorCount; +} + +BEGIN_TEST(testGCOutOfMemory) +{ + JS_SetErrorReporter(cx, ErrorCounter); + + jsvalRoot root(cx); + + /* + * We loop until we get out-of-memory. We have to disable the jit since it + * ignores the runtime allocation limits during execution. + */ + JS_ToggleOptions(cx, JSOPTION_JIT); + + static const char source[] = + "var max = 0; (function() {" + " var array = [];" + " for (; ; ++max)" + " array.push({});" + " array = []; array.push(0);" + "})();"; + JSBool ok = JS_EvaluateScript(cx, global, source, strlen(source), "", 1, + root.addr()); + + /* Check that we get OOM. */ + CHECK(!ok); + CHECK(!JS_IsExceptionPending(cx)); + CHECK_EQUAL(errorCount, 1); + JS_GC(cx); + JS_ToggleOptions(cx, JSOPTION_JIT); + EVAL("(function() {" + " var array = [];" + " for (var i = max >> 2; i != 0;) {" + " --i;" + " array.push({});" + " }" + "})();", root.addr()); + CHECK_EQUAL(errorCount, 1); + return true; +} + +virtual JSRuntime * createRuntime() { + return JS_NewRuntime(256 * 1024); +} + +virtual void destroyRuntime() { + JS_DestroyRuntime(rt); +} + +END_TEST(testGCOutOfMemory) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 2fb68bdfefa7..e740e8c9d07b 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -638,8 +638,7 @@ JS_IsBuiltinFunctionConstructor(JSFunction *fun) static JSBool js_NewRuntimeWasCalled = JS_FALSE; JSRuntime::JSRuntime() - : gcChunkAllocator(&defaultGCChunkAllocator), - trustedPrincipals_(NULL) + : trustedPrincipals_(NULL) { /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */ JS_INIT_CLIST(&contextList); diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 2f30ccfc6400..dd23ace50e77 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -512,14 +512,6 @@ struct JSRuntime { volatile ptrdiff_t gcMallocBytes; public: - js::GCChunkAllocator *gcChunkAllocator; - - void setCustomGCChunkAllocator(js::GCChunkAllocator *allocator) { - JS_ASSERT(allocator); - JS_ASSERT(state == JSRTS_DOWN); - gcChunkAllocator = allocator; - } - /* * The trace operation and its data argument to trace embedding-specific * GC roots. diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index aa42f0f457d3..3bfae14d3f61 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -534,7 +534,7 @@ Chunk::releaseArena(ArenaHeader *aheader) inline Chunk * AllocateGCChunk(JSRuntime *rt) { - Chunk *p = (Chunk *)rt->gcChunkAllocator->alloc(); + Chunk *p = static_cast(AllocGCChunk()); #ifdef MOZ_GCTIMER if (p) JS_ATOMIC_INCREMENT(&newChunkCount); @@ -549,7 +549,7 @@ ReleaseGCChunk(JSRuntime *rt, Chunk *p) #ifdef MOZ_GCTIMER JS_ATOMIC_INCREMENT(&destroyChunkCount); #endif - rt->gcChunkAllocator->free_(p); + FreeGCChunk(p); } /* The caller must hold the GC lock. */ diff --git a/js/src/jsgcchunk.cpp b/js/src/jsgcchunk.cpp index 551f6b7ebfa9..2529166fe9cb 100644 --- a/js/src/jsgcchunk.cpp +++ b/js/src/jsgcchunk.cpp @@ -272,8 +272,6 @@ UnmapPages(void *addr, size_t size) namespace js { -GCChunkAllocator defaultGCChunkAllocator; - inline void * FindChunkStart(void *p) { @@ -282,7 +280,7 @@ FindChunkStart(void *p) return reinterpret_cast(addr); } -JS_FRIEND_API(void *) +void * AllocGCChunk() { void *p; @@ -329,7 +327,7 @@ AllocGCChunk() return p; } -JS_FRIEND_API(void) +void FreeGCChunk(void *p) { JS_ASSERT(p); diff --git a/js/src/jsgcchunk.h b/js/src/jsgcchunk.h index 94d37ae2d329..df648ce9545d 100644 --- a/js/src/jsgcchunk.h +++ b/js/src/jsgcchunk.h @@ -49,44 +49,12 @@ const size_t GC_CHUNK_SHIFT = 20; const size_t GC_CHUNK_SIZE = size_t(1) << GC_CHUNK_SHIFT; const size_t GC_CHUNK_MASK = GC_CHUNK_SIZE - 1; -JS_FRIEND_API(void *) +void * AllocGCChunk(); -JS_FRIEND_API(void) +void FreeGCChunk(void *p); -class GCChunkAllocator { - public: - GCChunkAllocator() {} - - void *alloc() { - void *chunk = doAlloc(); - JS_ASSERT(!(reinterpret_cast(chunk) & GC_CHUNK_MASK)); - return chunk; - } - - void free_(void *chunk) { - JS_ASSERT(chunk); - JS_ASSERT(!(reinterpret_cast(chunk) & GC_CHUNK_MASK)); - doFree(chunk); - } - - private: - virtual void *doAlloc() { - return AllocGCChunk(); - } - - virtual void doFree(void *chunk) { - FreeGCChunk(chunk); - } - - /* No copy or assignment semantics. */ - GCChunkAllocator(const GCChunkAllocator &); - void operator=(const GCChunkAllocator &); -}; - -extern GCChunkAllocator defaultGCChunkAllocator; - } #endif /* jsgchunk_h__ */ diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index 3860dce81ddb..66855f176005 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -1445,41 +1445,7 @@ MakeMemoryReporterPath(const nsACString &pathPrefix, } // anonymous namespace -class XPConnectGCChunkAllocator - : public js::GCChunkAllocator -{ -public: - XPConnectGCChunkAllocator() {} - -private: - virtual void *doAlloc() { - void *chunk; -#ifdef MOZ_MEMORY - // posix_memalign returns zero on success, nonzero on failure. - if (posix_memalign(&chunk, js::GC_CHUNK_SIZE, js::GC_CHUNK_SIZE)) - chunk = 0; -#else - chunk = js::AllocGCChunk(); -#endif - return chunk; - } - - virtual void doFree(void *chunk) { -#ifdef MOZ_MEMORY - free(chunk); -#else - js::FreeGCChunk(chunk); -#endif - } -}; - -static XPConnectGCChunkAllocator gXPCJSChunkAllocator; - -#ifdef MOZ_MEMORY -#define JS_GC_HEAP_KIND nsIMemoryReporter::KIND_HEAP -#else #define JS_GC_HEAP_KIND nsIMemoryReporter::KIND_NONHEAP -#endif // We have per-compartment GC heap totals, so we can't put the total GC heap // size in the explicit allocations tree. But it's a useful figure, so put it @@ -2087,8 +2053,6 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) mJSRuntime->setActivityCallback(ActivityCallback, this); - mJSRuntime->setCustomGCChunkAllocator(&gXPCJSChunkAllocator); - NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap)); NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount)); NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));