author | Bill McCloskey <wmccloskey@mozilla.com> |
Thu, 17 Jul 2014 21:09:45 -0700 | |
changeset 194782 | ed1736c6367a4228e4b62213248e4d020ada8874 |
parent 194781 | 274a3f27b49788fe6a2a3607cf8b118788e9a576 |
child 194783 | 2afafea0f09e098bef2e7fdc93e19024cbd80101 |
push id | 46435 |
push user | wmccloskey@mozilla.com |
push date | Fri, 18 Jul 2014 04:09:55 +0000 |
treeherder | mozilla-inbound@ed1736c6367a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bsmedberg, luke |
bugs | 950745 |
milestone | 33.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/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -20,16 +20,17 @@ #include "mozilla/dom/HashChangeEvent.h" #include "mozilla/dom/PageTransitionEvent.h" #include "mozilla/dom/PopStateEvent.h" #include "mozilla/dom/StorageEvent.h" #include "mozilla/dom/TouchEvent.h" #include "mozilla/EventDispatcher.h" #include "mozilla/EventListenerManager.h" #include "mozilla/InternalMutationEvent.h" +#include "mozilla/ipc/MessageChannel.h" #include "mozilla/MiscEvents.h" #include "mozilla/MouseEvents.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" #include "mozilla/unused.h" namespace mozilla { @@ -395,16 +396,20 @@ EventDispatcher::Dispatch(nsISupports* a PROFILER_LABEL("EventDispatcher", "Dispatch", js::ProfileEntry::Category::EVENTS); NS_ASSERTION(aEvent, "Trying to dispatch without WidgetEvent!"); NS_ENSURE_TRUE(!aEvent->mFlags.mIsBeingDispatched, NS_ERROR_DOM_INVALID_STATE_ERR); NS_ASSERTION(!aTargets || !aEvent->message, "Wrong parameters!"); +#ifdef NIGHTLY_BUILD + MOZ_RELEASE_ASSERT(!mozilla::ipc::ProcessingUrgentMessages()); +#endif + // If we're dispatching an already created DOMEvent object, make // sure it is initialized! // If aTargets is non-null, the event isn't going to be dispatched. NS_ENSURE_TRUE(aEvent->message || !aDOMEvent || aTargets, NS_ERROR_DOM_INVALID_STATE_ERR); nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget);
--- a/ipc/glue/MessageChannel.cpp +++ b/ipc/glue/MessageChannel.cpp @@ -31,16 +31,18 @@ struct RunnableMethodTraits<mozilla::ipc }; #define IPC_ASSERT(_cond, ...) \ do { \ if (!(_cond)) \ DebugAbort(__FILE__, __LINE__, #_cond,## __VA_ARGS__); \ } while (0) +static uintptr_t gDispatchingUrgentMessageCount; + namespace mozilla { namespace ipc { const int32_t MessageChannel::kNoTimeout = INT32_MIN; // static bool MessageChannel::sIsPumpingMessages = false; @@ -1094,19 +1096,23 @@ MessageChannel::DispatchSyncMessage(cons void MessageChannel::DispatchUrgentMessage(const Message& aMsg) { AssertWorkerThread(); MOZ_ASSERT(aMsg.is_urgent()); Message *reply = nullptr; + MOZ_ASSERT(NS_IsMainThread()); + + gDispatchingUrgentMessageCount++; mDispatchingUrgentMessageCount++; Result rv = mListener->OnCallReceived(aMsg, reply); mDispatchingUrgentMessageCount--; + gDispatchingUrgentMessageCount--; if (!MaybeHandleError(rv, "DispatchUrgentMessage")) { delete reply; reply = new Message(); reply->set_urgent(); reply->set_reply(); reply->set_reply_error(); } @@ -1747,10 +1753,16 @@ MessageChannel::DumpInterruptStack(const const char* dir, *sems, *name; mCxxStackFrames[i].Describe(&id, &dir, &sems, &name); printf_stderr("%s[(%u) %s %s %s(actor=%d) ]\n", pfx, i, dir, sems, name, id); } } +bool +ProcessingUrgentMessages() +{ + return gDispatchingUrgentMessageCount > 0; +} + } // ipc } // mozilla
--- a/ipc/glue/MessageChannel.h +++ b/ipc/glue/MessageChannel.h @@ -636,12 +636,15 @@ class MessageChannel : HasResultCodes HANDLE mEvent; #endif // Should the channel abort the process from the I/O thread when // a channel error occurs? bool mAbortOnError; }; +bool +ProcessingUrgentMessages(); + } // namespace ipc } // namespace mozilla #endif // ifndef ipc_glue_MessageChannel_h
--- a/js/ipc/JavaScriptChild.cpp +++ b/js/ipc/JavaScriptChild.cpp @@ -3,39 +3,55 @@ * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "JavaScriptChild.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/BindingUtils.h" +#include "mozilla/ipc/MessageChannel.h" #include "nsContentUtils.h" #include "xpcprivate.h" #include "jsfriendapi.h" #include "nsCxPusher.h" +#include "AccessCheck.h" using namespace JS; using namespace mozilla; using namespace mozilla::jsipc; using mozilla::AutoSafeJSContext; +#ifdef NIGHTLY_BUILD +static void +UrgentMessageCheck(JSContext *cx, HandleScript script) +{ + // We're only allowed to enter chrome JS code while processing urgent + // messages. + if (ipc::ProcessingUrgentMessages()) + MOZ_RELEASE_ASSERT(xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))); +} +#endif + static void FinalizeChild(JSFreeOp *fop, JSFinalizeStatus status, bool isCompartment, void *data) { if (status == JSFINALIZE_GROUP_START) { static_cast<JavaScriptChild *>(data)->finalize(fop); } } JavaScriptChild::JavaScriptChild(JSRuntime *rt) : JavaScriptShared(rt), JavaScriptBase<PJavaScriptChild>(rt) { +#ifdef NIGHTLY_BUILD + js::SetAssertOnScriptEntryHook(rt, UrgentMessageCheck); +#endif } JavaScriptChild::~JavaScriptChild() { JS_RemoveFinalizeCallback(rt_, FinalizeChild); } bool
--- a/js/ipc/moz.build +++ b/js/ipc/moz.build @@ -25,10 +25,11 @@ FINAL_LIBRARY = 'xul' DEFINES['BIN_SUFFIX'] = '"%s"' % CONFIG['BIN_SUFFIX'] LOCAL_INCLUDES += [ '/dom/base', '/js/ipc', '/js/public', '/js/xpconnect/src', + '/js/xpconnect/wrappers', ]
--- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -58,16 +58,24 @@ js::SetSourceHook(JSRuntime *rt, UniqueP } JS_FRIEND_API(UniquePtr<SourceHook>) js::ForgetSourceHook(JSRuntime *rt) { return Move(rt->sourceHook); } +#ifdef NIGHTLY_BUILD +JS_FRIEND_API(void) +js::SetAssertOnScriptEntryHook(JSRuntime *rt, AssertOnScriptEntryHook hook) +{ + rt->assertOnScriptEntryHook_ = hook; +} +#endif + JS_FRIEND_API(void) JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data) { rt->gc.setGrayRootsTracer(traceOp, data); } JS_FRIEND_API(JSString *) JS_GetAnonymousString(JSRuntime *rt)
--- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -412,16 +412,23 @@ class SourceHook { */ extern JS_FRIEND_API(void) SetSourceHook(JSRuntime *rt, mozilla::UniquePtr<SourceHook> hook); /* Remove |rt|'s source hook, and return it. The caller now owns the hook. */ extern JS_FRIEND_API(mozilla::UniquePtr<SourceHook>) ForgetSourceHook(JSRuntime *rt); +#ifdef NIGHTLY_BUILD +typedef void (*AssertOnScriptEntryHook)(JSContext *cx, JS::HandleScript script); + +extern JS_FRIEND_API(void) +SetAssertOnScriptEntryHook(JSRuntime *rt, AssertOnScriptEntryHook hook); +#endif + extern JS_FRIEND_API(JS::Zone *) GetCompartmentZone(JSCompartment *comp); typedef bool (* PreserveWrapperCallback)(JSContext *cx, JSObject *obj); typedef enum { CollectNurseryBeforeDump,
--- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -369,16 +369,21 @@ ExecuteState::pushInterpreterFrame(JSCon type_, evalInFrame_); } bool js::RunScript(JSContext *cx, RunState &state) { JS_CHECK_RECURSION(cx, return false); +#ifdef NIGHTLY_BUILD + if (AssertOnScriptEntryHook hook = cx->runtime()->assertOnScriptEntryHook_) + (*hook)(cx, state.script()); +#endif + SPSEntryMarker marker(cx->runtime(), state.script()); state.script()->ensureNonLazyCanonicalFunction(cx); #ifdef JS_ION if (jit::IsIonEnabled(cx)) { jit::MethodStatus status = jit::CanEnter(cx, state); if (status == jit::Method_Error)
--- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -198,17 +198,17 @@ class RunState JS_ASSERT(isInvoke()); return (InvokeState *)this; } GeneratorState *asGenerator() const { JS_ASSERT(isGenerator()); return (GeneratorState *)this; } - JSScript *script() const { return script_; } + JS::HandleScript script() const { return script_; } virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx) = 0; virtual void setReturnValue(Value v) = 0; private: RunState(const RunState &other) MOZ_DELETE; RunState(const ExecuteState &other) MOZ_DELETE; RunState(const InvokeState &other) MOZ_DELETE;
--- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -176,16 +176,17 @@ JSRuntime::JSRuntime(JSRuntime *parentRu #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR) simulatorRuntime_(nullptr), #endif scriptAndCountsVector(nullptr), NaNValue(DoubleNaNValue()), negativeInfinityValue(DoubleValue(NegativeInfinity<double>())), positiveInfinityValue(DoubleValue(PositiveInfinity<double>())), emptyString(nullptr), + assertOnScriptEntryHook_(nullptr), debugMode(false), spsProfiler(thisFromCtor()), profilingScripts(false), hadOutOfMemory(false), haveCreatedContext(false), data(nullptr), signalHandlersInstalled_(false), defaultFreeOp_(thisFromCtor(), false),
--- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1031,16 +1031,18 @@ struct JSRuntime : public JS::shadow::Ru mozilla::LinkedList<JSContext> contextList; bool hasContexts() const { return !contextList.isEmpty(); } mozilla::UniquePtr<js::SourceHook> sourceHook; + js::AssertOnScriptEntryHook assertOnScriptEntryHook_; + /* Per runtime debug hooks -- see js/OldDebugAPI.h. */ JSDebugHooks debugHooks; /* If true, new compartments are initially in debug mode. */ bool debugMode; /* SPS profiling metadata */ js::SPSProfiler spsProfiler;
--- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -4336,16 +4336,18 @@ inline static mozilla::HangMonitor::Acti return mozilla::HangMonitor::kActivityUIAVail; } // The WndProc procedure for all nsWindows in this toolkit. This merely catches // exceptions and passes the real work to WindowProcInternal. See bug 587406 // and http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + MOZ_RELEASE_ASSERT(!ipc::ProcessingUrgentMessages()); + HangMonitor::NotifyActivity(ActivityTypeForMessage(msg)); return mozilla::CallWindowProcCrashProtected(WindowProcInternal, hWnd, msg, wParam, lParam); } LRESULT CALLBACK nsWindow::WindowProcInternal(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (::GetWindowLongPtrW(hWnd, GWLP_ID) == eFakeTrackPointScrollableID) {
--- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -20,16 +20,17 @@ #include "nsIProgrammingLanguage.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "pratom.h" #include "prlog.h" #include "nsIObserverService.h" #include "mozilla/HangMonitor.h" #include "mozilla/IOInterposer.h" +#include "mozilla/ipc/MessageChannel.h" #include "mozilla/Services.h" #include "nsXPCOMPrivate.h" #include "mozilla/ChaosMode.h" #ifdef XP_LINUX #include <sys/time.h> #include <sys/resource.h> #include <sched.h> @@ -681,16 +682,18 @@ void canary_alarm_handler(int signum) } \ PR_END_MACRO NS_IMETHODIMP nsThread::ProcessNextEvent(bool aMayWait, bool* aResult) { LOG(("THRD(%p) ProcessNextEvent [%u %u]\n", this, aMayWait, mRunningEvent)); + MOZ_RELEASE_ASSERT(!ipc::ProcessingUrgentMessages()); + if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) { return NS_ERROR_NOT_SAME_THREAD; } // The toplevel event loop normally blocks waiting for the next event, but // if we're trying to shut this thread down, we must exit the event loop when // the event queue is empty. // This only applys to the toplevel event loop! Nested event loops (e.g.