зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 1559659) for SM bustages on Runtime.cpp . CLOSED TREE
Backed out changeset 1d509e451876 (bug 1559659) Backed out changeset f4b6a279a331 (bug 1559659) Backed out changeset fa9186737abd (bug 1559659)
This commit is contained in:
Родитель
a4cd447c57
Коммит
047fde9d4e
|
@ -1142,7 +1142,6 @@ AbortReasonOr<Ok> IonBuilder::buildInline(IonBuilder* callerBuilder,
|
||||||
void IonBuilder::runTask() {
|
void IonBuilder::runTask() {
|
||||||
// This is the entry point when ion compiles are run offthread.
|
// This is the entry point when ion compiles are run offthread.
|
||||||
JSRuntime* rt = script()->runtimeFromAnyThread();
|
JSRuntime* rt = script()->runtimeFromAnyThread();
|
||||||
AutoSetHelperThreadContext usesContext;
|
|
||||||
|
|
||||||
TraceLoggerThread* logger = TraceLoggerForCurrentThread();
|
TraceLoggerThread* logger = TraceLoggerForCurrentThread();
|
||||||
TraceLoggerEvent event(TraceLogger_AnnotateScripts, script());
|
TraceLoggerEvent event(TraceLogger_AnnotateScripts, script());
|
||||||
|
|
|
@ -65,17 +65,8 @@ GlobalHelperThreadState* gHelperThreadState = nullptr;
|
||||||
|
|
||||||
bool js::CreateHelperThreadsState() {
|
bool js::CreateHelperThreadsState() {
|
||||||
MOZ_ASSERT(!gHelperThreadState);
|
MOZ_ASSERT(!gHelperThreadState);
|
||||||
UniquePtr<GlobalHelperThreadState> helperThreadState =
|
gHelperThreadState = js_new<GlobalHelperThreadState>();
|
||||||
MakeUnique<GlobalHelperThreadState>();
|
return gHelperThreadState != nullptr;
|
||||||
if (!helperThreadState) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
gHelperThreadState = helperThreadState.release();
|
|
||||||
if (!gHelperThreadState->initializeHelperContexts()) {
|
|
||||||
js_delete(gHelperThreadState);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void js::DestroyHelperThreadsState() {
|
void js::DestroyHelperThreadsState() {
|
||||||
|
@ -444,43 +435,6 @@ struct MOZ_RAII AutoSetContextParse {
|
||||||
~AutoSetContextParse() { TlsContext.get()->setParseTask(nullptr); }
|
~AutoSetContextParse() { TlsContext.get()->setParseTask(nullptr); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// We want our default stack size limit to be approximately 2MB, to be safe, but
|
|
||||||
// expect most threads to use much less. On Linux, however, requesting a stack
|
|
||||||
// of 2MB or larger risks the kernel allocating an entire 2MB huge page for it
|
|
||||||
// on first access, which we do not want. To avoid this possibility, we subtract
|
|
||||||
// 2 standard VM page sizes from our default.
|
|
||||||
static const uint32_t kDefaultHelperStackSize = 2048 * 1024 - 2 * 4096;
|
|
||||||
static const uint32_t kDefaultHelperStackQuota = 1800 * 1024;
|
|
||||||
|
|
||||||
// TSan enforces a minimum stack size that's just slightly larger than our
|
|
||||||
// default helper stack size. It does this to store blobs of TSan-specific
|
|
||||||
// data on each thread's stack. Unfortunately, that means that even though
|
|
||||||
// we'll actually receive a larger stack than we requested, the effective
|
|
||||||
// usable space of that stack is significantly less than what we expect.
|
|
||||||
// To offset TSan stealing our stack space from underneath us, double the
|
|
||||||
// default.
|
|
||||||
//
|
|
||||||
// Note that we don't need this for ASan/MOZ_ASAN because ASan doesn't
|
|
||||||
// require all the thread-specific state that TSan does.
|
|
||||||
#if defined(MOZ_TSAN)
|
|
||||||
static const uint32_t HELPER_STACK_SIZE = 2 * kDefaultHelperStackSize;
|
|
||||||
static const uint32_t HELPER_STACK_QUOTA = 2 * kDefaultHelperStackQuota;
|
|
||||||
#else
|
|
||||||
static const uint32_t HELPER_STACK_SIZE = kDefaultHelperStackSize;
|
|
||||||
static const uint32_t HELPER_STACK_QUOTA = kDefaultHelperStackQuota;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AutoSetHelperThreadContext::AutoSetHelperThreadContext() {
|
|
||||||
AutoLockHelperThreadState lock;
|
|
||||||
cx = HelperThreadState().getFirstUnusedContext(lock);
|
|
||||||
MOZ_ASSERT(cx);
|
|
||||||
cx->setHelperThread(lock);
|
|
||||||
cx->nativeStackBase = GetNativeStackBase();
|
|
||||||
// When we set the JSContext, we need to reset the computed stack limits for
|
|
||||||
// the current thread, so we also set the native stack quota.
|
|
||||||
JS_SetNativeStackQuota(cx, HELPER_STACK_QUOTA);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const JSClass parseTaskGlobalClass = {"internal-parse-task-global",
|
static const JSClass parseTaskGlobalClass = {"internal-parse-task-global",
|
||||||
JSCLASS_GLOBAL_FLAGS,
|
JSCLASS_GLOBAL_FLAGS,
|
||||||
&JS::DefaultGlobalClassOps};
|
&JS::DefaultGlobalClassOps};
|
||||||
|
@ -543,14 +497,11 @@ size_t ParseTask::sizeOfExcludingThis(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseTask::runTask() {
|
void ParseTask::runTask() {
|
||||||
AutoSetHelperThreadContext usesContext;
|
|
||||||
|
|
||||||
JSContext* cx = TlsContext.get();
|
JSContext* cx = TlsContext.get();
|
||||||
JSRuntime* runtime = parseGlobal->runtimeFromAnyThread();
|
JSRuntime* runtime = parseGlobal->runtimeFromAnyThread();
|
||||||
|
|
||||||
AutoSetContextRuntime ascr(runtime);
|
AutoSetContextRuntime ascr(runtime);
|
||||||
AutoSetContextParse parsetask(this);
|
AutoSetContextParse parsetask(this);
|
||||||
gc::AutoSuppressNurseryCellAlloc noNurseryAlloc(cx);
|
|
||||||
|
|
||||||
Zone* zone = parseGlobal->zoneFromAnyThread();
|
Zone* zone = parseGlobal->zoneFromAnyThread();
|
||||||
zone->setHelperThreadOwnerContext(cx);
|
zone->setHelperThreadOwnerContext(cx);
|
||||||
|
@ -1123,6 +1074,32 @@ bool js::CurrentThreadIsParseThread() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// We want our default stack size limit to be approximately 2MB, to be safe, but
|
||||||
|
// expect most threads to use much less. On Linux, however, requesting a stack
|
||||||
|
// of 2MB or larger risks the kernel allocating an entire 2MB huge page for it
|
||||||
|
// on first access, which we do not want. To avoid this possibility, we subtract
|
||||||
|
// 2 standard VM page sizes from our default.
|
||||||
|
static const uint32_t kDefaultHelperStackSize = 2048 * 1024 - 2 * 4096;
|
||||||
|
static const uint32_t kDefaultHelperStackQuota = 1800 * 1024;
|
||||||
|
|
||||||
|
// TSan enforces a minimum stack size that's just slightly larger than our
|
||||||
|
// default helper stack size. It does this to store blobs of TSan-specific
|
||||||
|
// data on each thread's stack. Unfortunately, that means that even though
|
||||||
|
// we'll actually receive a larger stack than we requested, the effective
|
||||||
|
// usable space of that stack is significantly less than what we expect.
|
||||||
|
// To offset TSan stealing our stack space from underneath us, double the
|
||||||
|
// default.
|
||||||
|
//
|
||||||
|
// Note that we don't need this for ASan/MOZ_ASAN because ASan doesn't
|
||||||
|
// require all the thread-specific state that TSan does.
|
||||||
|
#if defined(MOZ_TSAN)
|
||||||
|
static const uint32_t HELPER_STACK_SIZE = 2 * kDefaultHelperStackSize;
|
||||||
|
static const uint32_t HELPER_STACK_QUOTA = 2 * kDefaultHelperStackQuota;
|
||||||
|
#else
|
||||||
|
static const uint32_t HELPER_STACK_SIZE = kDefaultHelperStackSize;
|
||||||
|
static const uint32_t HELPER_STACK_QUOTA = kDefaultHelperStackQuota;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool GlobalHelperThreadState::ensureInitialized() {
|
bool GlobalHelperThreadState::ensureInitialized() {
|
||||||
MOZ_ASSERT(CanUseExtraThreads());
|
MOZ_ASSERT(CanUseExtraThreads());
|
||||||
|
|
||||||
|
@ -1187,7 +1164,6 @@ void GlobalHelperThreadState::finish() {
|
||||||
while (!freeList.empty()) {
|
while (!freeList.empty()) {
|
||||||
jit::FreeIonBuilder(freeList.popCopy());
|
jit::FreeIonBuilder(freeList.popCopy());
|
||||||
}
|
}
|
||||||
destroyHelperContexts(lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalHelperThreadState::finishThreads() {
|
void GlobalHelperThreadState::finishThreads() {
|
||||||
|
@ -1202,46 +1178,9 @@ void GlobalHelperThreadState::finishThreads() {
|
||||||
threads.reset(nullptr);
|
threads.reset(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalHelperThreadState::initializeHelperContexts() {
|
void GlobalHelperThreadState::lock() { helperLock.lock(); }
|
||||||
AutoLockHelperThreadState lock;
|
|
||||||
for (size_t i = 0; i < threadCount; i++) {
|
|
||||||
UniquePtr<JSContext> cx =
|
|
||||||
js::MakeUnique<JSContext>(nullptr, JS::ContextOptions());
|
|
||||||
// To initialize context-specific protected data, the context must
|
|
||||||
// temporarily set itself to the main thread. After initialization,
|
|
||||||
// cx can clear itself from the thread.
|
|
||||||
cx->setHelperThread(lock);
|
|
||||||
if (!cx->init(ContextKind::HelperThread)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cx->clearHelperThread(lock);
|
|
||||||
if (!helperContexts_.append(cx.release())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSContext* GlobalHelperThreadState::getFirstUnusedContext(
|
void GlobalHelperThreadState::unlock() { helperLock.unlock(); }
|
||||||
AutoLockHelperThreadState& locked) {
|
|
||||||
for (auto& cx : helperContexts_) {
|
|
||||||
if (cx->contextAvailable(locked)) {
|
|
||||||
return cx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MOZ_CRASH("Expected available JSContext");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlobalHelperThreadState::destroyHelperContexts(
|
|
||||||
AutoLockHelperThreadState& lock) {
|
|
||||||
while (helperContexts_.length() > 0) {
|
|
||||||
JSContext* cx = helperContexts_.popCopy();
|
|
||||||
// Before cx can be destroyed, it has to set itself to the main thread.
|
|
||||||
// This enables it to pass its context-specific data checks.
|
|
||||||
cx->setHelperThread(lock);
|
|
||||||
js_delete(cx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool GlobalHelperThreadState::isLockedByCurrentThread() const {
|
bool GlobalHelperThreadState::isLockedByCurrentThread() const {
|
||||||
|
@ -1359,8 +1298,8 @@ void GlobalHelperThreadState::triggerFreeUnusedMemory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoLockHelperThreadState lock;
|
AutoLockHelperThreadState lock;
|
||||||
for (auto& context : helperContexts_) {
|
for (auto& thread : *threads) {
|
||||||
context->setFreeUnusedMemory(true);
|
thread.shouldFreeUnusedMemory = true;
|
||||||
}
|
}
|
||||||
notifyAll(PRODUCER, lock);
|
notifyAll(PRODUCER, lock);
|
||||||
}
|
}
|
||||||
|
@ -1768,11 +1707,11 @@ void js::GCParallelTask::runFromMainThread(JSRuntime* rt) {
|
||||||
void js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& lock) {
|
void js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& lock) {
|
||||||
MOZ_ASSERT(isDispatched(lock));
|
MOZ_ASSERT(isDispatched(lock));
|
||||||
|
|
||||||
|
AutoSetContextRuntime ascr(runtime());
|
||||||
|
gc::AutoSetThreadIsPerformingGC performingGC;
|
||||||
|
|
||||||
{
|
{
|
||||||
AutoUnlockHelperThreadState parallelSection(lock);
|
AutoUnlockHelperThreadState parallelSection(lock);
|
||||||
AutoSetHelperThreadContext usesContext;
|
|
||||||
AutoSetContextRuntime ascr(runtime());
|
|
||||||
gc::AutoSetThreadIsPerformingGC performingGC;
|
|
||||||
TimeStamp timeStart = ReallyNow();
|
TimeStamp timeStart = ReallyNow();
|
||||||
runTask();
|
runTask();
|
||||||
duration_ = TimeSince(timeStart);
|
duration_ = TimeSince(timeStart);
|
||||||
|
@ -2176,6 +2115,7 @@ void HelperThread::handleIonWorkload(AutoLockHelperThreadState& locked) {
|
||||||
|
|
||||||
{
|
{
|
||||||
AutoUnlockHelperThreadState unlock(locked);
|
AutoUnlockHelperThreadState unlock(locked);
|
||||||
|
AutoSetContextRuntime ascr(rt);
|
||||||
|
|
||||||
builder->runTask();
|
builder->runTask();
|
||||||
}
|
}
|
||||||
|
@ -2543,9 +2483,21 @@ void HelperThread::threadLoop() {
|
||||||
|
|
||||||
ensureRegisteredWithProfiler();
|
ensureRegisteredWithProfiler();
|
||||||
|
|
||||||
|
JSContext cx(nullptr, JS::ContextOptions());
|
||||||
|
{
|
||||||
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
|
if (!cx.init(ContextKind::HelperThread)) {
|
||||||
|
oomUnsafe.crash("HelperThread cx.init()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gc::AutoSuppressNurseryCellAlloc noNurseryAlloc(&cx);
|
||||||
|
JS_SetNativeStackQuota(&cx, HELPER_STACK_QUOTA);
|
||||||
|
|
||||||
while (!terminate) {
|
while (!terminate) {
|
||||||
MOZ_ASSERT(idle());
|
MOZ_ASSERT(idle());
|
||||||
|
|
||||||
|
maybeFreeUnusedMemory(&cx);
|
||||||
|
|
||||||
// The selectors may depend on the HelperThreadState not changing
|
// The selectors may depend on the HelperThreadState not changing
|
||||||
// between task selection and task execution, in particular, on new
|
// between task selection and task execution, in particular, on new
|
||||||
// tasks not being added (because of the lifo structure of the work
|
// tasks not being added (because of the lifo structure of the work
|
||||||
|
@ -2579,3 +2531,14 @@ const HelperThread::TaskSpec* HelperThread::findHighestPriorityTask(
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HelperThread::maybeFreeUnusedMemory(JSContext* cx) {
|
||||||
|
MOZ_ASSERT(idle());
|
||||||
|
|
||||||
|
cx->tempLifoAlloc().releaseAll();
|
||||||
|
|
||||||
|
if (shouldFreeUnusedMemory) {
|
||||||
|
cx->tempLifoAlloc().freeAll();
|
||||||
|
shouldFreeUnusedMemory = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -100,7 +100,6 @@ class GlobalHelperThreadState {
|
||||||
typedef Vector<GCParallelTask*, 0, SystemAllocPolicy> GCParallelTaskVector;
|
typedef Vector<GCParallelTask*, 0, SystemAllocPolicy> GCParallelTaskVector;
|
||||||
typedef Vector<PromiseHelperTask*, 0, SystemAllocPolicy>
|
typedef Vector<PromiseHelperTask*, 0, SystemAllocPolicy>
|
||||||
PromiseHelperTaskVector;
|
PromiseHelperTaskVector;
|
||||||
typedef Vector<JSContext*, 0, SystemAllocPolicy> ContextVector;
|
|
||||||
|
|
||||||
// List of available threads, or null if the thread state has not been
|
// List of available threads, or null if the thread state has not been
|
||||||
// initialized.
|
// initialized.
|
||||||
|
@ -147,9 +146,6 @@ class GlobalHelperThreadState {
|
||||||
// GC tasks needing to be done in parallel.
|
// GC tasks needing to be done in parallel.
|
||||||
GCParallelTaskVector gcParallelWorklist_;
|
GCParallelTaskVector gcParallelWorklist_;
|
||||||
|
|
||||||
// Global list of JSContext for GlobalHelperThreadState to use.
|
|
||||||
ContextVector helperContexts_;
|
|
||||||
|
|
||||||
ParseTask* removeFinishedParseTask(ParseTaskKind kind,
|
ParseTask* removeFinishedParseTask(ParseTaskKind kind,
|
||||||
JS::OffThreadToken* token);
|
JS::OffThreadToken* token);
|
||||||
|
|
||||||
|
@ -171,10 +167,8 @@ class GlobalHelperThreadState {
|
||||||
void finish();
|
void finish();
|
||||||
void finishThreads();
|
void finishThreads();
|
||||||
|
|
||||||
MOZ_MUST_USE bool initializeHelperContexts();
|
void lock();
|
||||||
JSContext* getFirstUnusedContext(AutoLockHelperThreadState& locked);
|
void unlock();
|
||||||
void destroyHelperContexts(AutoLockHelperThreadState& lock);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool isLockedByCurrentThread() const;
|
bool isLockedByCurrentThread() const;
|
||||||
#endif
|
#endif
|
||||||
|
@ -383,6 +377,12 @@ struct HelperThread {
|
||||||
*/
|
*/
|
||||||
bool terminate;
|
bool terminate;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Indicates that this thread should free its unused memory when it is next
|
||||||
|
* idle.
|
||||||
|
*/
|
||||||
|
bool shouldFreeUnusedMemory;
|
||||||
|
|
||||||
/* The current task being executed by this thread, if any. */
|
/* The current task being executed by this thread, if any. */
|
||||||
mozilla::Maybe<HelperTaskUnion> currentTask;
|
mozilla::Maybe<HelperTaskUnion> currentTask;
|
||||||
|
|
||||||
|
@ -465,6 +465,8 @@ struct HelperThread {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void maybeFreeUnusedMemory(JSContext* cx);
|
||||||
|
|
||||||
void handleWasmWorkload(AutoLockHelperThreadState& locked,
|
void handleWasmWorkload(AutoLockHelperThreadState& locked,
|
||||||
wasm::CompileMode mode);
|
wasm::CompileMode mode);
|
||||||
|
|
||||||
|
@ -701,21 +703,6 @@ class MOZ_RAII AutoUnlockHelperThreadState : public UnlockGuard<Mutex> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MOZ_RAII AutoSetHelperThreadContext {
|
|
||||||
JSContext* cx;
|
|
||||||
explicit AutoSetHelperThreadContext();
|
|
||||||
~AutoSetHelperThreadContext() {
|
|
||||||
AutoLockHelperThreadState lock;
|
|
||||||
cx->tempLifoAlloc().releaseAll();
|
|
||||||
if (cx->shouldFreeUnusedMemory()) {
|
|
||||||
cx->tempLifoAlloc().freeAll();
|
|
||||||
cx->setFreeUnusedMemory(false);
|
|
||||||
}
|
|
||||||
cx->clearHelperThread(lock);
|
|
||||||
cx = nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ParseTask : public mozilla::LinkedListElement<ParseTask>,
|
struct ParseTask : public mozilla::LinkedListElement<ParseTask>,
|
||||||
public JS::OffThreadToken,
|
public JS::OffThreadToken,
|
||||||
public RunnableTask {
|
public RunnableTask {
|
||||||
|
|
|
@ -105,8 +105,6 @@ js::AutoCycleDetector::~AutoCycleDetector() {
|
||||||
bool JSContext::init(ContextKind kind) {
|
bool JSContext::init(ContextKind kind) {
|
||||||
// Skip most of the initialization if this thread will not be running JS.
|
// Skip most of the initialization if this thread will not be running JS.
|
||||||
if (kind == ContextKind::MainThread) {
|
if (kind == ContextKind::MainThread) {
|
||||||
TlsContext.set(this);
|
|
||||||
currentThread_ = ThisThread::GetId();
|
|
||||||
if (!regexpStack.ref().init()) {
|
if (!regexpStack.ref().init()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -158,14 +156,14 @@ JSContext* js::NewContext(uint32_t maxBytes, uint32_t maxNurseryBytes,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cx->init(ContextKind::MainThread)) {
|
if (!runtime->init(cx, maxBytes, maxNurseryBytes)) {
|
||||||
runtime->destroyRuntime();
|
runtime->destroyRuntime();
|
||||||
js_delete(cx);
|
js_delete(cx);
|
||||||
js_delete(runtime);
|
js_delete(runtime);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!runtime->init(cx, maxBytes, maxNurseryBytes)) {
|
if (!cx->init(ContextKind::MainThread)) {
|
||||||
runtime->destroyRuntime();
|
runtime->destroyRuntime();
|
||||||
js_delete(cx);
|
js_delete(cx);
|
||||||
js_delete(runtime);
|
js_delete(runtime);
|
||||||
|
@ -1228,7 +1226,6 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
|
||||||
freeLists_(this, nullptr),
|
freeLists_(this, nullptr),
|
||||||
atomsZoneFreeLists_(this),
|
atomsZoneFreeLists_(this),
|
||||||
defaultFreeOp_(this, runtime, true),
|
defaultFreeOp_(this, runtime, true),
|
||||||
freeUnusedMemory(false),
|
|
||||||
jitActivation(this, nullptr),
|
jitActivation(this, nullptr),
|
||||||
regexpStack(this),
|
regexpStack(this),
|
||||||
activation_(this, nullptr),
|
activation_(this, nullptr),
|
||||||
|
@ -1308,6 +1305,9 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(static_cast<JS::RootingContext*>(this) ==
|
MOZ_ASSERT(static_cast<JS::RootingContext*>(this) ==
|
||||||
JS::RootingContext::get(this));
|
JS::RootingContext::get(this));
|
||||||
|
|
||||||
|
MOZ_ASSERT(!TlsContext.get());
|
||||||
|
TlsContext.set(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSContext::~JSContext() {
|
JSContext::~JSContext() {
|
||||||
|
@ -1337,17 +1337,7 @@ JSContext::~JSContext() {
|
||||||
|
|
||||||
js_delete(atomsZoneFreeLists_.ref());
|
js_delete(atomsZoneFreeLists_.ref());
|
||||||
|
|
||||||
TlsContext.set(nullptr);
|
MOZ_ASSERT(TlsContext.get() == this);
|
||||||
}
|
|
||||||
|
|
||||||
void JSContext::setHelperThread(AutoLockHelperThreadState& locked) {
|
|
||||||
MOZ_ASSERT_IF(!JSRuntime::hasLiveRuntimes(), !TlsContext.get());
|
|
||||||
TlsContext.set(this);
|
|
||||||
currentThread_ = ThisThread::GetId();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSContext::clearHelperThread(AutoLockHelperThreadState& locked) {
|
|
||||||
currentThread_ = Thread::Id();
|
|
||||||
TlsContext.set(nullptr);
|
TlsContext.set(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,34 +176,13 @@ struct JSContext : public JS::RootingContext,
|
||||||
|
|
||||||
js::ContextData<js::FreeOp> defaultFreeOp_;
|
js::ContextData<js::FreeOp> defaultFreeOp_;
|
||||||
|
|
||||||
// Thread that the JSContext is currently running on, if in use.
|
|
||||||
js::Thread::Id currentThread_;
|
|
||||||
|
|
||||||
js::ParseTask* parseTask_;
|
js::ParseTask* parseTask_;
|
||||||
|
|
||||||
// When a helper thread is using a context, it may need to periodically
|
|
||||||
// free unused memory.
|
|
||||||
mozilla::Atomic<bool, mozilla::ReleaseAcquire> freeUnusedMemory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// This is used by helper threads to change the runtime their context is
|
// This is used by helper threads to change the runtime their context is
|
||||||
// currently operating on.
|
// currently operating on.
|
||||||
void setRuntime(JSRuntime* rt);
|
void setRuntime(JSRuntime* rt);
|
||||||
|
|
||||||
void setHelperThread(js::AutoLockHelperThreadState& locked);
|
|
||||||
void clearHelperThread(js::AutoLockHelperThreadState& locked);
|
|
||||||
|
|
||||||
bool contextAvailable(js::AutoLockHelperThreadState& locked) {
|
|
||||||
MOZ_ASSERT(kind_ == js::ContextKind::HelperThread);
|
|
||||||
return currentThread_ == js::Thread::Id();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFreeUnusedMemory(bool shouldFree) { freeUnusedMemory = shouldFree; }
|
|
||||||
|
|
||||||
bool shouldFreeUnusedMemory() const {
|
|
||||||
return kind_ == js::ContextKind::HelperThread && freeUnusedMemory;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isMainThreadContext() const {
|
bool isMainThreadContext() const {
|
||||||
return kind_ == js::ContextKind::MainThread;
|
return kind_ == js::ContextKind::MainThread;
|
||||||
}
|
}
|
||||||
|
@ -491,7 +470,7 @@ struct JSContext : public JS::RootingContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base address of the native stack for the current thread. */
|
/* Base address of the native stack for the current thread. */
|
||||||
uintptr_t nativeStackBase;
|
const uintptr_t nativeStackBase;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* If non-null, report JavaScript entry points to this monitor. */
|
/* If non-null, report JavaScript entry points to this monitor. */
|
||||||
|
|
|
@ -62,7 +62,6 @@ class Module::Tier2GeneratorTaskImpl : public Tier2GeneratorTask {
|
||||||
void cancel() override { cancelled_ = true; }
|
void cancel() override { cancelled_ = true; }
|
||||||
|
|
||||||
void runTask() override {
|
void runTask() override {
|
||||||
AutoSetHelperThreadContext usesContext;
|
|
||||||
CompileTier2(*compileArgs_, bytecode_->bytes, *module_, &cancelled_);
|
CompileTier2(*compileArgs_, bytecode_->bytes, *module_, &cancelled_);
|
||||||
}
|
}
|
||||||
ThreadType threadType() override {
|
ThreadType threadType() override {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче