☠☠ backed out by 831a02dbf05d ☠ ☠ | |
author | Jon Coppeard <jcoppeard@mozilla.com> |
Thu, 02 Nov 2017 14:51:27 +0000 | |
changeset 443106 | d3a0101e3936adcd5eb90c48c4fd6d768c6fabe3 |
parent 443105 | a602f924a33cafea259840a298e682d49fe4cc19 |
child 443131 | 3f56c67e2a2ab7404641d19dec37254c2523d475 |
push id | 1618 |
push user | Callek@gmail.com |
push date | Thu, 11 Jan 2018 17:45:48 +0000 |
treeherder | mozilla-release@882ca853e05a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | njn, nbp |
bugs | 1410132 |
milestone | 58.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/config/check_spidermonkey_style.py +++ b/config/check_spidermonkey_style.py @@ -64,16 +64,17 @@ included_inclnames_to_ignore = set([ 'double-conversion.h', # strange MFBT case 'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined 'frontend/ReservedWordsGenerated.h', # generated in $OBJDIR 'gc/StatsPhasesGenerated.h', # generated in $OBJDIR 'gc/StatsPhasesGenerated.cpp', # generated in $OBJDIR 'jscustomallocator.h', # provided by embedders; allowed to be missing 'js-config.h', # generated in $OBJDIR 'fdlibm.h', # fdlibm + 'mozmemory.h', # included without a path 'pratom.h', # NSPR 'prcvar.h', # NSPR 'prerror.h', # NSPR 'prinit.h', # NSPR 'prio.h', # NSPR 'private/pprio.h', # NSPR 'prlink.h', # NSPR 'prlock.h', # NSPR
--- a/js/public/Utility.h +++ b/js/public/Utility.h @@ -21,16 +21,18 @@ #ifdef JS_OOM_DO_BACKTRACES #include <execinfo.h> #include <stdio.h> #endif #include "jstypes.h" +#include "mozmemory.h" + /* The public JS engine namespace. */ namespace JS {} /* The mozilla-shared reusable template/utility namespace. */ namespace mozilla {} /* The private JS engine namespace. */ namespace js {} @@ -359,55 +361,65 @@ struct MOZ_RAII JS_PUBLIC_DATA(AutoEnter bool oomEnabled_; int64_t oomAfter_; #endif }; } /* namespace js */ +// Malloc allocation. + +namespace js { + +extern JS_PUBLIC_DATA(arena_id_t) MallocArena; + +extern void InitMallocAllocator(); +extern void ShutDownMallocAllocator(); + +} /* namespace js */ + static inline void* js_malloc(size_t bytes) { JS_OOM_POSSIBLY_FAIL(); - return malloc(bytes); + return moz_arena_malloc(js::MallocArena, bytes); } static inline void* js_calloc(size_t bytes) { JS_OOM_POSSIBLY_FAIL(); - return calloc(bytes, 1); + return moz_arena_calloc(js::MallocArena, bytes, 1); } static inline void* js_calloc(size_t nmemb, size_t size) { JS_OOM_POSSIBLY_FAIL(); - return calloc(nmemb, size); + return moz_arena_calloc(js::MallocArena, nmemb, size); } static inline void* js_realloc(void* p, size_t bytes) { // realloc() with zero size is not portable, as some implementations may // return nullptr on success and free |p| for this. We assume nullptr // indicates failure and that |p| is still valid. MOZ_ASSERT(bytes != 0); JS_OOM_POSSIBLY_FAIL(); - return realloc(p, bytes); + return moz_arena_realloc(js::MallocArena, p, bytes); } static inline void js_free(void* p) { + // TODO: This should call |moz_arena_free(js::MallocArena, p)| but we + // currently can't enforce that all memory freed here was allocated by + // js_malloc(). free(p); } -static inline char* js_strdup(const char* s) -{ - JS_OOM_POSSIBLY_FAIL(); - return strdup(s); -} +JS_PUBLIC_API(char*) js_strdup(const char* s); #endif/* JS_USE_CUSTOM_ALLOCATOR */ #include <new> /* * Low-level memory management in SpiderMonkey: * * ** Do not use the standard malloc/free/realloc: SpiderMonkey allows these
--- a/js/src/jsapi-tests/testHashTable.cpp +++ b/js/src/jsapi-tests/testHashTable.cpp @@ -389,22 +389,23 @@ BEGIN_TEST(testHashMapLookupWithDefaultO return true; } END_TEST(testHashMapLookupWithDefaultOOM) #endif // defined(DEBUG) BEGIN_TEST(testHashTableMovableEnum) { + IntSet set; CHECK(set.init()); // Exercise returning a hash table Enum object from a function. CHECK(set.put(1)); - for (auto e = enumerateSet(); !e.empty(); e.popFront()) + for (auto e = enumerateSet(set); !e.empty(); e.popFront()) e.removeFront(); CHECK(set.count() == 0); // Test moving an Enum object explicitly. CHECK(set.put(1)); CHECK(set.put(2)); CHECK(set.put(3)); @@ -420,16 +421,14 @@ BEGIN_TEST(testHashTableMovableEnum) e2.removeFront(); e2.popFront(); } CHECK(set.count() == 1); return true; } -IntSet set; - -IntSet::Enum enumerateSet() +IntSet::Enum enumerateSet(IntSet& set) { return IntSet::Enum(set); } END_TEST(testHashTableMovableEnum)
--- a/js/src/jsapi-tests/tests.cpp +++ b/js/src/jsapi-tests/tests.cpp @@ -40,16 +40,17 @@ void JSAPITest::uninit() JS_LeaveCompartment(cx, nullptr); global = nullptr; } if (cx) { JS_EndRequest(cx); destroyContext(); cx = nullptr; } + msgs.clear(); } bool JSAPITest::exec(const char* bytes, const char* filename, int lineno) { JS::RootedValue v(cx); JS::CompileOptions opts(cx); opts.setFileAndLine(filename, lineno); return JS::Evaluate(cx, opts, bytes, strlen(bytes), &v) ||
--- a/js/src/jsapi-tests/tests.h +++ b/js/src/jsapi-tests/tests.h @@ -28,16 +28,17 @@ class JSAPITestString { public: JSAPITestString() {} explicit JSAPITestString(const char* s) { *this += s; } JSAPITestString(const JSAPITestString& s) { *this += s; } const char* begin() const { return chars.begin(); } const char* end() const { return chars.end(); } size_t length() const { return chars.length(); } + void clear() { chars.clearAndFree(); } JSAPITestString& operator +=(const char* s) { if (!chars.append(s, strlen(s))) abort(); return *this; } JSAPITestString& operator +=(const JSAPITestString& s) {
--- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -3863,17 +3863,22 @@ js::DuplicateString(JSContext* cx, const return ret; PodCopy(ret.get(), s, n); return ret; } UniqueChars js::DuplicateString(const char* s) { - return UniqueChars(js_strdup(s)); + size_t n = strlen(s) + 1; + UniqueChars ret(js_pod_malloc<char>(n)); + if (!ret) + return ret; + PodCopy(ret.get(), s, n); + return ret; } UniqueChars js::DuplicateString(const char* s, size_t n) { UniqueChars ret(js_pod_malloc<char>(n + 1)); if (!ret) return nullptr; @@ -3894,16 +3899,22 @@ js::DuplicateString(const char16_t* s, s UniqueTwoByteChars ret(js_pod_malloc<char16_t>(n + 1)); if (!ret) return nullptr; PodCopy(ret.get(), s, n); ret[n] = 0; return ret; } +JS_PUBLIC_API(char*) +js_strdup(const char* s) +{ + return DuplicateString(s).release(); +} + template <typename CharT> const CharT* js_strchr_limit(const CharT* s, char16_t c, const CharT* limit) { while (s < limit) { if (*s == c) return s; s++;
--- a/js/src/jsutil.cpp +++ b/js/src/jsutil.cpp @@ -165,16 +165,30 @@ ResetSimulatedInterrupt() maxInterruptChecks = UINT64_MAX; interruptCheckFailAlways = false; } } // namespace oom } // namespace js #endif // defined(DEBUG) || defined(JS_OOM_BREAKPOINT) +JS_PUBLIC_DATA(arena_id_t) js::MallocArena; + +void +js::InitMallocAllocator() +{ + MallocArena = moz_create_arena(); +} + +void +js::ShutDownMallocAllocator() +{ + moz_dispose_arena(MallocArena); +} + JS_PUBLIC_API(void) JS_Assert(const char* s, const char* file, int ln) { MOZ_ReportAssertionFailure(s, file, ln); MOZ_CRASH(); } #ifdef __linux__
--- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3987,16 +3987,18 @@ KillWorkerThreads(JSContext* cx) AutoLockWorkerThreads alwt; if (workerThreads.empty()) break; thread = workerThreads.popCopy(); } thread->join(); } + workerThreads.clearAndFree(); + js_delete(workerThreadsLock); workerThreadsLock = nullptr; js_delete(cooperationState); cooperationState = nullptr; } static void @@ -4922,22 +4924,22 @@ NestedShell(JSContext* cx, unsigned argc AutoCStringVector argv(cx); // The first argument to the shell is its path, which we assume is our own // argv[0]. if (sArgc < 1) { JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL); return false; } - if (!argv.append(strdup(sArgv[0]))) + if (!argv.append(js_strdup(sArgv[0]))) return false; // Propagate selected flags from the current shell for (unsigned i = 0; i < sPropagatedFlags.length(); i++) { - char* cstr = strdup(sPropagatedFlags[i]); + char* cstr = js_strdup(sPropagatedFlags[i]); if (!cstr || !argv.append(cstr)) return false; } // The arguments to nestedShell are stringified and append to argv. RootedString str(cx); for (unsigned i = 0; i < args.length(); i++) { str = ToString(cx, args[i]); @@ -5748,16 +5750,17 @@ ConsumeBufferSource(JSContext* cx, JS::H static void ShutdownBufferStreams() { auto state = bufferStreamState.lock(); state->shutdown = true; while (!state->jobs.empty()) state.wait(/* jobs empty */); + state->jobs.clearAndFree(); } static bool SetBufferStreamParams(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!args.requireAtLeast(cx, "setBufferStreamParams", 2)) return false; @@ -8647,16 +8650,22 @@ main(int argc, char** argv, char** envp) RCFile rcStdout(stdout); rcStdout.acquire(); RCFile rcStderr(stderr); rcStderr.acquire(); SetOutputFile("JS_STDOUT", &rcStdout, &gOutFile); SetOutputFile("JS_STDERR", &rcStderr, &gErrFile); + // Start the engine. + if (!JS_Init()) + return 1; + + auto shutdownEngine = MakeScopeExit([]() { JS_ShutDown(); }); + OptionParser op("Usage: {progname} [options] [[script] scriptArgs*]"); op.setDescription("The SpiderMonkey shell provides a command line interface to the " "JavaScript engine. Code and file options provided via the command line are " "run left to right. If provided, the optional script argument is run after " "all options have been processed. Just-In-Time compilation modes may be enabled via " "command line options."); op.setDescriptionWidth(72); @@ -8870,20 +8879,16 @@ main(int argc, char** argv, char** envp) js::jit::CPUInfo::SetAVXEnabled(); PropagateFlagToNestedShells("--enable-avx"); } #endif if (op.getBoolOption("no-threads")) js::DisableExtraThreads(); - // Start the engine. - if (!JS_Init()) - return 1; - if (!InitSharedArrayBufferMailbox()) return 1; // The fake CPU count must be set before initializing the Runtime, // which spins up the thread pool. int32_t cpuCount = op.getIntOption("cpu-count"); // What we're really setting if (cpuCount < 0) cpuCount = op.getIntOption("thread-count"); // Legacy name @@ -8974,11 +8979,10 @@ main(int argc, char** argv, char** envp) KillWatchdog(cx); KillWorkerThreads(cx); ShutdownBufferStreams(); DestructSharedArrayBufferMailbox(); JS_DestroyContext(cx); - JS_ShutDown(); return result; }
--- a/js/src/vm/Initialization.cpp +++ b/js/src/vm/Initialization.cpp @@ -95,16 +95,18 @@ JS::detail::InitWithFailureDiagnostic(bo #endif RETURN_IF_FAIL(js::TlsContext.init()); #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) RETURN_IF_FAIL(js::oom::InitThreadType()); #endif + js::InitMallocAllocator(); + RETURN_IF_FAIL(js::Mutex::Init()); RETURN_IF_FAIL(js::wasm::InitInstanceStaticData()); js::gc::InitMemorySubsystem(); // Ensure gc::SystemPageSize() works. RETURN_IF_FAIL(js::jit::InitProcessExecutableMemory()); @@ -165,16 +167,17 @@ JS_ShutDown(void) #ifdef JS_TRACE_LOGGING js::DestroyTraceLoggerThreadState(); js::DestroyTraceLoggerGraphState(); #endif js::MemoryProtectionExceptionHandler::uninstall(); js::wasm::ShutDownInstanceStaticData(); + js::wasm::ShutDownProcessStaticData(); js::Mutex::ShutDown(); // The only difficult-to-address reason for the restriction that you can't // call JS_Init/stuff/JS_ShutDown multiple times is the Windows PRMJ // NowInit initialization code, which uses PR_CallOnce to initialize the // PRMJ_Now subsystem. (For reinitialization to be permitted, we'd need to // "reset" the called-once status -- doable, but more trouble than it's @@ -194,16 +197,18 @@ JS_ShutDown(void) js::FinishDateTimeState(); if (!JSRuntime::hasLiveRuntimes()) { js::wasm::ReleaseBuiltinThunks(); js::jit::ReleaseProcessExecutableMemory(); } + js::ShutDownMallocAllocator(); + libraryInitState = InitState::ShutDown; } JS_PUBLIC_API(bool) JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn) { MOZ_ASSERT(libraryInitState == InitState::Uninitialized, "must call JS_SetICUMemoryFunctions before any other JSAPI "
--- a/js/src/wasm/WasmProcess.cpp +++ b/js/src/wasm/WasmProcess.cpp @@ -121,16 +121,23 @@ class ProcessCodeSegmentMap } ~ProcessCodeSegmentMap() { MOZ_ASSERT(segments1_.empty()); MOZ_ASSERT(segments2_.empty()); } + void freeAll() { + MOZ_ASSERT(segments1_.empty()); + MOZ_ASSERT(segments2_.empty()); + segments1_.clearAndFree(); + segments2_.clearAndFree(); + } + bool insert(const CodeSegment* cs) { LockGuard<Mutex> lock(mutatorsMutex_); size_t index; MOZ_ALWAYS_FALSE(BinarySearchIf(*mutableCodeSegments_, 0, mutableCodeSegments_->length(), CodeSegmentPC(cs->base()), &index)); if (!mutableCodeSegments_->insert(mutableCodeSegments_->begin() + index, cs)) @@ -225,8 +232,14 @@ wasm::LookupCodeSegment(const void* pc) } const Code* wasm::LookupCode(const void* pc) { const CodeSegment* found = LookupCodeSegment(pc); return found ? found->code() : nullptr; } + +void +wasm::ShutDownProcessStaticData() +{ + processCodeSegmentMap.freeAll(); +}
--- a/js/src/wasm/WasmProcess.h +++ b/js/src/wasm/WasmProcess.h @@ -46,12 +46,15 @@ extern mozilla::Atomic<bool> CodeExists; // via pc in the methods described above. bool RegisterCodeSegment(const CodeSegment* cs); void UnregisterCodeSegment(const CodeSegment* cs); +void +ShutDownProcessStaticData(); + } // namespace wasm } // namespace js #endif // wasm_process_h