author | Brian Hackett <bhackett1024@gmail.com> |
Mon, 20 May 2013 20:26:44 -0600 | |
changeset 132478 | bfb827bd48d0cc7c57fb0d1c580e11efcc6971c0 |
parent 132477 | 399dc3feb02022fe2c8886335c310757c92b7c41 |
child 132479 | 24c7abacfd423ea281d1126e5f7c33215452fea5 |
push id | 24705 |
push user | ryanvm@gmail.com |
push date | Tue, 21 May 2013 17:24:33 +0000 |
treeherder | mozilla-central@97f49d0b228c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bholley |
bugs | 871079 |
milestone | 24.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
|
js/xpconnect/src/XPCJSRuntime.cpp | file | annotate | diff | comparison | revisions | |
js/xpconnect/src/xpcprivate.h | file | annotate | diff | comparison | revisions |
--- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1073,60 +1073,76 @@ class AutoLockWatchdog { PR_Lock(mRuntime->mWatchdogLock); } ~AutoLockWatchdog() { PR_Unlock(mRuntime->mWatchdogLock); } }; +bool +XPCJSRuntime::IsRuntimeActive() +{ + return mRuntimeState == RUNTIME_ACTIVE; +} + +PRTime +XPCJSRuntime::TimeSinceLastRuntimeStateChange() +{ + return PR_Now() - mTimeAtLastRuntimeStateChange; +} + //static void XPCJSRuntime::WatchdogMain(void *arg) { PR_SetCurrentThreadName("JS Watchdog"); XPCJSRuntime* self = static_cast<XPCJSRuntime*>(arg); // Lock lasts until we return AutoLockWatchdog lock(self); PRIntervalTime sleepInterval; while (self->mWatchdogThread) { // Sleep only 1 second if recently (or currently) active; otherwise, hibernate - if (self->mLastActiveTime == -1 || PR_Now() - self->mLastActiveTime <= PRTime(2*PR_USEC_PER_SEC)) + if (self->IsRuntimeActive() || self->TimeSinceLastRuntimeStateChange() <= PRTime(2*PR_USEC_PER_SEC)) sleepInterval = PR_TicksPerSecond(); else { sleepInterval = PR_INTERVAL_NO_TIMEOUT; self->mWatchdogHibernating = true; } MOZ_ALWAYS_TRUE(PR_WaitCondVar(self->mWatchdogWakeup, sleepInterval) == PR_SUCCESS); - JS_TriggerOperationCallback(self->mJSRuntime); + + // Don't trigger the operation callback if activity started less than one second ago. + // The callback is only used for detecting long running scripts, and triggering the + // callback from off the main thread can be expensive. + if (self->IsRuntimeActive() && self->TimeSinceLastRuntimeStateChange() >= PRTime(PR_USEC_PER_SEC)) + JS_TriggerOperationCallback(self->mJSRuntime); } /* Wake up the main thread waiting for the watchdog to terminate. */ PR_NotifyCondVar(self->mWatchdogWakeup); } //static void XPCJSRuntime::ActivityCallback(void *arg, JSBool active) { XPCJSRuntime* self = static_cast<XPCJSRuntime*>(arg); AutoLockWatchdog lock(self); - - if (active) { - self->mLastActiveTime = -1; - if (self->mWatchdogHibernating) { - self->mWatchdogHibernating = false; - PR_NotifyCondVar(self->mWatchdogWakeup); - } - } else { - self->mLastActiveTime = PR_Now(); + + self->mTimeAtLastRuntimeStateChange = PR_Now(); + self->mRuntimeState = active ? RUNTIME_ACTIVE : RUNTIME_INACTIVE; + + // Wake the watchdog up if it is hibernating due to a long period of inactivity. + if (active && self->mWatchdogHibernating) { + self->mWatchdogHibernating = false; + PR_NotifyCondVar(self->mWatchdogWakeup); } } // static // // JS-CTypes creates and caches a JSContext that it uses when executing JS // callbacks. When we're notified that ctypes is about to call into some JS, // push the cx to maintain the integrity of the context stack. @@ -2648,17 +2664,18 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* mDoingFinalization(false), mVariantRoots(nullptr), mWrappedJSRoots(nullptr), mObjectHolderRoots(nullptr), mWatchdogLock(nullptr), mWatchdogWakeup(nullptr), mWatchdogThread(nullptr), mWatchdogHibernating(false), - mLastActiveTime(-1), + mRuntimeState(RUNTIME_INACTIVE), + mTimeAtLastRuntimeStateChange(PR_Now()), mJunkScope(nullptr), mExceptionManagerNotAvailable(false) #ifdef DEBUG , mObjectToUnlink(nullptr) #endif { #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN DEBUG_WrappedNativeHashtable =
--- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -900,16 +900,18 @@ private: XPCJSRuntime(nsXPConnect* aXPConnect); // The caller must be holding the GC lock void RescheduleWatchdog(XPCContext* ccx); static void WatchdogMain(void *arg); void ReleaseIncrementally(nsTArray<nsISupports *> &array); + bool IsRuntimeActive(); + PRTime TimeSinceLastRuntimeStateChange(); static const char* mStrings[IDX_TOTAL_COUNT]; jsid mStrIDs[IDX_TOTAL_COUNT]; jsval mStrJSVals[IDX_TOTAL_COUNT]; nsXPConnect* mXPConnect; JSRuntime* mJSRuntime; XPCJSContextStack* mJSContextStack; @@ -935,17 +937,18 @@ private: XPCRootSetElem *mWrappedJSRoots; XPCRootSetElem *mObjectHolderRoots; nsDataHashtable<nsPtrHashKey<void>, nsScriptObjectTracer*> mJSHolders; PRLock *mWatchdogLock; PRCondVar *mWatchdogWakeup; PRThread *mWatchdogThread; nsTArray<JSGCCallback> extraGCCallbacks; bool mWatchdogHibernating; - PRTime mLastActiveTime; // -1 if active NOW + enum { RUNTIME_ACTIVE, RUNTIME_INACTIVE } mRuntimeState; + PRTime mTimeAtLastRuntimeStateChange; nsRefPtr<XPCIncrementalReleaseRunnable> mReleaseRunnable; JS::GCSliceCallback mPrevGCSliceCallback; JSObject* mJunkScope; nsCOMPtr<nsIException> mPendingException; nsCOMPtr<nsIExceptionManager> mExceptionManager; bool mExceptionManagerNotAvailable;