Bug 858927 - Move the mozilla::TimeStamp into mozglue. r=glandium
authorBenoit Girard <b56girard@gmail.com>
Fri, 05 Jun 2015 16:03:11 -0400
changeset 249681 bf2f1318c3c052e9da173c32ed1dab4de2a4a30c
parent 249680 325631a7b72a75d24301ff8f456fba7577119ebd
child 249682 d8c58dd8dabc156c3948a532d4bba47ccacb9977
push id28936
push userryanvm@gmail.com
push dateFri, 19 Jun 2015 20:34:42 +0000
treeherdermozilla-central@c319f262ce3e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs858927
milestone41.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
Bug 858927 - Move the mozilla::TimeStamp into mozglue. r=glandium
js/src/configure.in
mozglue/misc/TimeStamp.cpp
mozglue/misc/TimeStamp.h
mozglue/misc/TimeStamp_darwin.cpp
mozglue/misc/TimeStamp_posix.cpp
mozglue/misc/TimeStamp_windows.cpp
mozglue/misc/TimeStamp_windows.h
mozglue/misc/moz.build
mozglue/moz.build
xpcom/build/NSPRInterposer.cpp
xpcom/ds/TimeStamp.cpp
xpcom/ds/TimeStamp.h
xpcom/ds/TimeStamp_darwin.cpp
xpcom/ds/TimeStamp_posix.cpp
xpcom/ds/TimeStamp_windows.cpp
xpcom/ds/TimeStamp_windows.h
xpcom/ds/moz.build
xpcom/libxpcomrt/moz.build
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2444,16 +2444,38 @@ fi
 
 
 dnl Checks for library functions.
 dnl ========================================================
 AC_PROG_GCC_TRADITIONAL
 AC_FUNC_MEMCMP
 AC_CHECK_FUNCS([getc_unlocked _getc_nolock gmtime_r localtime_r])
 
+dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
+AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
+               ac_cv_clock_monotonic,
+               [for libs in "" -lrt; do
+                    _SAVE_LIBS="$LIBS"
+                    LIBS="$LIBS $libs"
+                    AC_TRY_LINK([#include <time.h>],
+                                 [ struct timespec ts;
+                                   clock_gettime(CLOCK_MONOTONIC, &ts); ],
+                                 ac_cv_clock_monotonic=$libs
+                                 LIBS="$_SAVE_LIBS"
+                                 break,
+                                 ac_cv_clock_monotonic=no)
+                    LIBS="$_SAVE_LIBS"
+                done])
+if test "$ac_cv_clock_monotonic" != "no"; then
+    HAVE_CLOCK_MONOTONIC=1
+    REALTIME_LIBS=$ac_cv_clock_monotonic
+    AC_DEFINE(HAVE_CLOCK_MONOTONIC)
+    AC_SUBST(HAVE_CLOCK_MONOTONIC)
+    AC_SUBST_LIST(REALTIME_LIBS)
+fi
 
 dnl Checks for math functions.
 dnl ========================================================
 AC_CHECK_LIB(m, sin)
 AC_CHECK_FUNCS([log2 log1p expm1 sqrt1pm1 acosh asinh atanh trunc cbrt])
 
 
 dnl check for wcrtomb/mbrtowc
rename from xpcom/ds/TimeStamp.cpp
rename to mozglue/misc/TimeStamp.cpp
--- a/xpcom/ds/TimeStamp.cpp
+++ b/mozglue/misc/TimeStamp.cpp
@@ -4,17 +4,18 @@
  * 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/. */
 
 /*
  * Implementation of the OS-independent methods of the TimeStamp class
  */
 
 #include "mozilla/TimeStamp.h"
