From 68b0327ea98a11a04d4880adaf5ed402ecf4b25a Mon Sep 17 00:00:00 2001 From: Brian Hackett <bhackett1024@gmail.com> Date: Wed, 4 Dec 2013 12:41:36 -0800 Subject: [PATCH] Bug 942984 - Set native stack limit for JS worker threads, r=billm a=lsblakk. --- js/src/jscntxt.cpp | 5 ++++- js/src/jscntxt.h | 1 + js/src/jsworkers.cpp | 35 +++++++++++++++++++++++++++++++++-- js/src/jsworkers.h | 1 + 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 013f1fae599ff..f68e2109b2161 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -423,7 +423,10 @@ js_ReportOverRecursed(JSContext *maybecx) void js_ReportOverRecursed(ThreadSafeContext *cx) { - js_ReportOverRecursed(cx->maybeJSContext()); + if (cx->isJSContext()) + js_ReportOverRecursed(cx->asJSContext()); + else if (cx->isExclusiveContext()) + cx->asExclusiveContext()->addPendingOverRecursed(); } void diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index cd3879104b92c..cd155e0ef35ee 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -402,6 +402,7 @@ class ExclusiveContext : public ThreadSafeContext // Methods specific to any WorkerThread for the context. frontend::CompileError &addPendingCompileError(); + void addPendingOverRecursed(); }; inline void diff --git a/js/src/jsworkers.cpp b/js/src/jsworkers.cpp index 9f78d642aea19..9e32046703500 100644 --- a/js/src/jsworkers.cpp +++ b/js/src/jsworkers.cpp @@ -9,6 +9,7 @@ #ifdef JS_WORKER_THREADS #include "mozilla/DebugOnly.h" +#include "jsnativestack.h" #include "prmjtime.h" #include "frontend/BytecodeCompiler.h" @@ -22,6 +23,7 @@ using namespace js; +using mozilla::ArrayLength; using mozilla::DebugOnly; bool @@ -179,7 +181,8 @@ ParseTask::ParseTask(ExclusiveContext *cx, const CompileOptions &options, JS::OffThreadCompileCallback callback, void *callbackData) : cx(cx), options(options), chars(chars), length(length), alloc(JSRuntime::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), scopeChain(scopeChain), - callback(callback), callbackData(callbackData), script(nullptr), errors(cx) + callback(callback), callbackData(callbackData), script(nullptr), + errors(cx), overRecursed(false) { JSRuntime *rt = scopeChain->runtimeFromMainThread(); @@ -310,6 +313,9 @@ js::WaitForOffThreadParsingToFinish(JSRuntime *rt) } } +static const uint32_t WORKER_STACK_SIZE = 512 * 1024; +static const uint32_t WORKER_STACK_QUOTA = 450 * 1024; + bool WorkerThreadState::init(JSRuntime *rt) { @@ -345,7 +351,7 @@ WorkerThreadState::init(JSRuntime *rt) helper.threadData.ref().addToThreadList(); helper.thread = PR_CreateThread(PR_USER_THREAD, WorkerThread::ThreadMain, &helper, - PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); + PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, WORKER_STACK_SIZE); if (!helper.thread || !helper.threadData.ref().init()) { for (size_t j = 0; j < numThreads; j++) threads[j].destroy(); @@ -578,6 +584,8 @@ WorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *toke AutoCompartment ac(maybecx, parseTask->scopeChain); for (size_t i = 0; i < parseTask->errors.length(); i++) parseTask->errors[i]->throwError(maybecx); + if (parseTask->overRecursed) + js_ReportOverRecursed(maybecx); if (script) { // The Debugger only needs to be told about the topmost script that was compiled. @@ -729,6 +737,13 @@ ExclusiveContext::addPendingCompileError() return *error; } +void +ExclusiveContext::addPendingOverRecursed() +{ + if (workerThread()->parseTask) + workerThread()->parseTask->overRecursed = true; +} + void WorkerThread::handleParseWorkload(WorkerThreadState &state) { @@ -894,6 +909,16 @@ WorkerThread::threadLoop() js::TlsPerThreadData.set(threadData.addr()); + // Compute the thread's stack limit, for over-recursed checks. + uintptr_t stackLimit = GetNativeStackBase(); +#if JS_STACK_GROWTH_DIRECTION > 0 + stackLimit += WORKER_STACK_QUOTA; +#else + stackLimit -= WORKER_STACK_QUOTA; +#endif + for (size_t i = 0; i < ArrayLength(threadData.ref().nativeStackLimit); i++) + threadData.ref().nativeStackLimit[i] = stackLimit; + while (true) { JS_ASSERT(!ionBuilder && !asmData); @@ -1113,4 +1138,10 @@ ExclusiveContext::addPendingCompileError() MOZ_ASSUME_UNREACHABLE("Off thread compilation not available."); } +void +ExclusiveContext::addPendingOverRecursed() +{ + MOZ_ASSUME_UNREACHABLE("Off thread compilation not available."); +} + #endif /* JS_WORKER_THREADS */ diff --git a/js/src/jsworkers.h b/js/src/jsworkers.h index bfec31af59cbe..32bd43716e98c 100644 --- a/js/src/jsworkers.h +++ b/js/src/jsworkers.h @@ -413,6 +413,7 @@ struct ParseTask // Any errors or warnings produced during compilation. These are reported // when finishing the script. Vector<frontend::CompileError *> errors; + bool overRecursed; ParseTask(ExclusiveContext *cx, const CompileOptions &options, const jschar *chars, size_t length, JSObject *scopeChain, -- GitLab