Bug 1432429 Tell the JS Runtime/Workers whether or not Fuzzyfox is enabled 13/14
MozReview-Commit-ID: 6F9sVpOxZUV
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2673,16 +2673,17 @@ nsJSContext::EnsureStatics()
asmjscache::CloseEntryForRead,
AsmJSCacheOpenEntryForWrite,
asmjscache::CloseEntryForWrite
};
JS::SetAsmJSCacheOps(jsapi.cx(), &asmJSCacheOps);
JS::InitDispatchToEventLoop(jsapi.cx(), DispatchToEventLoop, nullptr);
JS::InitConsumeStreamCallback(jsapi.cx(), ConsumeStream);
+ js::InitCheckLockedClockEnabledStatusCallback(jsapi.cx(), GetFuzzyfoxEnabled);
// Set these global xpconnect options...
Preferences::RegisterCallbackAndCall(SetMemoryPrefChangedCallbackMB,
"javascript.options.mem.high_water_mark",
(void*)JSGC_MAX_MALLOC_BYTES);
Preferences::RegisterCallbackAndCall(SetMemoryPrefChangedCallbackMB,
"javascript.options.mem.max",
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -769,17 +769,17 @@ public:
int64_t aNewTime)
: WorkerRunnable(aWorkerPrivate)
, mNewTime(aNewTime)
{}
virtual bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
- JS_UpdateLockedClock(aCx, mNewTime);
+ js::UpdateLockedClock(aCx, mNewTime);
return true;
}
};
class UpdateLanguagesRunnable final : public WorkerRunnable
{
nsTArray<nsString> mLanguages;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5701,22 +5701,16 @@ JS_RequestInterruptCallback(JSContext* c
}
JS_PUBLIC_API(void)
JS_RequestInterruptCallbackCanWait(JSContext* cx)
{
cx->requestInterrupt(InterruptReason::CallbackCanWait);
}
-JS_PUBLIC_API(void)
-JS_UpdateLockedClock(JSContext* cx, int64_t update)
-{
- cx->runtime()->updateLockedClock(update);
-}
-
JS::AutoSetAsyncStackForNewCalls::AutoSetAsyncStackForNewCalls(
JSContext* cx, HandleObject stack, const char* asyncCause,
JS::AutoSetAsyncStackForNewCalls::AsyncCallKind kind)
: cx(cx),
oldAsyncStack(cx, cx->asyncStackForNewActivations()),
oldAsyncCause(cx->asyncCauseForNewActivations),
oldAsyncCallIsExplicit(cx->asyncCallIsExplicit)
{
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5483,19 +5483,16 @@ extern JS_PUBLIC_API(bool)
JS_GetPendingException(JSContext* cx, JS::MutableHandleValue vp);
extern JS_PUBLIC_API(void)
JS_SetPendingException(JSContext* cx, JS::HandleValue v);
extern JS_PUBLIC_API(void)
JS_ClearPendingException(JSContext* cx);
-extern JS_PUBLIC_API(void)
-JS_UpdateLockedClock(JSContext* cx, int64_t update);
-
namespace JS {
/**
* Save and later restore the current exception state of a given JSContext.
* This is useful for implementing behavior in C++ that's like try/catch
* or try/finally in JS.
*
* Typical usage:
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -805,16 +805,28 @@ js::DumpPC(JSContext* cx) {
JS_FRIEND_API(bool)
js::DumpScript(JSContext* cx, JSScript* scriptArg)
{
return DumpScript(cx, scriptArg, stdout);
}
#endif
+JS_FRIEND_API(void)
+js::UpdateLockedClock(JSContext* cx, int64_t update)
+{
+ cx->runtime()->updateLockedClock(update);
+}
+
+JS_FRIEND_API(void)
+js::InitCheckLockedClockEnabledStatusCallback(JSContext* cx, CheckLockedClockEnabledStatusCallback callback)
+{
+ cx->runtime()->setLockedClockEnabledStatusCallback(callback);
+}
+
static const char*
FormatValue(JSContext* cx, const Value& vArg, JSAutoByteString& bytes)
{
RootedValue v(cx, vArg);
if (v.isMagic(JS_OPTIMIZED_OUT))
return "[unavailable]";
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -290,16 +290,25 @@ extern JS_FRIEND_API(bool) DumpScript(JS
#endif
extern JS_FRIEND_API(void)
DumpBacktrace(JSContext* cx, FILE* fp);
extern JS_FRIEND_API(void)
DumpBacktrace(JSContext* cx);
+extern JS_FRIEND_API(void)
+UpdateLockedClock(JSContext* cx, int64_t update);
+
+typedef bool
+(* CheckLockedClockEnabledStatusCallback)();
+
+extern JS_FRIEND_API(void)
+InitCheckLockedClockEnabledStatusCallback(JSContext* cx, CheckLockedClockEnabledStatusCallback callback);
+
} // namespace js
namespace JS {
/** Exposed for DumpJSStack */
extern JS_FRIEND_API(JS::UniqueChars)
FormatStackDump(JSContext* cx, JS::UniqueChars&& buf, bool showArgs, bool showLocals,
bool showThisProps);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -9324,16 +9324,17 @@ main(int argc, char** argv, char** envp)
js_new<ExclusiveWaitableData<BufferStreamState>>(mutexid::BufferStreamState);
if (!bufferStreamState)
return 1;
auto shutdownBufferStreams = MakeScopeExit([] {
ShutdownBufferStreams();
js_delete(bufferStreamState);
});
JS::InitConsumeStreamCallback(cx, ConsumeBufferSource);
+ js::InitCheckLockedClockEnabledStatusCallback(cx, mozilla::GetFuzzyfoxEnabled);
JS_SetNativeStackQuota(cx, gMaxStackSize);
JS::dbg::SetDebuggerMallocSizeOf(cx, moz_malloc_size_of);
js::UseInternalJobQueues(cx);
if (const char* opt = op.getStringOption("nursery-strings")) {
--- a/js/src/vm/FuzzyfoxClock.h
+++ b/js/src/vm/FuzzyfoxClock.h
@@ -2,42 +2,62 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef FuzzyfoxClock_h
#define FuzzyfoxClock_h
+#include "js/GCAPI.h"
+
namespace js {
/* Locked clock impl*/
class FuzzyfoxClock
{
public:
- FuzzyfoxClock() : currentClock(0)
+ FuzzyfoxClock() : callback(NULL), currentClock(0)
{}
int64_t
getFuzzyfoxClock() const
{
return currentClock;
}
bool
isClockStarted() const
{
- return currentClock;
+ return getEnabled() && currentClock;
+ }
+
+ bool
+ getEnabled() const
+ {
+ // The Hazards build gets confused by this callback; because it could do 'anything'.
+ // In practice, it only returns a boolean member variable from the TimeStamp class.
+ JS::AutoSuppressGCAnalysis nogc;
+ if (callback)
+ return callback();
+ return false;
+ }
+
+ void
+ setEnabledStatusCallback(CheckLockedClockEnabledStatusCallback aCallback)
+ {
+ callback = aCallback;
}
void
updateFuzzyfoxClock(int64_t update)
{
currentClock = update;
}
private:
+ CheckLockedClockEnabledStatusCallback callback;
int64_t currentClock;
};
} // js namespace
#endif /* FuzzyfoxClock_h*/
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -806,28 +806,42 @@ void
JSRuntime::setUsedByHelperThread(Zone* zone)
{
MOZ_ASSERT(!zone->usedByHelperThread());
MOZ_ASSERT(!zone->wasGCStarted());
zone->setUsedByHelperThread();
numActiveHelperThreadZones++;
}
+js::FuzzyfoxClock JSRuntime::fuzzyfoxClock;
+
void
JSRuntime::updateLockedClock(int64_t update)
{
fuzzyfoxClock.updateFuzzyfoxClock(update);
}
+void
+JSRuntime::setLockedClockEnabledStatusCallback(js::CheckLockedClockEnabledStatusCallback callback)
+{
+ fuzzyfoxClock.setEnabledStatusCallback(callback);
+}
+
bool
JSRuntime::hasValidFuzzyfoxClock() const
{
return fuzzyfoxClock.isClockStarted();
}
+bool
+JSRuntime::getFuzzyfoxEnabled() const
+{
+ return fuzzyfoxClock.getEnabled();
+}
+
int64_t
JSRuntime::getFuzzyfoxClock() const
{
return fuzzyfoxClock.getFuzzyfoxClock();
}
void
JSRuntime::clearUsedByHelperThread(Zone* zone)
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -965,21 +965,23 @@ struct JSRuntime : public js::MallocProv
// in this runtime will trigger the call to `interceptor`
JSErrorInterceptor* interceptor;
};
ErrorInterceptionSupport errorInterception;
#endif // defined(NIGHTLY_BUILD)
public:
void updateLockedClock(int64_t update);
+ void setLockedClockEnabledStatusCallback(js::CheckLockedClockEnabledStatusCallback callback);
+ bool getFuzzyfoxEnabled() const;
bool hasValidFuzzyfoxClock() const;
int64_t getFuzzyfoxClock() const;
private:
- js::FuzzyfoxClock fuzzyfoxClock;
+ static js::FuzzyfoxClock fuzzyfoxClock;
};
namespace js {
/*
* RAII class that takes the GC lock while it is live.
*
* Usually functions will pass const references of this class. However
--- a/js/src/vm/Time.cpp
+++ b/js/src/vm/Time.cpp
@@ -45,28 +45,32 @@ extern int gettimeofday(struct timeval*
using mozilla::DebugOnly;
#if defined(XP_UNIX)
int64_t
PRMJ_Now()
{
JSContext* cx = js::TlsContext.get();
- if (cx && cx->runtime()->hasValidFuzzyfoxClock())
+ if (cx && cx->runtime() && cx->runtime()->hasValidFuzzyfoxClock())
return cx->runtime()->getFuzzyfoxClock();
struct timeval tv;
#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
gettimeofday(&tv);
#else
gettimeofday(&tv, 0);
#endif /* _SVID_GETTOD */
- return int64_t(tv.tv_sec) * PRMJ_USEC_PER_SEC + int64_t(tv.tv_usec);
+ int64_t now = int64_t(tv.tv_sec) * PRMJ_USEC_PER_SEC + int64_t(tv.tv_usec);
+
+ if (cx && cx->runtime() && cx->runtime()->hasValidFuzzyfoxClock())
+ return cx->runtime()->getFuzzyfoxClock() > now ? cx->runtime()->getFuzzyfoxClock() : now;
+ return now;
}
#else
// Returns the number of microseconds since the Unix epoch.
static double
FileTimeToUnixMicroseconds(const FILETIME& ft)
{
@@ -155,24 +159,27 @@ PRMJ_NowShutdown()
#define MUTEX_UNLOCK(m) LeaveCriticalSection(m)
#define MUTEX_SETSPINCOUNT(m, c) SetCriticalSectionSpinCount((m),(c))
// Please see bug 363258 for why the win32 timing code is so complex.
int64_t
PRMJ_Now()
{
JSContext* cx = js::TlsContext.get();
- if (cx && cx->runtime()->hasValidFuzzyfoxClock())
+ if (cx && cx->runtime() && cx->runtime()->hasValidFuzzyfoxClock())
return cx->runtime()->getFuzzyfoxClock();
if (pGetSystemTimePreciseAsFileTime) {
// Windows 8 has a new API function that does all the work.
FILETIME ft;
pGetSystemTimePreciseAsFileTime(&ft);
- return int64_t(FileTimeToUnixMicroseconds(ft));
+ int64_t now = int64_t(FileTimeToUnixMicroseconds(ft));
+ if (cx && cx->runtime() && cx->runtime()->hasValidFuzzyfoxClock())
+ return cx->runtime()->getFuzzyfoxClock() > now ? cx->runtime()->getFuzzyfoxClock() : now;
+ return now;
}
bool calibrated = false;
bool needsCalibration = !calibration.calibrated;
double cachedOffset = 0.0;
while (true) {
if (needsCalibration) {
MUTEX_LOCK(&calibration.data_lock);
@@ -222,30 +229,36 @@ PRMJ_Now()
// For some reason that I have not determined, the skew can be
// up to twice a kernel tick. This does not seem to happen by
// itself, but I have only seen it triggered by another program
// doing some kind of file I/O. The symptoms are a negative diff
// followed by an equally large positive diff.
if (mozilla::Abs(diff) <= 2 * KernelTickInMicroseconds) {
// No detectable clock skew.
- return int64_t(highresTime);
+ int64_t now = int64_t(highresTime);
+ if (cx && cx->runtime() && cx->runtime()->hasValidFuzzyfoxClock())
+ return cx->runtime()->getFuzzyfoxClock() > now ? cx->runtime()->getFuzzyfoxClock() : now;
+ return now;
}
if (calibrated) {
// If we already calibrated once this instance, and the
// clock is still skewed, then either the processor(s) are
// wildly changing clockspeed or the system is so busy that
// we get switched out for long periods of time. In either
// case, it would be infeasible to make use of high
// resolution results for anything, so let's resort to old
// behavior for this call. It's possible that in the
// future, the user will want the high resolution timer, so
// we don't disable it entirely.
- return int64_t(lowresTime);
+ int64_t now = int64_t(lowresTime);
+ if (cx && cx->runtime() && cx->runtime()->hasValidFuzzyfoxClock())
+ return cx->runtime()->getFuzzyfoxClock() > now ? cx->runtime()->getFuzzyfoxClock() : now;
+ return now;
}
// It is possible that when we recalibrate, we will return a
// value less than what we have returned before; this is
// unavoidable. We cannot tell the different between a
// faulty QueryPerformanceCounter implementation and user
// changes to the operating system time. Since we must
// respect user changes to the operating system time, we
--- a/js/xpconnect/src/FuzzyfoxClockUpdater.cpp
+++ b/js/xpconnect/src/FuzzyfoxClockUpdater.cpp
@@ -60,36 +60,36 @@ FuzzyfoxClockUpdater::Initialize()
NS_IMETHODIMP
FuzzyfoxClockUpdater::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(NS_IsMainThread());
if (!strcmp(aTopic, "fuzzyfox-update-clocks")) {
+ CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
+ if (!ccjscx) {
+ return NS_OK;
+ }
+
+ JSContext* cx = ccjscx->Context();
+ MOZ_ASSERT(cx);
+
nsCOMPtr<nsISupportsPRInt64> wrapper = do_QueryInterface(aSubject);
if (NS_WARN_IF(!wrapper)) {
return NS_OK;
}
int64_t newTime = 0;
nsresult rv = wrapper->GetData(&newTime);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_OK;
}
- CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
- if (!ccjscx) {
- return NS_OK;
- }
-
- JSContext* cx = ccjscx->Context();
- MOZ_ASSERT(cx);
-
- JS_UpdateLockedClock(cx, newTime);
+ js::UpdateLockedClock(cx, newTime);
return NS_OK;
}
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
Shutdown();
return NS_OK;
}
--- a/mozglue/misc/TimeStamp.cpp
+++ b/mozglue/misc/TimeStamp.cpp
@@ -43,16 +43,22 @@ struct TimeStampInitialization
~TimeStampInitialization()
{
TimeStamp::Shutdown();
};
};
static bool sFuzzyfoxEnabled;
+bool
+GetFuzzyfoxEnabled()
+{
+ return TimeStamp::GetFuzzyfoxEnabled();
+}
+
/* static */ bool
TimeStamp::GetFuzzyfoxEnabled()
{
return sFuzzyfoxEnabled;
}
/* static */ void
TimeStamp::SetFuzzyfoxEnabled(bool aValue)
--- a/mozglue/misc/TimeStamp.h
+++ b/mozglue/misc/TimeStamp.h
@@ -644,11 +644,14 @@ private:
* When using a system clock, a value is system dependent.
*/
TimeStampValue mValue;
bool mUsedCanonicalNow;
friend class Fuzzyfox;
};
+MFBT_API bool
+GetFuzzyfoxEnabled();
+
} // namespace mozilla
#endif /* mozilla_TimeStamp_h */
--- a/toolkit/components/fuzzyfox/Fuzzyfox.cpp
+++ b/toolkit/components/fuzzyfox/Fuzzyfox.cpp
@@ -38,17 +38,16 @@ static LazyLogModule sFuzzyfoxLog("Fuzzy
#define LOG(level, args) MOZ_LOG(sFuzzyfoxLog, mozilla::LogLevel::level, args)
#define FUZZYFOX_ENABLED_PREF "privacy.fuzzyfox.enabled"
#define FUZZYFOX_ENABLED_PREF_DEFAULT false
#define FUZZYFOX_CLOCKGRAIN_PREF "privacy.fuzzyfox.clockgrainus"
#define FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT 100
-Atomic<bool, Relaxed> Fuzzyfox::sFuzzyfoxEnabledPrefMapped;
Atomic<uint32_t, Relaxed> Fuzzyfox::sFuzzyfoxClockGrain;
NS_IMPL_ISUPPORTS_INHERITED(Fuzzyfox, Runnable, nsIObserver)
/* static */ void
Fuzzyfox::Start()
{
MOZ_ASSERT(NS_IsMainThread());
@@ -64,27 +63,27 @@ Fuzzyfox::Fuzzyfox()
, mDuration(PickDuration())
, mTickType(eUptick)
{
MOZ_ASSERT(NS_IsMainThread());
// [[ I originally ran this after observing profile-after-change, but
// it turned out that this contructor was getting called _after_ that
// event had already fired. ]]
- Preferences::AddAtomicBoolVarCache(&sFuzzyfoxEnabledPrefMapped,
- FUZZYFOX_ENABLED_PREF,
- FUZZYFOX_ENABLED_PREF_DEFAULT);
Preferences::AddAtomicUintVarCache(&sFuzzyfoxClockGrain,
FUZZYFOX_CLOCKGRAIN_PREF,
FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT);
- LOG(Info, ("PT(%p) Created Fuzzyfox, sFuzzyfoxEnabled is now %s \n",
- this, (sFuzzyfoxEnabledPrefMapped ? "enabled" : "disabled")));
+ bool fuzzyfoxEnabled =
+ Preferences::GetBool(FUZZYFOX_ENABLED_PREF, FUZZYFOX_ENABLED_PREF_DEFAULT);
- TimeStamp::SetFuzzyfoxEnabled(sFuzzyfoxEnabledPrefMapped);
+ LOG(Info, ("PT(%p) Created Fuzzyfox, FuzzyFox is now %s \n",
+ this, (fuzzyfoxEnabled ? "enabled" : "disabled")));
+
+ TimeStamp::SetFuzzyfoxEnabled(fuzzyfoxEnabled);
// Should I see if these fail? And do what?
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefs->AddObserver(FUZZYFOX_ENABLED_PREF, this, false);
prefs->AddObserver(FUZZYFOX_CLOCKGRAIN_PREF, this, false);
}
Fuzzyfox::~Fuzzyfox() = default;
@@ -92,21 +91,24 @@ Fuzzyfox::~Fuzzyfox() = default;
NS_IMETHODIMP
Fuzzyfox::Observe(nsISupports* aObject, const char* aTopic,
const char16_t* aMessage)
{
if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
NS_ConvertUTF16toUTF8 pref(aMessage);
if (pref.EqualsLiteral(FUZZYFOX_ENABLED_PREF)) {
- LOG(Info, ("PT(%p) Observed a pref change, sFuzzyfoxEnabled is now %s \n",
- this, (sFuzzyfoxEnabledPrefMapped ? "enabled" : "disabled")));
+ bool fuzzyfoxEnabled =
+ Preferences::GetBool(FUZZYFOX_ENABLED_PREF, FUZZYFOX_ENABLED_PREF_DEFAULT);
+
+ LOG(Info, ("PT(%p) Observed a pref change, FuzzyFox is now %s \n",
+ this, (fuzzyfoxEnabled ? "enabled" : "disabled")));
- TimeStamp::SetFuzzyfoxEnabled(sFuzzyfoxEnabledPrefMapped);
+ TimeStamp::SetFuzzyfoxEnabled(fuzzyfoxEnabled);
if (TimeStamp::GetFuzzyfoxEnabled()) {
// Queue a runnable
nsCOMPtr<nsIRunnable> r = this;
SystemGroup::Dispatch(TaskCategory::Other, r.forget());
} else {
mStartTime = 0;