Bug 1432429 JS fuzzy time update 8/14
MozReview-Commit-ID: EH8XsX6Ubjf
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5701,16 +5701,24 @@ JS_RequestInterruptCallback(JSContext* c
}
JS_PUBLIC_API(void)
JS_RequestInterruptCallbackCanWait(JSContext* cx)
{
cx->requestInterrupt(InterruptReason::CallbackCanWait);
}
+#ifdef MOZ_FUZZYFOX
+JS_PUBLIC_API(void)
+JS_UpdateLockedClock(JSContext* cx, int64_t update)
+{
+ cx->runtime()->updateLockedClock(update);
+}
+#endif
+
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,16 +5483,21 @@ 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);
+#ifdef MOZ_FUZZYFOX
+extern JS_PUBLIC_API(void)
+JS_UpdateLockedClock(JSContext* cx, int64_t update);
+#endif
+
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:
new file mode 100644
--- /dev/null
+++ b/js/src/vm/FuzzyfoxClock.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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
+
+namespace js {
+
+/* Locked clock impl*/
+class FuzzyfoxClock
+{
+ public:
+ FuzzyfoxClock() : currentClock(0)
+ {}
+
+ int64_t
+ getFuzzyfoxClock() const
+ {
+ return currentClock;
+ }
+
+ bool
+ isClockStarted() const
+ {
+ return currentClock;
+ }
+
+ void
+ updateFuzzyfoxClock(int64_t update)
+ {
+ currentClock = update;
+ }
+
+ private:
+ int64_t currentClock;
+};
+
+} // js namespace
+
+#endif /* FuzzyfoxClock_h*/
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -806,16 +806,36 @@ void
JSRuntime::setUsedByHelperThread(Zone* zone)
{
MOZ_ASSERT(!zone->usedByHelperThread());
MOZ_ASSERT(!zone->wasGCStarted());
zone->setUsedByHelperThread();
numActiveHelperThreadZones++;
}
+#ifdef MOZ_FUZZYFOX
+void
+JSRuntime::updateLockedClock(int64_t update)
+{
+ fuzzyfoxClock.updateFuzzyfoxClock(update);
+}
+
+bool
+JSRuntime::hasValidFuzzyfoxClock() const
+{
+ return fuzzyfoxClock.isClockStarted();
+}
+
+int64_t
+JSRuntime::getFuzzyfoxClock() const
+{
+ return fuzzyfoxClock.getFuzzyfoxClock();
+}
+#endif
+
void
JSRuntime::clearUsedByHelperThread(Zone* zone)
{
MOZ_ASSERT(zone->usedByHelperThread());
zone->clearUsedByHelperThread();
numActiveHelperThreadZones--;
JSContext* cx = mainContextFromOwnThread();
if (gc.fullGCForAtomsRequested() && cx->canCollectAtoms())
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -37,16 +37,19 @@
#endif
#include "js/UniquePtr.h"
#include "js/Vector.h"
#include "threading/Thread.h"
#include "vm/Caches.h"
#include "vm/CodeCoverage.h"
#include "vm/CommonPropertyNames.h"
#include "vm/DateTime.h"
+#ifdef MOZ_FUZZYFOX
+#include "vm/FuzzyfoxClock.h"
+#endif
#include "vm/GeckoProfiler.h"
#include "vm/JSAtom.h"
#include "vm/JSScript.h"
#include "vm/Scope.h"
#include "vm/SharedImmutableStringsCache.h"
#include "vm/Stack.h"
#include "vm/Stopwatch.h"
#include "vm/SymbolType.h"
@@ -961,16 +964,26 @@ struct JSRuntime : public js::MallocProv
bool isExecuting;
// if non-null, any call to `setPendingException`
// in this runtime will trigger the call to `interceptor`
JSErrorInterceptor* interceptor;
};
ErrorInterceptionSupport errorInterception;
#endif // defined(NIGHTLY_BUILD)
+
+#ifdef MOZ_FUZZYFOX
+ public:
+ void updateLockedClock(int64_t update);
+ bool hasValidFuzzyfoxClock() const;
+ int64_t getFuzzyfoxClock() const;
+
+ private:
+ js::FuzzyfoxClock fuzzyfoxClock;
+#endif
};
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
@@ -6,16 +6,18 @@
/* PR time code. */
#include "vm/Time.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/MathAlgorithms.h"
+#include "vm/JSContext.h"
+
#ifdef SOLARIS
#define _REENTRANT 1
#endif
#include <string.h>
#include <time.h>
#include "jstypes.h"
#include "jsutil.h"
@@ -42,16 +44,22 @@ extern int gettimeofday(struct timeval*
#endif /* XP_UNIX */
using mozilla::DebugOnly;
#if defined(XP_UNIX)
int64_t
PRMJ_Now()
{
+#ifdef MOZ_FUZZYFOX
+ JSContext* cx = js::TlsContext.get();
+ if (cx && cx->runtime()->hasValidFuzzyfoxClock())
+ return cx->runtime()->getFuzzyfoxClock();
+#endif
+
struct timeval tv;
#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
gettimeofday(&tv);
#else
gettimeofday(&tv, 0);
#endif /* _SVID_GETTOD */
@@ -148,16 +156,22 @@ PRMJ_NowShutdown()
#define MUTEX_LOCK(m) EnterCriticalSection(m)
#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()
{
+#ifdef MOZ_FUZZYFOX
+ JSContext* cx = js::TlsContext.get();
+ if (cx && cx->runtime()->hasValidFuzzyfoxClock())
+ return cx->runtime()->getFuzzyfoxClock();
+#endif
+
if (pGetSystemTimePreciseAsFileTime) {
// Windows 8 has a new API function that does all the work.
FILETIME ft;
pGetSystemTimePreciseAsFileTime(&ft);
return int64_t(FileTimeToUnixMicroseconds(ft));
}
bool calibrated = false;
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/src/FuzzyfoxClockUpdater.cpp
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "FuzzyfoxClockUpdater.h"
+#include "mozilla/CycleCollectedJSContext.h"
+#include "nsThreadUtils.h"
+#include "nsCOMPtr.h"
+
+using namespace mozilla;
+
+/* static */ already_AddRefed<FuzzyfoxClockUpdater>
+FuzzyfoxClockUpdater::Create()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ RefPtr<FuzzyfoxClockUpdater> holder = new FuzzyfoxClockUpdater();
+ if (!holder->Initialize()) {
+ return nullptr;
+ }
+
+ return holder.forget();
+}
+
+FuzzyfoxClockUpdater::FuzzyfoxClockUpdater()
+ : mShutdown(false)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+FuzzyfoxClockUpdater::~FuzzyfoxClockUpdater()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+bool
+FuzzyfoxClockUpdater::Initialize()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+ if (NS_WARN_IF(!obs)) {
+ return false;
+ }
+
+ nsresult rv = obs->AddObserver(this, "fuzzyfox-update-clocks", false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return false;
+ }
+
+ rv = obs->AddObserver(this, "xpcom-shutdown", false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return false;
+ }
+
+ return true;
+}
+
+NS_IMETHODIMP
+FuzzyfoxClockUpdater::Observe(nsISupports* aSubject, const char* aTopic,
+ const char16_t* aData)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ if (!strcmp(aTopic, "fuzzyfox-update-clocks")) {
+ 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);
+ return NS_OK;
+ }
+
+ MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
+ Shutdown();
+ return NS_OK;
+}
+
+void
+FuzzyfoxClockUpdater::Shutdown()
+{
+ if (mShutdown) {
+ return;
+ }
+
+ mShutdown = true;
+
+ nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+ if (NS_WARN_IF(!obs)) {
+ return;
+ }
+
+ obs->RemoveObserver(this, "fuzzyfox-update-clocks");
+ obs->RemoveObserver(this, "xpcom-shutdown");
+}
+
+NS_INTERFACE_MAP_BEGIN(FuzzyfoxClockUpdater)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
+ NS_INTERFACE_MAP_ENTRY(nsIObserver)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(FuzzyfoxClockUpdater)
+NS_IMPL_RELEASE(FuzzyfoxClockUpdater)
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/src/FuzzyfoxClockUpdater.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 mozilla_FuzzyfoxClockUpdater_h
+#define mozilla_FuzzyfoxClockUpdater_h
+
+#include "nsIObserver.h"
+
+namespace mozilla {
+
+// This class holds a FuzzyFoxClock object and it keeps updated.
+class FuzzyfoxClockUpdater final : public nsIObserver
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+
+ static already_AddRefed<FuzzyfoxClockUpdater>
+ Create();
+
+ void
+ Shutdown();
+
+private:
+ FuzzyfoxClockUpdater();
+ ~FuzzyfoxClockUpdater();
+
+ bool
+ Initialize();
+
+ bool
+ mShutdown;
+};
+
+} // mozilla namespace
+
+#endif /* mozilla_FuzzyfoxClockUpdater_h */
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -51,16 +51,20 @@
#include "mozilla/ProcessHangMonitor.h"
#include "mozilla/Sprintf.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/Unused.h"
#include "AccessCheck.h"
#include "nsGlobalWindow.h"
#include "nsAboutProtocolUtils.h"
+#ifdef MOZ_FUZZYFOX
+#include "FuzzyfoxClockUpdater.h"
+#endif
+
#include "GeckoProfiler.h"
#include "nsIInputStream.h"
#include "nsIXULRuntime.h"
#include "nsJSPrincipals.h"
#ifdef XP_WIN
#include <windows.h>
#endif
@@ -1063,16 +1067,23 @@ XPCJSRuntime::Shutdown(JSContext* cx)
mClassInfo2NativeSetMap = nullptr;
delete mNativeSetMap;
mNativeSetMap = nullptr;
delete mDyingWrappedNativeProtoMap;
mDyingWrappedNativeProtoMap = nullptr;
+#ifdef MOZ_FUZZYFOX
+ if (mFuzzyfoxClockUpdater) {
+ mFuzzyfoxClockUpdater->Shutdown();
+ mFuzzyfoxClockUpdater = nullptr;
+ }
+#endif
+
CycleCollectedJSRuntime::Shutdown(cx);
}
XPCJSRuntime::~XPCJSRuntime()
{
MOZ_COUNT_DTOR_INHERITED(XPCJSRuntime, CycleCollectedJSRuntime);
}
@@ -2878,16 +2889,20 @@ XPCJSRuntime::Initialize(JSContext* cx)
RegisterStrongMemoryReporter(new JSMainRuntimeTemporaryPeakReporter());
RegisterJSMainRuntimeGCHeapDistinguishedAmount(JSMainRuntimeGCHeapDistinguishedAmount);
RegisterJSMainRuntimeTemporaryPeakDistinguishedAmount(JSMainRuntimeTemporaryPeakDistinguishedAmount);
RegisterJSMainRuntimeRealmsSystemDistinguishedAmount(JSMainRuntimeRealmsSystemDistinguishedAmount);
RegisterJSMainRuntimeRealmsUserDistinguishedAmount(JSMainRuntimeRealmsUserDistinguishedAmount);
mozilla::RegisterJSSizeOfTab(JSSizeOfTab);
xpc_LocalizeRuntime(JS_GetRuntime(cx));
+
+#ifdef MOZ_FUZZYFOX
+ mFuzzyfoxClockUpdater = FuzzyfoxClockUpdater::Create();
+#endif
}
bool
XPCJSRuntime::InitializeStrings(JSContext* cx)
{
JSAutoRequest ar(cx);
// if it is our first context then we need to generate our string ids
--- a/js/xpconnect/src/XPCRuntimeService.cpp
+++ b/js/xpconnect/src/XPCRuntimeService.cpp
@@ -25,16 +25,17 @@ NS_IMPL_ISUPPORTS(BackstagePass,
XPC_SCRIPTABLE_WANT_ENUMERATE | \
XPC_SCRIPTABLE_WANT_FINALIZE | \
XPC_SCRIPTABLE_WANT_PRECREATE | \
XPC_SCRIPTABLE_USE_JSSTUB_FOR_ADDPROPERTY | \
XPC_SCRIPTABLE_USE_JSSTUB_FOR_DELPROPERTY | \
XPC_SCRIPTABLE_DONT_ENUM_QUERY_INTERFACE | \
XPC_SCRIPTABLE_IS_GLOBAL_OBJECT | \
XPC_SCRIPTABLE_DONT_REFLECT_INTERFACE_NAMES)
+#include "xpc_make_class.h"
#include "xpc_map_end.h" /* This will #undef the above */
JSObject*
BackstagePass::GetGlobalJSObject()
{
if (mWrapper)
return mWrapper->GetFlatJSObject();
--- a/js/xpconnect/src/moz.build
+++ b/js/xpconnect/src/moz.build
@@ -38,16 +38,21 @@ UNIFIED_SOURCES += [
'XPCWrappedNative.cpp',
'XPCWrappedNativeInfo.cpp',
'XPCWrappedNativeJSOps.cpp',
'XPCWrappedNativeProto.cpp',
'XPCWrappedNativeScope.cpp',
'XPCWrapper.cpp',
]
+if CONFIG['MOZ_FUZZYFOX']:
+ UNIFIED_SOURCES += [
+ 'FuzzyfoxClockUpdater.cpp',
+ ]
+
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../loader',
'../wrappers',
'/caps',
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -155,19 +155,25 @@
#undef GetClassInfo
#endif
#ifdef GetClassName
#undef GetClassName
#endif
#endif /* XP_WIN */
namespace mozilla {
+
+#ifdef MOZ_FUZZYFOX
+class FuzzyfoxClockUpdater;
+#endif
+
namespace dom {
class Exception;
} // namespace dom
+
} // namespace mozilla
/***************************************************************************/
// default initial sizes for maps (hashtables)
#define XPC_JS_MAP_LENGTH 32
#define XPC_JS_CLASS_MAP_LENGTH 32
@@ -612,16 +618,20 @@ private:
nsTArray<xpcGCCallback> extraGCCallbacks;
JS::GCSliceCallback mPrevGCSliceCallback;
JS::DoCycleCollectionCallback mPrevDoCycleCollectionCallback;
JS::PersistentRootedObject mUnprivilegedJunkScope;
JS::PersistentRootedObject mPrivilegedJunkScope;
JS::PersistentRootedObject mCompilationScope;
RefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
+#ifdef MOZ_FUZZYFOX
+ RefPtr<mozilla::FuzzyfoxClockUpdater> mFuzzyfoxClockUpdater;
+#endif
+
friend class XPCJSContext;
friend class XPCIncrementalReleaseRunnable;
};
inline JS::HandleId
XPCJSContext::GetStringID(unsigned index) const
{
return Runtime()->GetStringID(index);
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -6026,26 +6026,29 @@ nsHttpChannel::AsyncOpen(nsIStreamListen
return NS_OK;
}
nsresult
nsHttpChannel::AsyncOpenFinal(TimeStamp aTimeStamp)
{
// Added due to PauseTask/DelayHttpChannel
nsresult rv;
+ TimeStamp now = aTimeStamp;
+#else
+ TimeStamp now = TimeStamp::Now();
#endif
if (mLoadGroup)
mLoadGroup->AddRequest(this, nullptr);
// record asyncopen time unconditionally and clear it if we
// don't want it after OnModifyRequest() weighs in. But waiting for
// that to complete would mean we don't include proxy resolution in the
// timing.
- mAsyncOpenTime = aTimeStamp;
+ mAsyncOpenTime = now;
// Remember we have Authorization header set here. We need to check on it
// just once and early, AsyncOpen is the best place.
mCustomAuthHeader = mRequestHead.HasHeader(nsHttp::Authorization);
// The common case for HTTP channels is to begin proxy resolution and return
// at this point. The only time we know mProxyInfo already is if we're
// proxying a non-http protocol like ftp. We don't need to discover proxy