author | Jan de Mooij <jdemooij@mozilla.com> |
Mon, 18 Jul 2016 14:36:43 +0200 | |
changeset 305325 | d8fb8e2d81a0bcd9d75703916c8e0593dac12d3c |
parent 305324 | 2fb342547aa8c02298f38714058411a651ea4b90 |
child 305326 | 895a11230f50a35a7dc626f6cdca22018f772547 |
push id | 79553 |
push user | jandemooij@gmail.com |
push date | Mon, 18 Jul 2016 12:40:11 +0000 |
treeherder | mozilla-inbound@d8fb8e2d81a0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | efaust |
bugs | 1285134 |
milestone | 50.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/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -146,20 +146,20 @@ static const TimeDuration MAX_TIMEOUT_IN #else # define SHARED_MEMORY_DEFAULT 0 #endif #ifdef SPIDERMONKEY_PROMISE using JobQueue = GCVector<JSObject*, 0, SystemAllocPolicy>; #endif // SPIDERMONKEY_PROMISE -// Per-runtime shell state. -struct ShellRuntime -{ - explicit ShellRuntime(JSRuntime* rt); +// Per-context shell state. +struct ShellContext +{ + explicit ShellContext(JSContext* cx); bool isWorker; double timeoutInterval; double startTime; Atomic<bool> serviceInterrupt; Atomic<bool> haveInterruptFunc; JS::PersistentRootedValue interruptFunc; bool lastWarningEnabled; @@ -234,23 +234,23 @@ static bool OOM_printAllocationCount = f // Shell state this is only accessed on the main thread. bool jsCachingEnabled = false; mozilla::Atomic<bool> jsCacheOpened(false); static bool SetTimeoutValue(JSContext* cx, double t); static void -KillWatchdog(JSRuntime *rt); - -static bool -ScheduleWatchdog(JSRuntime* rt, double t); +KillWatchdog(JSContext* cx); + +static bool +ScheduleWatchdog(JSContext* cx, double t); static void -CancelExecution(JSRuntime* rt); +CancelExecution(JSContext* cx); static JSObject* NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options, JSPrincipals* principals); /* * A toy principals type for the shell. * @@ -312,41 +312,40 @@ ShellPrincipals ShellPrincipals::fullyTr #ifdef EDITLINE extern "C" { extern JS_EXPORT_API(char*) readline(const char* prompt); extern JS_EXPORT_API(void) add_history(char* line); } // extern "C" #endif -ShellRuntime::ShellRuntime(JSRuntime* rt) +ShellContext::ShellContext(JSContext* cx) : isWorker(false), timeoutInterval(-1.0), startTime(PRMJ_Now()), serviceInterrupt(false), haveInterruptFunc(false), - interruptFunc(rt, NullValue()), + interruptFunc(cx, NullValue()), lastWarningEnabled(false), - lastWarning(rt, NullValue()), + lastWarning(cx, NullValue()), #ifdef SPIDERMONKEY_PROMISE - promiseRejectionTrackerCallback(rt, NullValue()), + promiseRejectionTrackerCallback(cx, NullValue()), #endif // SPIDERMONKEY_PROMISE exitCode(0), quitting(false), readLineBufPos(0), spsProfilingStackSize(0) {} -static ShellRuntime* -GetShellRuntime(JSRuntime *rt) -{ - JSContext* cx = JS_GetContext(rt); - ShellRuntime* sr = static_cast<ShellRuntime*>(JS_GetContextPrivate(cx)); - MOZ_ASSERT(sr); - return sr; +static ShellContext* +GetShellContext(JSContext* cx) +{ + ShellContext* sc = static_cast<ShellContext*>(JS_GetContextPrivate(cx)); + MOZ_ASSERT(sc); + return sc; } static char* GetLine(FILE* file, const char * prompt) { #ifdef EDITLINE /* * Use readline only if file is stdin, because there's no way to specify @@ -412,59 +411,59 @@ GetLine(FILE* file, const char * prompt) current = buffer + len; } while (true); return nullptr; } static bool ShellInterruptCallback(JSContext* cx) { - ShellRuntime* sr = GetShellRuntime(cx); - if (!sr->serviceInterrupt) + ShellContext* sc = GetShellContext(cx); + if (!sc->serviceInterrupt) return true; // Reset serviceInterrupt. CancelExecution or InterruptIf will set it to // true to distinguish watchdog or user triggered interrupts. // Do this first to prevent other interrupts that may occur while the // user-supplied callback is executing from re-entering the handler. - sr->serviceInterrupt = false; + sc->serviceInterrupt = false; bool result; - if (sr->haveInterruptFunc) { + if (sc->haveInterruptFunc) { bool wasAlreadyThrowing = cx->isExceptionPending(); JS::AutoSaveExceptionState savedExc(cx); - JSAutoCompartment ac(cx, &sr->interruptFunc.toObject()); + JSAutoCompartment ac(cx, &sc->interruptFunc.toObject()); RootedValue rval(cx); // Report any exceptions thrown by the JS interrupt callback, but do // *not* keep it on the cx. The interrupt handler is invoked at points // that are not expected to throw catchable exceptions, like at // JSOP_RETRVAL. // // If the interrupted JS code was already throwing, any exceptions // thrown by the interrupt handler are silently swallowed. { Maybe<AutoReportException> are; if (!wasAlreadyThrowing) are.emplace(cx); - result = JS_CallFunctionValue(cx, nullptr, sr->interruptFunc, + result = JS_CallFunctionValue(cx, nullptr, sc->interruptFunc, JS::HandleValueArray::empty(), &rval); } savedExc.restore(); if (rval.isBoolean()) result = rval.toBoolean(); else result = false; } else { result = false; } - if (!result && sr->exitCode == 0) - sr->exitCode = EXITCODE_TIMEOUT; + if (!result && sc->exitCode == 0) + sc->exitCode = EXITCODE_TIMEOUT; return result; } /* * Some UTF-8 files, notably those written using Notepad, have a Unicode * Byte-Order-Mark (BOM) as their first character. This is useless (byte-order * is meaningless for UTF-8) but causes a syntax error unless we skip it. @@ -634,45 +633,45 @@ ShellGetIncumbentGlobalCallback(JSContex { return JS::CurrentGlobalOrNull(cx); } static bool ShellEnqueuePromiseJobCallback(JSContext* cx, JS::HandleObject job, JS::HandleObject allocationSite, JS::HandleObject incumbentGlobal, void* data) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); MOZ_ASSERT(job); - return sr->jobQueue.append(job); + return sc->jobQueue.append(job); } #endif // SPIDERMONKEY_PROMISE static bool DrainJobQueue(JSContext* cx) { #ifdef SPIDERMONKEY_PROMISE - ShellRuntime* sr = GetShellRuntime(cx); - if (sr->quitting) + ShellContext* sc = GetShellContext(cx); + if (sc->quitting) return true; RootedObject job(cx); JS::HandleValueArray args(JS::HandleValueArray::empty()); RootedValue rval(cx); // Execute jobs in a loop until we've reached the end of the queue. // Since executing a job can trigger enqueuing of additional jobs, // it's crucial to re-check the queue length during each iteration. - for (size_t i = 0; i < sr->jobQueue.length(); i++) { - job = sr->jobQueue[i]; + for (size_t i = 0; i < sc->jobQueue.length(); i++) { + job = sc->jobQueue[i]; AutoCompartment ac(cx, job); { AutoReportException are(cx); JS::Call(cx, UndefinedHandleValue, job, args, &rval); } - sr->jobQueue[i].set(nullptr); - } - sr->jobQueue.clear(); + sc->jobQueue[i].set(nullptr); + } + sc->jobQueue.clear(); #endif // SPIDERMONKEY_PROMISE return true; } static bool DrainJobQueue(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -683,17 +682,17 @@ DrainJobQueue(JSContext* cx, unsigned ar return true; } #ifdef SPIDERMONKEY_PROMISE static void ForwardingPromiseRejectionTrackerCallback(JSContext* cx, JS::HandleObject promise, PromiseRejectionHandlingState state, void* data) { - RootedValue callback(cx, GetShellRuntime(cx)->promiseRejectionTrackerCallback); + RootedValue callback(cx, GetShellContext(cx)->promiseRejectionTrackerCallback); if (callback.isNull()) { return; } FixedInvokeArgs<2> args(cx); args[0].setObject(*promise); args[1].setInt32(static_cast<int32_t>(state)); @@ -711,17 +710,17 @@ SetPromiseRejectionTrackerCallback(JSCon #ifdef SPIDERMONKEY_PROMISE if (!IsCallable(args.get(0))) { JS_ReportError(cx, "setPromiseRejectionTrackerCallback expects a function as its sole " "argument"); return false; } - GetShellRuntime(cx)->promiseRejectionTrackerCallback = args[0]; + GetShellContext(cx)->promiseRejectionTrackerCallback = args[0]; JS::SetPromiseRejectionTrackerCallback(cx, ForwardingPromiseRejectionTrackerCallback); #endif // SPIDERMONKEY_PROMISE args.rval().setUndefined(); return true; } static bool @@ -757,51 +756,51 @@ EvalAndPrint(JSContext* cx, const char* JS_free(cx, utf8chars); } return true; } static MOZ_MUST_USE bool ReadEvalPrintLoop(JSContext* cx, FILE* in, bool compileOnly) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); int lineno = 1; bool hitEOF = false; do { /* * Accumulate lines until we get a 'compilable unit' - one that either * generates an error (before running out of source) or that compiles * cleanly. This should be whenever we get a complete statement that * coincides with the end of a line. */ int startline = lineno; typedef Vector<char, 32> CharBuffer; RootedObject globalLexical(cx, &cx->global()->lexicalScope()); CharBuffer buffer(cx); do { - ScheduleWatchdog(cx->runtime(), -1); - sr->serviceInterrupt = false; + ScheduleWatchdog(cx, -1); + sc->serviceInterrupt = false; errno = 0; char* line = GetLine(in, startline == lineno ? "js> " : ""); if (!line) { if (errno) { JS_ReportError(cx, strerror(errno)); return false; } hitEOF = true; break; } if (!buffer.append(line, strlen(line)) || !buffer.append('\n')) return false; lineno++; - if (!ScheduleWatchdog(cx->runtime(), sr->timeoutInterval)) { + if (!ScheduleWatchdog(cx, sc->timeoutInterval)) { hitEOF = true; break; } } while (!JS_BufferIsCompilableUnit(cx, cx->global(), buffer.begin(), buffer.length())); if (hitEOF && buffer.empty()) break; @@ -820,17 +819,17 @@ ReadEvalPrintLoop(JSContext* cx, FILE* i "Warning: the global bindings should be permanently uninitialized.\n" "Warning: We have non-standard-ly initialized them to `undefined`" "for you.\nWarning: This nicety only happens in the JS shell.\n", stderr); } DrainJobQueue(cx); - } while (!hitEOF && !sr->quitting); + } while (!hitEOF && !sc->quitting); if (gOutFile->isOpen()) fprintf(gOutFile->fp, "\n"); return true; } enum FileKind @@ -1713,25 +1712,25 @@ ReadLine(JSContext* cx, unsigned argc, V /* * function readlineBuf() * Provides a hook for scripts to emulate readline() using a string object. */ static bool ReadLineBuf(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); if (!args.length()) { - if (!sr->readLineBuf) { + if (!sc->readLineBuf) { JS_ReportError(cx, "No source buffer set. You must initially call readlineBuf with an argument."); return false; } - char* currentBuf = sr->readLineBuf.get() + sr->readLineBufPos; + char* currentBuf = sc->readLineBuf.get() + sc->readLineBufPos; size_t buflen = strlen(currentBuf); if (!buflen) { args.rval().setNull(); return true; } size_t len = 0; @@ -1741,36 +1740,36 @@ ReadLineBuf(JSContext* cx, unsigned argc len++; } JSString* str = JS_NewStringCopyN(cx, currentBuf, len); if (!str) return false; if (currentBuf[len] == '\0') - sr->readLineBufPos += len; + sc->readLineBufPos += len; else - sr->readLineBufPos += len + 1; + sc->readLineBufPos += len + 1; args.rval().setString(str); return true; } if (args.length() == 1) { - if (sr->readLineBuf) - sr->readLineBuf.reset(); + if (sc->readLineBuf) + sc->readLineBuf.reset(); RootedString str(cx, JS::ToString(cx, args[0])); if (!str) return false; - sr->readLineBuf = UniqueChars(JS_EncodeStringToUTF8(cx, str)); - if (!sr->readLineBuf) + sc->readLineBuf = UniqueChars(JS_EncodeStringToUTF8(cx, str)); + if (!sc->readLineBuf) return false; - sr->readLineBufPos = 0; + sc->readLineBufPos = 0; return true; } JS_ReportError(cx, "Must specify at most one argument"); return false; } static bool @@ -1849,17 +1848,17 @@ PrintErr(JSContext* cx, unsigned argc, V } static bool Help(JSContext* cx, unsigned argc, Value* vp); static bool Quit(JSContext* cx, unsigned argc, Value* vp) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); #ifdef JS_MORE_DETERMINISTIC // Print a message to stderr in more-deterministic builds to help jsfunfuzz // find uncatchable-exception bugs. fprintf(stderr, "quit called\n"); #endif CallArgs args = CallArgsFromVp(argc, vp); @@ -1872,18 +1871,18 @@ Quit(JSContext* cx, unsigned argc, Value // POSIX platforms, the exit code is 8-bit and negative values can also // result in an exit code >= 128. We restrict the value to range [0, 127] to // avoid false positives. if (code < 0 || code >= 128) { JS_ReportError(cx, "quit exit code should be in range 0-127"); return false; } - sr->exitCode = code; - sr->quitting = true; + sc->exitCode = code; + sc->quitting = true; return false; } static bool StartTimingMutator(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() > 0) { @@ -2943,41 +2942,41 @@ WorkerMain(void* arg) WorkerInput* input = (WorkerInput*) arg; JSRuntime* rt = JS_NewRuntime(8L * 1024L * 1024L, 2L * 1024L * 1024L, input->runtime); if (!rt) { js_delete(input); return; } - UniquePtr<ShellRuntime> sr = MakeUnique<ShellRuntime>(rt); - if (!sr) { + JSContext* cx = JS_GetContext(rt); + + UniquePtr<ShellContext> sc = MakeUnique<ShellContext>(cx); + if (!sc) { JS_DestroyRuntime(rt); js_delete(input); return; } - JSContext* cx = JS_GetContext(rt); - - sr->isWorker = true; - JS_SetContextPrivate(cx, sr.get()); + sc->isWorker = true; + JS_SetContextPrivate(cx, sc.get()); JS_SetFutexCanWait(cx); JS::SetWarningReporter(cx, WarningReporter); js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback); JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy); SetWorkerContextOptions(cx); if (!JS::InitSelfHostedCode(cx)) { JS_DestroyRuntime(rt); js_delete(input); return; } #ifdef SPIDERMONKEY_PROMISE - sr->jobQueue.init(cx, JobQueue(SystemAllocPolicy())); + sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy())); JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback); JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback); #endif // SPIDERMONKEY_PROMISE EnvironmentPreparer environmentPreparer(cx); JS::SetLargeAllocationFailureCallback(cx, my_LargeAllocFailCallback, (void*)cx); @@ -3004,20 +3003,20 @@ WorkerMain(void* arg) JS_ExecuteScript(cx, script, &result); } while (0); JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr); #ifdef SPIDERMONKEY_PROMISE JS::SetGetIncumbentGlobalCallback(cx, nullptr); JS::SetEnqueuePromiseJobCallback(cx, nullptr); - sr->jobQueue.reset(); + sc->jobQueue.reset(); #endif // SPIDERMONKEY_PROMISE - KillWatchdog(rt); + KillWatchdog(cx); JS_DestroyRuntime(rt); js_delete(input); } // Workers can spawn other workers, so we need a lock to access workerThreads. static Mutex* workerThreadsLock = nullptr; @@ -3112,17 +3111,17 @@ ShapeOf(JSContext* cx, unsigned argc, JS JSObject* obj = &args[0].toObject(); args.rval().set(JS_NumberValue(double(uintptr_t(obj->maybeShape()) >> 3))); return true; } static bool Sleep_fn(JSContext* cx, unsigned argc, Value* vp) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); CallArgs args = CallArgsFromVp(argc, vp); TimeDuration duration = TimeDuration::FromSeconds(0.0); if (args.length() > 0) { double t_secs; if (!ToNumber(cx, args[0], &t_secs)) return false; if (mozilla::IsNaN(t_secs)) { @@ -3132,113 +3131,113 @@ Sleep_fn(JSContext* cx, unsigned argc, V duration = TimeDuration::FromSeconds(Max(0.0, t_secs)); if (duration > MAX_TIMEOUT_INTERVAL) { JS_ReportError(cx, "Excessive sleep interval"); return false; } } { - LockGuard<Mutex> guard(sr->watchdogLock); + LockGuard<Mutex> guard(sc->watchdogLock); TimeStamp toWakeup = TimeStamp::Now() + duration; for (;;) { - sr->sleepWakeup.wait_for(guard, duration); - if (sr->serviceInterrupt) + sc->sleepWakeup.wait_for(guard, duration); + if (sc->serviceInterrupt) break; auto now = TimeStamp::Now(); if (now >= toWakeup) break; duration = toWakeup - now; } } args.rval().setUndefined(); - return !sr->serviceInterrupt; + return !sc->serviceInterrupt; } static void -KillWatchdog(JSRuntime* rt) -{ - ShellRuntime* sr = GetShellRuntime(rt); +KillWatchdog(JSContext* cx) +{ + ShellContext* sc = GetShellContext(cx); Maybe<Thread> thread; { - LockGuard<Mutex> guard(sr->watchdogLock); - Swap(sr->watchdogThread, thread); + LockGuard<Mutex> guard(sc->watchdogLock); + Swap(sc->watchdogThread, thread); if (thread) { // The watchdog thread becoming Nothing is its signal to exit. - sr->watchdogWakeup.notify_one(); + sc->watchdogWakeup.notify_one(); } } if (thread) thread->join(); - MOZ_ASSERT(!sr->watchdogThread); + MOZ_ASSERT(!sc->watchdogThread); } static void -WatchdogMain(JSRuntime* rt) +WatchdogMain(JSContext* cx) { ThisThread::SetName("JS Watchdog"); - ShellRuntime* sr = GetShellRuntime(rt); - - LockGuard<Mutex> guard(sr->watchdogLock); - while (sr->watchdogThread) { + ShellContext* sc = GetShellContext(cx); + + LockGuard<Mutex> guard(sc->watchdogLock); + while (sc->watchdogThread) { auto now = TimeStamp::Now(); - if (sr->watchdogTimeout && now >= sr->watchdogTimeout.value()) { + if (sc->watchdogTimeout && now >= sc->watchdogTimeout.value()) { /* * The timeout has just expired. Request an interrupt callback * outside the lock. */ - sr->watchdogTimeout = Nothing(); + sc->watchdogTimeout = Nothing(); { UnlockGuard<Mutex> unlock(guard); - CancelExecution(rt); + CancelExecution(cx); } /* Wake up any threads doing sleep. */ - sr->sleepWakeup.notify_all(); + sc->sleepWakeup.notify_all(); } else { - if (sr->watchdogTimeout) { + if (sc->watchdogTimeout) { /* * Time hasn't expired yet. Simulate an interrupt callback * which doesn't abort execution. */ - JS_RequestInterruptCallback(rt); + JS_RequestInterruptCallback(cx->runtime()); } - TimeDuration sleepDuration = sr->watchdogTimeout + TimeDuration sleepDuration = sc->watchdogTimeout ? TimeDuration::FromSeconds(0.1) : TimeDuration::Forever(); - sr->watchdogWakeup.wait_for(guard, sleepDuration); + sc->watchdogWakeup.wait_for(guard, sleepDuration); } } } static bool -ScheduleWatchdog(JSRuntime* rt, double t) -{ - ShellRuntime* sr = GetShellRuntime(rt); +ScheduleWatchdog(JSContext* cx, double t) +{ + ShellContext* sc = GetShellContext(cx); if (t <= 0) { - LockGuard<Mutex> guard(sr->watchdogLock); - sr->watchdogTimeout = Nothing(); + LockGuard<Mutex> guard(sc->watchdogLock); + sc->watchdogTimeout = Nothing(); return true; } auto interval = TimeDuration::FromSeconds(t); auto timeout = TimeStamp::Now() + interval; - LockGuard<Mutex> guard(sr->watchdogLock); - if (!sr->watchdogThread) { - MOZ_ASSERT(!sr->watchdogTimeout); - sr->watchdogThread.emplace(WatchdogMain, rt); - } else if (!sr->watchdogTimeout || timeout < sr->watchdogTimeout.value()) { - sr->watchdogWakeup.notify_one(); - } - sr->watchdogTimeout = Some(timeout); + LockGuard<Mutex> guard(sc->watchdogLock); + if (!sc->watchdogThread) { + MOZ_ASSERT(!sc->watchdogTimeout); + sc->watchdogThread.emplace(WatchdogMain, cx); + } else if (!sc->watchdogTimeout || timeout < sc->watchdogTimeout.value()) { + sc->watchdogWakeup.notify_one(); + } + sc->watchdogTimeout = Some(timeout); return true; } static void KillWorkerThreads() { MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty()); @@ -3261,55 +3260,55 @@ KillWorkerThreads() PR_JoinThread(thread); } js_delete(workerThreadsLock); workerThreadsLock = nullptr; } static void -CancelExecution(JSRuntime* rt) -{ - ShellRuntime* sr = GetShellRuntime(rt); - sr->serviceInterrupt = true; - JS_RequestInterruptCallback(rt); - - if (sr->haveInterruptFunc) { +CancelExecution(JSContext* cx) +{ + ShellContext* sc = GetShellContext(cx); + sc->serviceInterrupt = true; + JS_RequestInterruptCallback(cx->runtime()); + + if (sc->haveInterruptFunc) { static const char msg[] = "Script runs for too long, terminating.\n"; fputs(msg, stderr); } } static bool SetTimeoutValue(JSContext* cx, double t) { if (mozilla::IsNaN(t)) { JS_ReportError(cx, "timeout is not a number"); return false; } if (TimeDuration::FromSeconds(t) > MAX_TIMEOUT_INTERVAL) { JS_ReportError(cx, "Excessive timeout value"); return false; } - GetShellRuntime(cx)->timeoutInterval = t; - if (!ScheduleWatchdog(cx->runtime(), t)) { + GetShellContext(cx)->timeoutInterval = t; + if (!ScheduleWatchdog(cx, t)) { JS_ReportError(cx, "Failed to create the watchdog"); return false; } return true; } static bool Timeout(JSContext* cx, unsigned argc, Value* vp) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { - args.rval().setNumber(sr->timeoutInterval); + args.rval().setNumber(sc->timeoutInterval); return true; } if (args.length() > 2) { JS_ReportError(cx, "Wrong number of arguments"); return false; } @@ -3318,18 +3317,18 @@ Timeout(JSContext* cx, unsigned argc, Va return false; if (args.length() > 1) { RootedValue value(cx, args[1]); if (!value.isObject() || !value.toObject().is<JSFunction>()) { JS_ReportError(cx, "Second argument must be a timeout function"); return false; } - sr->interruptFunc = value; - sr->haveInterruptFunc = true; + sc->interruptFunc = value; + sc->haveInterruptFunc = true; } args.rval().setUndefined(); return SetTimeoutValue(cx, t); } static bool InterruptIf(JSContext* cx, unsigned argc, Value* vp) @@ -3337,34 +3336,34 @@ InterruptIf(JSContext* cx, unsigned argc CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { JS_ReportError(cx, "Wrong number of arguments"); return false; } if (ToBoolean(args[0])) { - GetShellRuntime(cx)->serviceInterrupt = true; + GetShellContext(cx)->serviceInterrupt = true; JS_RequestInterruptCallback(cx->runtime()); } args.rval().setUndefined(); return true; } static bool InvokeInterruptCallbackWrapper(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { JS_ReportError(cx, "Wrong number of arguments"); return false; } - GetShellRuntime(cx)->serviceInterrupt = true; + GetShellContext(cx)->serviceInterrupt = true; JS_RequestInterruptCallback(cx->runtime()); bool interruptRv = CheckForInterrupt(cx); // The interrupt handler could have set a pending exception. Since we call // back into JS, don't have it see the pending exception. If we have an // uncatchable exception that's not propagating a debug mode forced // return, return. if (!interruptRv && !cx->isExceptionPending() && !cx->isPropagatingForcedReturn()) @@ -3394,79 +3393,79 @@ SetInterruptCallback(JSContext* cx, unsi return false; } RootedValue value(cx, args[0]); if (!value.isObject() || !value.toObject().is<JSFunction>()) { JS_ReportError(cx, "Argument must be a function"); return false; } - GetShellRuntime(cx)->interruptFunc = value; - GetShellRuntime(cx)->haveInterruptFunc = true; + GetShellContext(cx)->interruptFunc = value; + GetShellContext(cx)->haveInterruptFunc = true; args.rval().setUndefined(); return true; } static bool EnableLastWarning(JSContext* cx, unsigned argc, Value* vp) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); CallArgs args = CallArgsFromVp(argc, vp); - sr->lastWarningEnabled = true; - sr->lastWarning.setNull(); + sc->lastWarningEnabled = true; + sc->lastWarning.setNull(); args.rval().setUndefined(); return true; } static bool DisableLastWarning(JSContext* cx, unsigned argc, Value* vp) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); CallArgs args = CallArgsFromVp(argc, vp); - sr->lastWarningEnabled = false; - sr->lastWarning.setNull(); + sc->lastWarningEnabled = false; + sc->lastWarning.setNull(); args.rval().setUndefined(); return true; } static bool GetLastWarning(JSContext* cx, unsigned argc, Value* vp) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); CallArgs args = CallArgsFromVp(argc, vp); - if (!sr->lastWarningEnabled) { + if (!sc->lastWarningEnabled) { JS_ReportError(cx, "Call enableLastWarning first."); return false; } - if (!JS_WrapValue(cx, &sr->lastWarning)) - return false; - - args.rval().set(sr->lastWarning); + if (!JS_WrapValue(cx, &sc->lastWarning)) + return false; + + args.rval().set(sc->lastWarning); return true; } static bool ClearLastWarning(JSContext* cx, unsigned argc, Value* vp) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); CallArgs args = CallArgsFromVp(argc, vp); - if (!sr->lastWarningEnabled) { + if (!sc->lastWarningEnabled) { JS_ReportError(cx, "Call enableLastWarning first."); return false; } - sr->lastWarning.setNull(); + sc->lastWarning.setNull(); args.rval().setUndefined(); return true; } #ifdef DEBUG static bool StackDump(JSContext* cx, unsigned argc, Value* vp) @@ -3507,17 +3506,17 @@ StackPointerInfo(JSContext* cx, unsigned } static bool Elapsed(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { - double d = PRMJ_Now() - GetShellRuntime(cx)->startTime; + double d = PRMJ_Now() - GetShellContext(cx)->startTime; args.rval().setDouble(d); return true; } JS_ReportError(cx, "Wrong number of arguments"); return false; } static bool @@ -4491,17 +4490,17 @@ IsCachingEnabled(JSContext* cx, unsigned args.rval().setBoolean(jsCachingEnabled && jsCacheAsmJSPath != nullptr); return true; } static bool SetCachingEnabled(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - if (GetShellRuntime(cx)->isWorker) { + if (GetShellContext(cx)->isWorker) { JS_ReportError(cx, "Caching is not supported in workers"); return false; } jsCachingEnabled = ToBoolean(args.get(0)); args.rval().setUndefined(); return true; } @@ -4634,56 +4633,56 @@ IsLatin1(JSContext* cx, unsigned argc, V return true; } static bool EnableSPSProfiling(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); // Disable before re-enabling; see the assertion in |SPSProfiler::setProfilingStack|. if (cx->runtime()->spsProfiler.installed()) cx->runtime()->spsProfiler.enable(false); - SetRuntimeProfilingStack(cx->runtime(), sr->spsProfilingStack, &sr->spsProfilingStackSize, - ShellRuntime::SpsProfilingMaxStackSize); + SetRuntimeProfilingStack(cx->runtime(), sc->spsProfilingStack, &sc->spsProfilingStackSize, + ShellContext::SpsProfilingMaxStackSize); cx->runtime()->spsProfiler.enableSlowAssertions(false); cx->runtime()->spsProfiler.enable(true); args.rval().setUndefined(); return true; } static bool EnableSPSProfilingWithSlowAssertions(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setUndefined(); - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); if (cx->runtime()->spsProfiler.enabled()) { // If profiling already enabled with slow assertions disabled, // this is a no-op. if (cx->runtime()->spsProfiler.slowAssertionsEnabled()) return true; // Slow assertions are off. Disable profiling before re-enabling // with slow assertions on. cx->runtime()->spsProfiler.enable(false); } // Disable before re-enabling; see the assertion in |SPSProfiler::setProfilingStack|. if (cx->runtime()->spsProfiler.installed()) cx->runtime()->spsProfiler.enable(false); - SetRuntimeProfilingStack(cx->runtime(), sr->spsProfilingStack, &sr->spsProfilingStackSize, - ShellRuntime::SpsProfilingMaxStackSize); + SetRuntimeProfilingStack(cx->runtime(), sc->spsProfilingStack, &sc->spsProfilingStackSize, + ShellContext::SpsProfilingMaxStackSize); cx->runtime()->spsProfiler.enableSlowAssertions(true); cx->runtime()->spsProfiler.enable(true); return true; } static bool DisableSPSProfiling(JSContext* cx, unsigned argc, Value* vp) @@ -5978,17 +5977,17 @@ CreateLastWarningObject(JSContext* cx, J RootedValue linenoVal(cx, Int32Value(report->lineno)); if (!DefineProperty(cx, warningObj, cx->names().lineNumber, linenoVal)) return false; RootedValue columnVal(cx, Int32Value(report->column)); if (!DefineProperty(cx, warningObj, cx->names().columnNumber, columnVal)) return false; - GetShellRuntime(cx)->lastWarning.setObject(*warningObj); + GetShellContext(cx)->lastWarning.setObject(*warningObj); return true; } static FILE* ErrorFilePointer() { if (gErrFile->isOpen()) return gErrFile->fp; @@ -6040,17 +6039,17 @@ js::shell::AutoReportException::~AutoRep return; // Get exception object before printing and clearing exception. RootedValue exn(cx); (void) JS_GetPendingException(cx, &exn); JS_ClearPendingException(cx); - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); js::ErrorReport report(cx); if (!report.init(cx, exn, js::ErrorReport::WithSideEffects)) { fprintf(stderr, "out of memory initializing ErrorReport\n"); JS_ClearPendingException(cx); return; } MOZ_ASSERT(!JSREPORT_IS_WARNING(report.report()->flags)); @@ -6061,33 +6060,33 @@ js::shell::AutoReportException::~AutoRep { JS::AutoSaveExceptionState savedExc(cx); if (!PrintStackTrace(cx, exn)) fputs("(Unable to print stack trace)\n", fp); savedExc.restore(); } if (report.report()->errorNumber == JSMSG_OUT_OF_MEMORY) - sr->exitCode = EXITCODE_OUT_OF_MEMORY; + sc->exitCode = EXITCODE_OUT_OF_MEMORY; else - sr->exitCode = EXITCODE_RUNTIME_ERROR; + sc->exitCode = EXITCODE_RUNTIME_ERROR; JS_ClearPendingException(cx); } void js::shell::WarningReporter(JSContext* cx, const char* message, JSErrorReport* report) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); FILE* fp = ErrorFilePointer(); MOZ_ASSERT(report); MOZ_ASSERT(JSREPORT_IS_WARNING(report->flags)); - if (sr->lastWarningEnabled) { + if (sc->lastWarningEnabled) { JS::AutoSaveExceptionState savedExc(cx); if (!CreateLastWarningObject(cx, report)) { fputs("Unhandled error happened while creating last warning object.\n", fp); fflush(fp); } savedExc.restore(); } @@ -6728,17 +6727,17 @@ OptionFailure(const char* option, const { fprintf(stderr, "Unrecognized option for %s: %s\n", option, str); return false; } static MOZ_MUST_USE bool ProcessArgs(JSContext* cx, OptionParser* op) { - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); if (op->getBoolOption('s')) JS::ContextOptionsRef(cx).toggleExtraWarnings(); /* |scriptArgs| gets bound on the global before any code is run. */ if (!BindScriptArgs(cx, op)) return false; @@ -6773,28 +6772,28 @@ ProcessArgs(JSContext* cx, OptionParser* } else if (ccArgno < fpArgno && ccArgno < mpArgno) { const char* code = codeChunks.front(); RootedValue rval(cx); JS::CompileOptions opts(cx); opts.setFileAndLine("-e", 1); if (!JS::Evaluate(cx, opts, code, strlen(code), &rval)) return false; codeChunks.popFront(); - if (sr->quitting) + if (sc->quitting) break; } else { MOZ_ASSERT(mpArgno < fpArgno && mpArgno < ccArgno); char* path = modulePaths.front(); if (!Process(cx, path, false, FileModule)) return false; modulePaths.popFront(); } } - if (sr->quitting) + if (sc->quitting) return false; /* The |script| argument is processed after all options. */ if (const char* path = op->getStringArg("script")) { if (!Process(cx, path, false)) return false; } @@ -7134,26 +7133,26 @@ Shell(JSContext* cx, OptionParser* op, c JS::CompartmentOptions options; SetStandardCompartmentOptions(options); RootedObject glob(cx, NewGlobalObject(cx, options, nullptr)); if (!glob) return 1; JSAutoCompartment ac(cx, glob); - ShellRuntime* sr = GetShellRuntime(cx); + ShellContext* sc = GetShellContext(cx); int result = EXIT_SUCCESS; { AutoReportException are(cx); - if (!ProcessArgs(cx, op) && !sr->quitting) + if (!ProcessArgs(cx, op) && !sc->quitting) result = EXITCODE_RUNTIME_ERROR; } - if (sr->exitCode) - result = sr->exitCode; + if (sc->exitCode) + result = sc->exitCode; if (enableDisassemblyDumps) js::DumpCompartmentPCCounts(cx); if (!op->getBoolOption("no-js-cache-per-process")) { if (jsCacheAsmJSPath) { unlink(jsCacheAsmJSPath); JS_free(cx, const_cast<char*>(jsCacheAsmJSPath)); @@ -7453,23 +7452,23 @@ main(int argc, char** argv, char** envp) size_t nurseryBytes = JS::DefaultNurseryBytes; nurseryBytes = op.getIntOption("nursery-size") * 1024L * 1024L; /* Use the same parameters as the browser in xpcjsruntime.cpp. */ JSRuntime* rt = JS_NewRuntime(JS::DefaultHeapMaxBytes, nurseryBytes); if (!rt) return 1; - UniquePtr<ShellRuntime> sr = MakeUnique<ShellRuntime>(rt); - if (!sr) + JSContext* cx = JS_GetContext(rt); + + UniquePtr<ShellContext> sc = MakeUnique<ShellContext>(cx); + if (!sc) return 1; - JSContext* cx = JS_GetContext(rt); - - JS_SetContextPrivate(cx, sr.get()); + JS_SetContextPrivate(cx, sc.get()); // Waiting is allowed on the shell's main thread, for now. JS_SetFutexCanWait(cx); JS::SetWarningReporter(cx, WarningReporter); if (!SetContextOptions(cx, op)) return 1; JS_SetGCParameter(cx, JSGC_MAX_BYTES, 0xffffffff); @@ -7488,17 +7487,17 @@ main(int argc, char** argv, char** envp) JS_SetNativeStackQuota(cx, gMaxStackSize); JS::dbg::SetDebuggerMallocSizeOf(cx, moz_malloc_size_of); if (!JS::InitSelfHostedCode(cx)) return 1; #ifdef SPIDERMONKEY_PROMISE - sr->jobQueue.init(cx, JobQueue(SystemAllocPolicy())); + sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy())); JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback); JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback); #endif // SPIDERMONKEY_PROMISE EnvironmentPreparer environmentPreparer(cx); JS_SetGCParameter(cx, JSGC_MODE, JSGC_MODE_INCREMENTAL); @@ -7524,20 +7523,20 @@ main(int argc, char** argv, char** envp) printf("OOM max count: %" PRIu64 "\n", js::oom::counter); #endif JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr); #ifdef SPIDERMONKEY_PROMISE JS::SetGetIncumbentGlobalCallback(cx, nullptr); JS::SetEnqueuePromiseJobCallback(cx, nullptr); - sr->jobQueue.reset(); + sc->jobQueue.reset(); #endif // SPIDERMONKEY_PROMISE - KillWatchdog(rt); + KillWatchdog(cx); KillWorkerThreads(); DestructSharedArrayBufferMailbox(); JS_DestroyRuntime(rt); JS_ShutDown(); return result;