-#include "prenv.h"
+#include <stdio.h>
+#include <string.h>
 
 namespace mozilla {
 
 /**
  * Wrapper class used to initialize static data used by the TimeStamp class
  */
 struct TimeStampInitialization
 {
@@ -40,23 +41,23 @@ struct TimeStampInitialization
   ~TimeStampInitialization()
   {
     TimeStamp::Shutdown();
   };
 };
 
 static TimeStampInitialization sInitOnce;
 
-TimeStamp
+MFBT_API TimeStamp
 TimeStamp::ProcessCreation(bool& aIsInconsistent)
 {
   aIsInconsistent = false;
 
   if (sInitOnce.mProcessCreation.IsNull()) {
-    char* mozAppRestart = PR_GetEnv("MOZ_APP_RESTART");
+    char* mozAppRestart = getenv("MOZ_APP_RESTART");
     TimeStamp ts;
 
     /* When calling PR_SetEnv() with an empty value the existing variable may
      * be unset or set to the empty string depending on the underlying platform
      * thus we have to check if the variable is present and not empty. */
     if (mozAppRestart && (strcmp(mozAppRestart, "") != 0)) {
       /* Firefox was restarted, use the first time-stamp we've taken as the new
        * process startup time. */
rename from xpcom/ds/TimeStamp.h
rename to mozglue/misc/TimeStamp.h
--- a/xpcom/ds/TimeStamp.h
+++ b/mozglue/misc/TimeStamp.h
@@ -7,18 +7,17 @@
 #ifndef mozilla_TimeStamp_h
 #define mozilla_TimeStamp_h
 
 #include <stdint.h>
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/TypeTraits.h"
-#include "nscore.h"
-#include "nsDebug.h"
+#include "mozilla/Types.h"
 
 namespace IPC {
 template<typename T> struct ParamTraits;
 }
 
 #ifdef XP_WIN
 // defines TimeStampValue as a complex value keeping both
 // GetTickCount and QueryPerformanceCounter values
@@ -34,20 +33,20 @@ typedef uint64_t TimeStampValue;
 class TimeStamp;
 
 /**
  * Platform-specific implementation details of BaseTimeDuration.
  */
 class BaseTimeDurationPlatformUtils
 {
 public:
-  static double ToSeconds(int64_t aTicks);
-  static double ToSecondsSigDigits(int64_t aTicks);
-  static int64_t TicksFromMilliseconds(double aMilliseconds);
-  static int64_t ResolutionInTicks();
+  static MFBT_API double ToSeconds(int64_t aTicks);
+  static MFBT_API double ToSecondsSigDigits(int64_t aTicks);
+  static MFBT_API int64_t TicksFromMilliseconds(double aMilliseconds);
+  static MFBT_API int64_t ResolutionInTicks();
 };
 
 /**
  * Instances of this class represent the length of an interval of time.
  * Negative durations are allowed, meaning the end is before the start.
  *
  * Internally the duration is stored as a int64_t in units of
  * PR_TicksPerSecond() when building with NSPR interval timers, or a
@@ -201,17 +200,16 @@ public:
   }
   BaseTimeDuration operator*(const int64_t aMultiplier) const
   {
     return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const uint64_t aMultiplier) const
   {
     if (aMultiplier > INT64_MAX) {
-      NS_WARNING("Out-of-range multiplier when multiplying BaseTimeDuration");
       return Forever();
     }
     return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator/(const int64_t aDivisor) const
   {
     MOZ_ASSERT(aDivisor != 0, "Division by zero");
     return FromTicks(ValueCalculator::Divide(mValue, aDivisor));
@@ -423,39 +421,39 @@ public:
    * Now() is trying to ensure the best possible precision on each platform,
    * at least one millisecond.
    *
    * NowLoRes() has been introduced to workaround performance problems of
    * QueryPerformanceCounter on the Windows platform.  NowLoRes() is giving
    * lower precision, usually 15.6 ms, but with very good performance benefit.
    * Use it for measurements of longer times, like >200ms timeouts.
    */
-  static TimeStamp Now() { return Now(true); }
-  static TimeStamp NowLoRes() { return Now(false); }
+  static MFBT_API TimeStamp Now() { return Now(true); }
+  static MFBT_API TimeStamp NowLoRes() { return Now(false); }
 
   /**
    * Return a timestamp representing the time when the current process was
    * created which will be comparable with other timestamps taken with this
    * class. If the actual process creation time is detected to be inconsistent
    * the @a aIsInconsistent parameter will be set to true, the returned
    * timestamp however will still be valid though inaccurate.
    *
    * @param aIsInconsistent Set to true if an inconsistency was detected in the
    * process creation time
    * @returns A timestamp representing the time when the process was created,
    * this timestamp is always valid even when errors are reported
    */
-  static TimeStamp ProcessCreation(bool& aIsInconsistent);
+  static MFBT_API TimeStamp ProcessCreation(bool& aIsInconsistent);
 
   /**
    * Records a process restart. After this call ProcessCreation() will return
    * the time when the browser was restarted instead of the actual time when
    * the process was created.
    */
-  static void RecordProcessRestart();
+  static MFBT_API void RecordProcessRestart();
 
   /**
    * Compute the difference between two timestamps. Both must be non-null.
    */
   TimeDuration operator-(const TimeStamp& aOther) const
   {
     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
@@ -531,36 +529,36 @@ public:
   {
     return !(*this == aOther);
   }
 
   // Comparing TimeStamps for equality should be discouraged. Adding
   // two TimeStamps, or scaling TimeStamps, is nonsense and must never
   // be allowed.
 
-  static nsresult Startup();
-  static void Shutdown();
+  static MFBT_API void Startup();
+  static MFBT_API void Shutdown();
 
 private:
   friend struct IPC::ParamTraits<mozilla::TimeStamp>;
   friend void StartupTimelineRecordExternal(int, uint64_t);
 
   MOZ_IMPLICIT TimeStamp(TimeStampValue aValue) : mValue(aValue) {}
 
-  static TimeStamp Now(bool aHighResolution);
+  static MFBT_API TimeStamp Now(bool aHighResolution);
 
   /**
    * Computes the uptime of the current process in microseconds. The result
    * is platform-dependent and needs to be checked against existing timestamps
    * for consistency.
    *
    * @returns The number of microseconds since the calling process was started
    *          or 0 if an error was encountered while computing the uptime
    */
-  static uint64_t ComputeProcessUptime();
+  static MFBT_API uint64_t ComputeProcessUptime();
 
   /**
    * When built with PRIntervalTime, a value of 0 means this instance
    * is "null". Otherwise, the low 32 bits represent a PRIntervalTime,
    * and the high 32 bits represent a counter of the number of
    * rollovers of PRIntervalTime that we've seen. This counter starts
    * at 1 to avoid a real time colliding with the "null" value.
    *
rename from xpcom/ds/TimeStamp_darwin.cpp
rename to mozglue/misc/TimeStamp_darwin.cpp
--- a/xpcom/ds/TimeStamp_darwin.cpp
+++ b/mozglue/misc/TimeStamp_darwin.cpp
@@ -18,17 +18,16 @@
 
 #include <mach/mach_time.h>
 #include <sys/time.h>
 #include <sys/sysctl.h>
 #include <time.h>
 #include <unistd.h>
 
 #include "mozilla/TimeStamp.h"
-#include "nsDebug.h"
 
 // Estimate of the smallest duration of time we can measure.
 static uint64_t sResolution;
 static uint64_t sResolutionSigDigs;
 
 static const uint64_t kNsPerMs   =    1000000;
 static const uint64_t kUsPerSec  =    1000000;
 static const double kNsPerMsd    =    1000000.0;
@@ -115,46 +114,46 @@ BaseTimeDurationPlatformUtils::TicksFrom
 
 int64_t
 BaseTimeDurationPlatformUtils::ResolutionInTicks()
 {
   MOZ_ASSERT(gInitialized, "calling TimeDuration too early");
   return static_cast<int64_t>(sResolution);
 }
 
-nsresult
+void
 TimeStamp::Startup()
 {
   if (gInitialized) {
-    return NS_OK;
+    return;
   }
 
   mach_timebase_info_data_t timebaseInfo;
   // Apple's QA1398 suggests that the output from mach_timebase_info
   // will not change while a program is running, so it should be safe
   // to cache the result.
   kern_return_t kr = mach_timebase_info(&timebaseInfo);
   if (kr != KERN_SUCCESS) {
-    NS_RUNTIMEABORT("mach_timebase_info failed");
+    MOZ_RELEASE_ASSERT(false, "mach_timebase_info failed");
   }
 
   sNsPerTick = double(timebaseInfo.numer) / timebaseInfo.denom;
 
   sResolution = ClockResolutionNs();
 
   // find the number of significant digits in sResolution, for the
   // sake of ToSecondsSigDigits()
   for (sResolutionSigDigs = 1;
        !(sResolutionSigDigs == sResolution ||
          10 * sResolutionSigDigs > sResolution);
        sResolutionSigDigs *= 10);
 
   gInitialized = true;
 
-  return NS_OK;
+  return;
 }
 
 void
 TimeStamp::Shutdown()
 {
 }
 
 TimeStamp
rename from xpcom/ds/TimeStamp_posix.cpp
rename to mozglue/misc/TimeStamp_posix.cpp
--- a/xpcom/ds/TimeStamp_posix.cpp
+++ b/mozglue/misc/TimeStamp_posix.cpp
@@ -43,20 +43,17 @@
 #define KP_START_USEC ki_start.tv_usec
 #else
 #define KP_START_SEC p_ustart_sec
 #define KP_START_USEC p_ustart_usec
 #endif
 
 #include "mozilla/Snprintf.h"
 #include "mozilla/TimeStamp.h"
-#include "nsCRT.h"
-#include "prprf.h"
-#include "prthread.h"
-#include "nsDebug.h"
+#include <pthread.h>
 
 // Estimate of the smallest duration of time we can measure.
 static uint64_t sResolution;
 static uint64_t sResolutionSigDigs;
 
 static const uint16_t kNsPerUs   =       1000;
 static const uint64_t kNsPerMs   =    1000000;
 static const uint64_t kNsPerSec  = 1000000000;
@@ -166,40 +163,40 @@ BaseTimeDurationPlatformUtils::TicksFrom
 int64_t
 BaseTimeDurationPlatformUtils::ResolutionInTicks()
 {
   return static_cast<int64_t>(sResolution);
 }
 
 static bool gInitialized = false;
 
-nsresult
+void
 TimeStamp::Startup()
 {
   if (gInitialized) {
-    return NS_OK;
+    return;
   }
 
   struct timespec dummy;
   if (clock_gettime(CLOCK_MONOTONIC, &dummy) != 0) {
-    NS_RUNTIMEABORT("CLOCK_MONOTONIC is absent!");
+    MOZ_CRASH("CLOCK_MONOTONIC is absent!");
   }
 
   sResolution = ClockResolutionNs();
 
   // find the number of significant digits in sResolution, for the
   // sake of ToSecondsSigDigits()
   for (sResolutionSigDigs = 1;
        !(sResolutionSigDigs == sResolution ||
          10 * sResolutionSigDigs > sResolution);
        sResolutionSigDigs *= 10);
 
   gInitialized = true;
 
-  return NS_OK;
+  return;
 }
 
 void
 TimeStamp::Shutdown()
 {
 }
 
 TimeStamp
@@ -254,57 +251,57 @@ JiffiesSinceBoot(const char* aFile)
 }
 
 // Computes the interval that has elapsed between the thread creation and the
 // process creation by comparing the starttime fields in the respective
 // /proc/*/stat files. The resulting value will be a good approximation of the
 // process uptime. This value will be stored at the address pointed by aTime;
 // if an error occurred 0 will be stored instead.
 
-static void
+static void*
 ComputeProcessUptimeThread(void* aTime)
 {
   uint64_t* uptime = static_cast<uint64_t*>(aTime);
   long hz = sysconf(_SC_CLK_TCK);
 
   *uptime = 0;
 
   if (!hz) {
-    return;
+    return nullptr;
   }
 
   char threadStat[40];
   snprintf_literal(threadStat, "/proc/self/task/%d/stat", (pid_t)syscall(__NR_gettid));
 
   uint64_t threadJiffies = JiffiesSinceBoot(threadStat);
   uint64_t selfJiffies = JiffiesSinceBoot("/proc/self/stat");
 
   if (!threadJiffies || !selfJiffies) {
-    return;
+    return nullptr;
   }
 
   *uptime = ((threadJiffies - selfJiffies) * kNsPerSec) / hz;
+  return nullptr;
 }
 
 // Computes and returns the process uptime in us on Linux & its derivatives.
 // Returns 0 if an error was encountered.
 
 uint64_t
 TimeStamp::ComputeProcessUptime()
 {
   uint64_t uptime = 0;
-  PRThread* thread = PR_CreateThread(PR_USER_THREAD,
-                                     ComputeProcessUptimeThread,
-                                     &uptime,
-                                     PR_PRIORITY_NORMAL,
-                                     PR_GLOBAL_THREAD,
-                                     PR_JOINABLE_THREAD,
-                                     0);
+  pthread_t uptime_pthread;
 
-  PR_JoinThread(thread);
+  if (pthread_create(&uptime_pthread, nullptr, ComputeProcessUptimeThread, &uptime)) {
+    MOZ_CRASH("Failed to create process uptime thread.");
+    return 0;
+  }
+
+  pthread_join(uptime_pthread, NULL);
 
   return uptime / kNsPerUs;
 }
 
 #elif defined(__DragonFly__) || defined(__FreeBSD__) \
       || defined(__NetBSD__) || defined(__OpenBSD__)
 
 // Computes and returns the process uptime in us on various BSD flavors.
rename from xpcom/ds/TimeStamp_windows.cpp
rename to mozglue/misc/TimeStamp_windows.cpp
--- a/xpcom/ds/TimeStamp_windows.cpp
+++ b/mozglue/misc/TimeStamp_windows.cpp
@@ -3,47 +3,40 @@
 /* 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/. */
 
 // Implement TimeStamp::Now() with QueryPerformanceCounter() controlled with
 // values of GetTickCount().
 
 #include "mozilla/MathAlgorithms.h"
-#include "mozilla/Mutex.h"
 #include "mozilla/TimeStamp.h"
-#include "nsWindowsHelpers.h"
+
+#include <stdio.h>
+#include <intrin.h>
 #include <windows.h>
 
-#include "nsCRT.h"
-#include "mozilla/Logging.h"
-#include "prprf.h"
-#include <stdio.h>
-
-#include <intrin.h>
+// To enable logging define to your favorite logging API
+#define LOG(x)
 
-// Log module for mozilla::TimeStamp for Windows logging...
-//
-// To enable logging (see prlog.h for full details):
-//
-//    set NSPR_LOG_MODULES=TimeStampWindows:5
-//    set NSPR_LOG_FILE=nspr.log
-//
-// this enables LogLevel::Debug level information and places all output in
-// the file nspr.log
-static PRLogModuleInfo*
-GetTimeStampLog()
+class AutoCriticalSection
 {
-  static PRLogModuleInfo* sLog;
-  if (!sLog) {
-    sLog = PR_NewLogModule("TimeStampWindows");
+public:
+  AutoCriticalSection(LPCRITICAL_SECTION aSection)
+    : mSection(aSection)
+  {
+    ::EnterCriticalSection(mSection);
   }
-  return sLog;
-}
-#define LOG(x)  MOZ_LOG(GetTimeStampLog(), mozilla::LogLevel::Debug, x)
+  ~AutoCriticalSection()
+  {
+    ::LeaveCriticalSection(mSection);
+  }
+private:
+  LPCRITICAL_SECTION mSection;
+};
 
 // Estimate of the smallest duration of time we can measure.
 static volatile ULONGLONG sResolution;
 static volatile ULONGLONG sResolutionSigDigs;
 static const double   kNsPerSecd  = 1000000000.0;
 static const LONGLONG kNsPerSec   = 1000000000;
 static const LONGLONG kNsPerMillisec = 1000000;
 
@@ -288,44 +281,44 @@ InitResolution()
        sigDigs *= 10);
 
   sResolutionSigDigs = sigDigs;
 }
 
 // ----------------------------------------------------------------------------
 // TimeStampValue implementation
 // ----------------------------------------------------------------------------
-
+MFBT_API
 TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC)
   : mGTC(aGTC)
   , mQPC(aQPC)
   , mHasQPC(aHasQPC)
   , mIsNull(false)
 {
 }
 
-TimeStampValue&
+MFBT_API TimeStampValue&
 TimeStampValue::operator+=(const int64_t aOther)
 {
   mGTC += aOther;
   mQPC += aOther;
   return *this;
 }
 
-TimeStampValue&
+MFBT_API TimeStampValue&
 TimeStampValue::operator-=(const int64_t aOther)
 {
   mGTC -= aOther;
   mQPC -= aOther;
   return *this;
 }
 
 // If the duration is less then two seconds, perform check of QPC stability
 // by comparing both GTC and QPC calculated durations of this and aOther.
-uint64_t
+MFBT_API uint64_t
 TimeStampValue::CheckQPC(const TimeStampValue& aOther) const
 {
   uint64_t deltaGTC = mGTC - aOther.mGTC;
 
   if (!mHasQPC || !aOther.mHasQPC) { // Both not holding QPC
     return deltaGTC;
   }
 
@@ -389,63 +382,63 @@ TimeStampValue::CheckQPC(const TimeStamp
       sFaultIntoleranceCheckpoint = now + sFailureFreeInterval;
       LOG(("TimeStamp: recording 1st QPC failure"));
     }
   }
 
   return deltaGTC;
 }
 
-uint64_t
+MFBT_API uint64_t
 TimeStampValue::operator-(const TimeStampValue& aOther) const
 {
   if (mIsNull && aOther.mIsNull) {
     return uint64_t(0);
   }
 
   return CheckQPC(aOther);
 }
 
 // ----------------------------------------------------------------------------
 // TimeDuration and TimeStamp implementation
 // ----------------------------------------------------------------------------
 
-double
+MFBT_API double
 BaseTimeDurationPlatformUtils::ToSeconds(int64_t aTicks)
 {
   // Converting before arithmetic avoids blocked store forward
   return double(aTicks) / (double(sFrequencyPerSec) * 1000.0);
 }
 
-double
+MFBT_API double
 BaseTimeDurationPlatformUtils::ToSecondsSigDigits(int64_t aTicks)
 {
   // don't report a value < mResolution ...
   LONGLONG resolution = sResolution;
   LONGLONG resolutionSigDigs = sResolutionSigDigs;
   LONGLONG valueSigDigs = resolution * (aTicks / resolution);
   // and chop off insignificant digits
   valueSigDigs = resolutionSigDigs * (valueSigDigs / resolutionSigDigs);
   return double(valueSigDigs) / kNsPerSecd;
 }
 
-int64_t
+MFBT_API int64_t
 BaseTimeDurationPlatformUtils::TicksFromMilliseconds(double aMilliseconds)
 {
   double result = ms2mt(aMilliseconds);
   if (result > INT64_MAX) {
     return INT64_MAX;
   } else if (result < INT64_MIN) {
     return INT64_MIN;
   }
 
   return result;
 }
 
-int64_t
+MFBT_API int64_t
 BaseTimeDurationPlatformUtils::ResolutionInTicks()
 {
   return static_cast<int64_t>(sResolution);
 }
 
 static bool
 HasStableTSC()
 {
@@ -477,17 +470,17 @@ HasStableTSC()
   }
 
   __cpuid(regs, 0x80000007);
   // if bit 8 is set than TSC will run at a constant rate
   // in all ACPI P-state, C-states and T-states
   return regs[3] & (1 << 8);
 }
 
