Bug 1334845 - Create only one JSContext per helper thread, r=jandem.

--HG--
extra : rebase_source : 91db0da813d1cacb6ff3c0fdfd9d03f983ccf6cb
This commit is contained in:
Brian Hackett 2017-02-07 13:20:32 -07:00
Родитель 2f7cc13432
Коммит 0e46fcc795
3 изменённых файлов: 38 добавлений и 11 удалений

Просмотреть файл

@ -1031,7 +1031,7 @@ JSContext::~JSContext()
{
#ifdef XP_WIN
if (threadNative_)
CloseHandle((HANDLE)threadNative_);
CloseHandle((HANDLE)threadNative_.ref());
#endif
/* Free the stuff hanging off of cx. */
@ -1051,6 +1051,18 @@ JSContext::~JSContext()
TlsContext.set(nullptr);
}
void
JSContext::setRuntime(JSRuntime* rt)
{
MOZ_ASSERT(!resolvingList);
MOZ_ASSERT(!compartment());
MOZ_ASSERT(!activation());
MOZ_ASSERT(!unwrappedException_.ref().initialized());
MOZ_ASSERT(!asyncStackForNewActivations_.ref().initialized());
runtime_ = rt;
}
bool
JSContext::getPendingException(MutableHandleValue rval)
{

Просмотреть файл

@ -93,10 +93,10 @@ struct JSContext : public JS::RootingContext,
bool init();
private:
JSRuntime* const runtime_;
js::UnprotectedData<JSRuntime*> runtime_;
// System handle for the thread this context is associated with.
size_t threadNative_;
js::WriteOnceData<size_t> threadNative_;
// The thread on which this context is running, if this is performing a parse task.
js::ThreadLocalData<js::HelperThread*> helperThread_;
@ -106,6 +106,10 @@ struct JSContext : public JS::RootingContext,
js::ThreadLocalData<js::gc::ArenaLists*> arenas_;
public:
// This is used by helper threads to change the runtime their context is
// currently operating on.
void setRuntime(JSRuntime* rt);
size_t threadNative() const { return threadNative_; }
inline js::gc::ArenaLists* arenas() const { return arenas_; }

Просмотреть файл

@ -873,6 +873,16 @@ GlobalHelperThreadState::checkTaskThreadLimit(size_t maxThreads) const
return true;
}
struct MOZ_RAII AutoSetContextRuntime
{
explicit AutoSetContextRuntime(JSRuntime* rt) {
TlsContext.get()->setRuntime(rt);
}
~AutoSetContextRuntime() {
TlsContext.get()->setRuntime(nullptr);
}
};
static inline bool
IsHelperThreadSimulatingOOM(js::oom::ThreadType threadType)
{
@ -1182,15 +1192,15 @@ js::GCParallelTask::runFromMainThread(JSRuntime* rt)
void
js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& locked)
{
JSContext cx(runtime(), JS::ContextOptions());
AutoSetContextRuntime ascr(runtime());
gc::AutoSetThreadIsPerformingGC performingGC;
{
AutoUnlockHelperThreadState parallelSection(locked);
mozilla::TimeStamp timeStart = mozilla::TimeStamp::Now();
cx.heapState = JS::HeapState::MajorCollecting;
TlsContext.get()->heapState = JS::HeapState::MajorCollecting;
run();
cx.heapState = JS::HeapState::Idle;
TlsContext.get()->heapState = JS::HeapState::Idle;
duration_ = mozilla::TimeStamp::Now() - timeStart;
}
@ -1494,7 +1504,6 @@ HelperThread::handlePromiseTaskWorkload(AutoLockHelperThreadState& locked)
{
AutoUnlockHelperThreadState unlock(locked);
JSContext cx(nullptr, JS::ContextOptions());
task->execute();
@ -1548,7 +1557,7 @@ HelperThread::handleIonWorkload(AutoLockHelperThreadState& locked)
AutoTraceLog logScript(logger, event);
AutoTraceLog logCompile(logger, TraceLogger_IonCompilation);
JSContext cx(rt, JS::ContextOptions());
AutoSetContextRuntime ascr(rt);
jit::JitContext jctx(jit::CompileRuntime::get(rt),
jit::CompileCompartment::get(builder->script()->compartment()),
&builder->alloc());
@ -1665,13 +1674,13 @@ HelperThread::handleParseWorkload(AutoLockHelperThreadState& locked, uintptr_t s
for (size_t i = 0; i < ArrayLength(task->cx->nativeStackLimit); i++)
task->cx->nativeStackLimit[i] = stackLimit;
MOZ_ASSERT(!TlsContext.get());
JSContext* oldcx = TlsContext.get();
TlsContext.set(task->cx);
{
AutoUnlockHelperThreadState unlock(locked);
task->parse();
}
TlsContext.set(nullptr);
TlsContext.set(oldcx);
// The callback is invoked while we are still off the main thread.
task->callback(task, task->callbackData);
@ -1863,7 +1872,7 @@ HelperThread::handleGCHelperWorkload(AutoLockHelperThreadState& locked)
currentTask.emplace(HelperThreadState().gcHelperWorklist(locked).popCopy());
GCHelperState* task = gcHelperTask();
JSContext cx(task->runtime(), JS::ContextOptions());
AutoSetContextRuntime ascr(task->runtime());
{
AutoUnlockHelperThreadState unlock(locked);
@ -1882,6 +1891,8 @@ HelperThread::threadLoop()
JS::AutoSuppressGCAnalysis nogc;
AutoLockHelperThreadState lock;
JSContext cx(nullptr, JS::ContextOptions());
// Compute the thread's stack limit, for over-recursed checks.
uintptr_t stackLimit = GetNativeStackBase();
#if JS_STACK_GROWTH_DIRECTION > 0