author | Bill McCloskey <billm@mozilla.com> |
Thu, 23 Jun 2016 17:03:03 -0700 | |
changeset 353971 | 277c54118c8ae0b1f9a61855df6e28d625e990ab |
parent 353970 | fd8d766932630c6e2c34a6e02eb8c428bb898b46 |
child 353972 | b1c893387fdd8785e61602f8098c16f2e50a731e |
push id | 1324 |
push user | mtabara@mozilla.com |
push date | Mon, 16 Jan 2017 13:07:44 +0000 |
treeherder | mozilla-release@a01c49833940 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dvander |
bugs | 1279086 |
milestone | 51.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/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -11116,24 +11116,24 @@ nsGlobalWindow::ShowSlowScriptDialog() (nsIPrompt::BUTTON_TITLE_IS_STRING * (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1)); // Add a third button if necessary. if (showDebugButton) buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2; // Null out the operation callback while we're re-entering JS here. - JSInterruptCallback old = JS_SetInterruptCallback(cx, nullptr); + bool old = JS_DisableInterruptCallback(cx); // Open the dialog. rv = prompt->ConfirmEx(title, msg, buttonFlags, waitButton, stopButton, debugButton, neverShowDlg, &neverShowDlgChk, &buttonPressed); - JS_SetInterruptCallback(cx, old); + JS_ResetInterruptCallback(cx, old); if (NS_SUCCEEDED(rv) && (buttonPressed == 0)) { return neverShowDlgChk ? AlwaysContinueSlowScript : ContinueSlowScript; } if (buttonPressed == 2) { if (debugCallback) { rv = debugCallback->HandleSlowScriptDebug(this); return NS_SUCCEEDED(rv) ? ContinueSlowScript : KillSlowScript;
--- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -901,17 +901,17 @@ InitJSContextForWorker(WorkerPrivate* aW JS::SetAsyncTaskCallbacks(aWorkerCx, StartAsyncTaskCallback, FinishAsyncTaskCallback); if (!JS::InitSelfHostedCode(aWorkerCx)) { NS_WARNING("Could not init self-hosted code!"); return false; } - JS_SetInterruptCallback(aWorkerCx, InterruptCallback); + JS_AddInterruptCallback(aWorkerCx, InterruptCallback); js::SetCTypesActivityCallback(aWorkerCx, CTypesActivityCallback); #ifdef JS_GC_ZEAL JS_SetGCZeal(aWorkerCx, settings.gcZeal, settings.gcZealFrequency); #endif return true;
--- a/js/src/jsapi-tests/testSlowScript.cpp +++ b/js/src/jsapi-tests/testSlowScript.cpp @@ -19,17 +19,17 @@ RequestInterruptCallback(JSContext* cx, if (!sRemain--) JS_RequestInterruptCallback(cx); args.rval().setUndefined(); return true; } BEGIN_TEST(testSlowScript) { - JS_SetInterruptCallback(cx, InterruptCallback); + JS_AddInterruptCallback(cx, InterruptCallback); JS_DefineFunction(cx, global, "requestInterruptCallback", RequestInterruptCallback, 0, 0); test("while (true)" " for (i in [0,0,0,0])" " requestInterruptCallback();"); test("while (true)" " for (i in [0,0,0,0])"
--- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4636,28 +4636,34 @@ JS_New(JSContext* cx, HandleObject ctor, } JS_PUBLIC_API(bool) JS_CheckForInterrupt(JSContext* cx) { return js::CheckForInterrupt(cx); } -JS_PUBLIC_API(JSInterruptCallback) -JS_SetInterruptCallback(JSContext* cx, JSInterruptCallback callback) -{ - JSInterruptCallback old = cx->interruptCallback; - cx->interruptCallback = callback; - return old; -} - -JS_PUBLIC_API(JSInterruptCallback) -JS_GetInterruptCallback(JSContext* cx) -{ - return cx->interruptCallback; +JS_PUBLIC_API(bool) +JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback) +{ + return cx->interruptCallbacks.append(callback); +} + +JS_PUBLIC_API(bool) +JS_DisableInterruptCallback(JSContext* cx) +{ + bool result = cx->interruptCallbackDisabled; + cx->interruptCallbackDisabled = true; + return result; +} + +JS_PUBLIC_API(void) +JS_ResetInterruptCallback(JSContext* cx, bool enable) +{ + cx->interruptCallbackDisabled = enable; } /************************************************************************/ /* * Promises. */ JS_PUBLIC_API(void)
--- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -4315,21 +4315,24 @@ JS_CheckForInterrupt(JSContext* cx); * To schedule the GC and for other activities the engine internally triggers * interrupt callbacks. The embedding should thus not rely on callbacks being * triggered through the external API only. * * Important note: Additional callbacks can occur inside the callback handler * if it re-enters the JS engine. The embedding must ensure that the callback * is disconnected before attempting such re-entry. */ -extern JS_PUBLIC_API(JSInterruptCallback) -JS_SetInterruptCallback(JSContext* cx, JSInterruptCallback callback); - -extern JS_PUBLIC_API(JSInterruptCallback) -JS_GetInterruptCallback(JSContext* cx); +extern JS_PUBLIC_API(bool) +JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback); + +extern JS_PUBLIC_API(bool) +JS_DisableInterruptCallback(JSContext* cx); + +extern JS_PUBLIC_API(void) +JS_ResetInterruptCallback(JSContext* cx, bool enable); extern JS_PUBLIC_API(void) JS_RequestInterruptCallback(JSContext* cx); namespace JS { /** * Sets the callback that's invoked whenever an incumbent global is required.
--- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -7558,17 +7558,17 @@ main(int argc, char** argv, char** envp) size_t availMem = op.getIntOption("available-memory"); if (availMem > 0) JS_SetGCParametersBasedOnAvailableMemory(cx, availMem); JS_SetTrustedPrincipals(cx, &ShellPrincipals::fullyTrusted); JS_SetSecurityCallbacks(cx, &ShellPrincipals::securityCallbacks); JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy); - JS_SetInterruptCallback(cx, ShellInterruptCallback); + JS_AddInterruptCallback(cx, ShellInterruptCallback); JS::SetBuildIdOp(cx, ShellBuildId); JS::SetAsmJSCacheOps(cx, &asmJSCacheOps); JS_SetNativeStackQuota(cx, gMaxStackSize); JS::dbg::SetDebuggerMallocSizeOf(cx, moz_malloc_size_of); if (!JS::InitSelfHostedCode(cx))
--- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -145,17 +145,17 @@ JSRuntime::JSRuntime(JSRuntime* parentRu parentRuntime(parentRuntime), #ifdef DEBUG updateChildRuntimeCount(parentRuntime), #endif interrupt_(false), telemetryCallback(nullptr), handlingSegFault(false), handlingJitInterrupt_(false), - interruptCallback(nullptr), + interruptCallbackDisabled(false), getIncumbentGlobalCallback(nullptr), enqueuePromiseJobCallback(nullptr), enqueuePromiseJobCallbackData(nullptr), promiseRejectionTrackerCallback(nullptr), promiseRejectionTrackerCallbackData(nullptr), startAsyncTaskCallback(nullptr), finishAsyncTaskCallback(nullptr), #ifdef DEBUG @@ -521,21 +521,26 @@ InvokeInterruptCallback(JSContext* cx) // A worker thread may have requested an interrupt after finishing an Ion // compilation. jit::AttachFinishedCompilations(cx); // Important: Additional callbacks can occur inside the callback handler // if it re-enters the JS engine. The embedding must ensure that the // callback is disconnected before attempting such re-entry. - JSInterruptCallback cb = cx->runtime()->interruptCallback; - if (!cb) + if (cx->runtime()->interruptCallbackDisabled) return true; - if (cb(cx)) { + bool stop = false; + for (JSInterruptCallback cb : cx->runtime()->interruptCallbacks) { + if (!cb(cx)) + stop = true; + } + + if (!stop) { // Debugger treats invoking the interrupt callback as a "step", so // invoke the onStep handler. if (cx->compartment()->isDebuggee()) { ScriptFrameIter iter(cx); if (!iter.done() && cx->compartment() == iter.compartment() && iter.script()->stepModeEnabled()) {
--- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -628,17 +628,19 @@ struct JSRuntime : public JS::shadow::Ru void finishHandlingJitInterrupt() { MOZ_ASSERT(handlingJitInterrupt_); handlingJitInterrupt_ = false; } bool handlingJitInterrupt() const { return handlingJitInterrupt_; } - JSInterruptCallback interruptCallback; + using InterruptCallbackVector = js::Vector<JSInterruptCallback, 2, js::SystemAllocPolicy>; + InterruptCallbackVector interruptCallbacks; + bool interruptCallbackDisabled; JSGetIncumbentGlobalCallback getIncumbentGlobalCallback; JSEnqueuePromiseJobCallback enqueuePromiseJobCallback; void* enqueuePromiseJobCallbackData; JSPromiseRejectionTrackerCallback promiseRejectionTrackerCallback; void* promiseRejectionTrackerCallbackData;
--- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -3524,17 +3524,17 @@ XPCJSRuntime::Initialize() JS_SetWrapObjectCallbacks(cx, &WrapObjectCallbacks); js::SetPreserveWrapperCallback(cx, PreserveWrapper); #ifdef MOZ_ENABLE_PROFILER_SPS if (PseudoStack* stack = mozilla_get_pseudo_stack()) stack->sampleContext(cx); #endif JS_SetAccumulateTelemetryCallback(cx, AccumulateTelemetryCallback); js::SetActivityCallback(cx, ActivityCallback, this); - JS_SetInterruptCallback(cx, InterruptCallback); + JS_AddInterruptCallback(cx, InterruptCallback); js::SetWindowProxyClass(cx, &OuterWindowProxyClass); #ifdef MOZ_CRASHREPORTER js::AutoEnterOOMUnsafeRegion::setAnnotateOOMAllocationSizeCallback( CrashReporter::AnnotateOOMAllocationSize); #endif // The JS engine needs to keep the source code around in order to implement // Function.prototype.toSource(). It'd be nice to not have to do this for
--- a/js/xpconnect/src/XPCShellImpl.cpp +++ b/js/xpconnect/src/XPCShellImpl.cpp @@ -1416,17 +1416,17 @@ XRE_XPCShellMain(int argc, char** argv, cx = jsapi.cx(); // Override the default XPConnect interrupt callback. We could store the // old one and restore it before shutting down, but there's not really a // reason to bother. sScriptedInterruptCallback = new PersistentRootedValue; sScriptedInterruptCallback->init(cx, UndefinedValue()); - JS_SetInterruptCallback(cx, XPCShellInterruptCallback); + JS_AddInterruptCallback(cx, XPCShellInterruptCallback); argc--; argv++; ProcessArgsForCompartment(cx, argv, argc); nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (!xpc) { printf("failed to get nsXPConnect service!\n");