-nsresult
+MFBT_API void
 TimeStamp::Startup()
 {
   // Decide which implementation to use for the high-performance timer.
 
   HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll");
   sGetTickCount64 = reinterpret_cast<GetTickCount64_t>(
     GetProcAddress(kernelDLL, "GetTickCount64"));
   if (!sGetTickCount64) {
@@ -503,50 +496,50 @@ TimeStamp::Startup()
 
   LARGE_INTEGER freq;
   sUseQPC = ::QueryPerformanceFrequency(&freq);
   if (!sUseQPC) {
     // No Performance Counter.  Fall back to use GetTickCount.
     InitResolution();
 
     LOG(("TimeStamp: using GetTickCount"));
-    return NS_OK;
+    return;
   }
 
   sFrequencyPerSec = freq.QuadPart;
   LOG(("TimeStamp: QPC frequency=%llu", sFrequencyPerSec));
 
   InitThresholds();
   InitResolution();
 
-  return NS_OK;
+  return;
 }
 
-void
+MFBT_API void
 TimeStamp::Shutdown()
 {
   DeleteCriticalSection(&sTimeStampLock);
 }
 
-TimeStamp
+MFBT_API TimeStamp
 TimeStamp::Now(bool aHighResolution)
 {
   // sUseQPC is volatile
   bool useQPC = (aHighResolution && sUseQPC);
 
   // Both values are in [mt] units.
   ULONGLONG QPC = useQPC ? PerformanceCounter() : uint64_t(0);
   ULONGLONG GTC = ms2mt(sGetTickCount64());
   return TimeStamp(TimeStampValue(GTC, QPC, useQPC));
 }
 
 // Computes and returns the process uptime in microseconds.
 // Returns 0 if an error was encountered.
 
-uint64_t
+MFBT_API uint64_t
 TimeStamp::ComputeProcessUptime()
 {
   SYSTEMTIME nowSys;
   GetSystemTime(&nowSys);
 
   FILETIME now;
   bool success = SystemTimeToFileTime(&nowSys, &now);
 
rename from xpcom/ds/TimeStamp_windows.h
rename to mozglue/misc/TimeStamp_windows.h
--- a/xpcom/ds/TimeStamp_windows.h
+++ b/mozglue/misc/TimeStamp_windows.h
@@ -2,58 +2,60 @@
 /* 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_TimeStamp_windows_h
 #define mozilla_TimeStamp_windows_h
 
+#include "mozilla/Types.h"
+
 namespace mozilla {
 
 class TimeStamp;
 
 class TimeStampValue
 {
   friend struct IPC::ParamTraits<mozilla::TimeStampValue>;
   friend class TimeStamp;
   friend void StartupTimelineRecordExternal(int, uint64_t);
 
   // Both QPC and GTC are kept in [mt] units.
   uint64_t mGTC;
   uint64_t mQPC;
   bool mHasQPC;
   bool mIsNull;
 
-  TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC);
+  MFBT_API TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC);
 
-  uint64_t CheckQPC(const TimeStampValue& aOther) const;
+  MFBT_API uint64_t CheckQPC(const TimeStampValue& aOther) const;
 
   struct _SomethingVeryRandomHere;
   MOZ_CONSTEXPR TimeStampValue(_SomethingVeryRandomHere* aNullValue)
     : mGTC(0)
     , mQPC(0)
     , mHasQPC(false)
     , mIsNull(true)
   {
   }
 
 public:
-  uint64_t operator-(const TimeStampValue& aOther) const;
+  MFBT_API uint64_t operator-(const TimeStampValue& aOther) const;
 
   TimeStampValue operator+(const int64_t aOther) const
   {
     return TimeStampValue(mGTC + aOther, mQPC + aOther, mHasQPC);
   }
   TimeStampValue operator-(const int64_t aOther) const
   {
     return TimeStampValue(mGTC - aOther, mQPC - aOther, mHasQPC);
   }
-  TimeStampValue& operator+=(const int64_t aOther);
-  TimeStampValue& operator-=(const int64_t aOther);
+  MFBT_API TimeStampValue& operator+=(const int64_t aOther);
+  MFBT_API TimeStampValue& operator-=(const int64_t aOther);
 
   bool operator<(const TimeStampValue& aOther) const
   {
     return int64_t(*this - aOther) < 0;
   }
   bool operator>(const TimeStampValue& aOther) const
   {
     return int64_t(*this - aOther) > 0;
new file mode 100644
--- /dev/null
+++ b/mozglue/misc/moz.build
@@ -0,0 +1,35 @@
+FINAL_LIBRARY = 'mozglue'
+
+EXPORTS.mozilla += [
+    'TimeStamp.h',
+]
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+    EXPORTS.mozilla += [
+        'TimeStamp_windows.h',
+    ]
+
+SOURCES += [
+    'TimeStamp.cpp',
+]
+
+OS_LIBS += CONFIG['REALTIME_LIBS']
+
+DEFINES['IMPL_MFBT'] = True
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+    SOURCES += [
+        'TimeStamp_windows.cpp',
+    ]
+elif CONFIG['HAVE_CLOCK_MONOTONIC']:
+    SOURCES += [
+        'TimeStamp_posix.cpp',
+    ]
+elif CONFIG['OS_ARCH'] == 'Darwin':
+    SOURCES += [
+        'TimeStamp_darwin.cpp',
+    ]
+elif CONFIG['COMPILE_ENVIRONMENT']:
+    error('No TimeStamp implementation on this platform.  Build will not succeed')
+
+FAIL_ON_WARNINGS = True
--- a/mozglue/moz.build
+++ b/mozglue/moz.build
@@ -5,15 +5,18 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['MOZ_LINKER']:
     DIRS += ['linker']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     DIRS += ['android']
 
-DIRS += ['build']
+DIRS += [
+  'build',
+  'misc',
+]
 
 if CONFIG['MOZ_CRT']:
     DIRS += ['crt']
 
 if not CONFIG['JS_STANDALONE']:
     TEST_DIRS += ['tests']
--- a/xpcom/build/NSPRInterposer.cpp
+++ b/xpcom/build/NSPRInterposer.cpp
@@ -4,16 +4,18 @@
  * 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 "IOInterposer.h"
 #include "NSPRInterposer.h"
 
 #include "prio.h"
 #include "private/pprio.h"
+#include "nsDebug.h"
+#include "nscore.h"
 
 namespace {
 
 using namespace mozilla;
 
 /* Original IO methods */
 PRCloseFN sCloseFn = nullptr;
 PRReadFN  sReadFn  = nullptr;
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -31,17 +31,16 @@ XPIDL_SOURCES += [
     'nsIWritablePropertyBag2.idl',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     XPIDL_SOURCES += [
         'nsIWindowsRegKey.idl',
     ]
     EXPORTS += ['nsWindowsRegKey.h']
-    EXPORTS.mozilla += ['TimeStamp_windows.h']
     SOURCES += [
         'nsWindowsRegKey.cpp'
     ]
 
 XPIDL_MODULE = 'xpcom_ds'
 
 EXPORTS += [
     'nsArray.h',
@@ -58,17 +57,16 @@ EXPORTS += [
     'nsSupportsArray.h',
     'nsSupportsPrimitives.h',
     'nsVariant.h',
     'nsWhitespaceTokenizer.h',
 ]
 
 EXPORTS.mozilla += [
     'StickyTimeDuration.h',
-    'TimeStamp.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsArray.cpp',
     'nsAtomService.cpp',
     'nsAtomTable.cpp',
     'nsCRT.cpp',
     'nsHashPropertyBag.cpp',
@@ -76,41 +74,25 @@ UNIFIED_SOURCES += [
     'nsObserverList.cpp',
     'nsObserverService.cpp',
     'nsProperties.cpp',
     'nsStringEnumerator.cpp',
     'nsSupportsArray.cpp',
     'nsSupportsArrayEnumerator.cpp',
     'nsSupportsPrimitives.cpp',
     'nsVariant.cpp',
-    'TimeStamp.cpp',
 ]
 
 # These two files cannot be built in unified mode because they use the
 # PL_ARENA_CONST_ALIGN_MASK macro with plarena.h.
 SOURCES += [
     'nsPersistentProperties.cpp',
     'nsStaticNameTable.cpp',
 ]
 
-if CONFIG['OS_ARCH'] == 'WINNT':
-    SOURCES += [
-        'TimeStamp_windows.cpp',
-    ]
-elif CONFIG['HAVE_CLOCK_MONOTONIC']:
-    SOURCES += [
-        'TimeStamp_posix.cpp',
-    ]
-elif CONFIG['OS_ARCH'] == 'Darwin':
-    SOURCES += [
-        'TimeStamp_darwin.cpp',
-    ]
-elif CONFIG['COMPILE_ENVIRONMENT']:
-    error('No TimeStamp implementation on this platform.  Build will not succeed')
-
 EXTRA_COMPONENTS += [
     'nsINIProcessor.js',
     'nsINIProcessor.manifest',
 ]
 
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
--- a/xpcom/libxpcomrt/moz.build
+++ b/xpcom/libxpcomrt/moz.build
@@ -38,30 +38,17 @@ src_list += [
 ]
 
 xpcom_ds_src = [
     'nsObserverList.cpp',
     'nsObserverService.cpp',
     'nsStringEnumerator.cpp',
     'nsSupportsPrimitives.cpp',
 ]
-if CONFIG['OS_ARCH'] == 'WINNT':
-    xpcom_ds_src += [
-        'TimeStamp_windows.cpp',
-    ]
-elif CONFIG['HAVE_CLOCK_MONOTONIC']:
-    xpcom_ds_src += [
-        'TimeStamp_posix.cpp',
-    ]
-elif CONFIG['OS_ARCH'] == 'Darwin':
-    xpcom_ds_src += [
-        'TimeStamp_darwin.cpp',
-    ]
-elif CONFIG['COMPILE_ENVIRONMENT']:
-    error('No TimeStamp implementation on this platform.  Build will not succeed')
+
 src_list += [
     '/xpcom/ds/%s' % s for s in xpcom_ds_src
 ]
 
 xpcom_glue_src = [
     'BlockingResourceBase.cpp',
     'nsArrayEnumerator.cpp',
     'nsClassInfoImpl.cpp',