Bug 1324434 - remove JS_GetCurrentEmbedderTime in favor of TimeStamp; r?sfink draft
authorTom Tromey <tom@tromey.com>
Mon, 19 Dec 2016 08:23:59 -0700
changeset 469738 4e57810dd52924a32eb9aa904aa58432e8d0718d
parent 469617 823dc40ab5fe45344a611ff454212f8cf56e1435
child 544287 e3863300ec4facb93ca93f76258de6b44a3618e4
push id43824
push userbmo:ttromey@mozilla.com
push dateThu, 02 Feb 2017 17:59:28 +0000
reviewerssfink
bugs1324434
milestone54.0a1
Bug 1324434 - remove JS_GetCurrentEmbedderTime in favor of TimeStamp; r?sfink MozReview-Commit-ID: CG0MidpH8k3
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/debug/Memory-drainAllocationsLog-14.js
js/src/jsapi.cpp
js/src/jsapi.h
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
js/src/vm/DebuggerMemory.cpp
js/src/vm/SavedStacks.cpp
xpcom/build/XPCOMInit.cpp
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -4203,16 +4203,27 @@ AflLoop(JSContext* cx, unsigned argc, Va
     if (!ToUint32(cx, args.get(0), &max_cnt))
         return false;
 
     args.rval().setBoolean(!!__AFL_LOOP(max_cnt));
     return true;
 }
 #endif
 
+static bool
+TimeSinceCreation(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    bool ignore;
+    double when = (mozilla::TimeStamp::Now()
+                   - mozilla::TimeStamp::ProcessCreation(ignore)).ToMilliseconds();
+    args.rval().setNumber(when);
+    return true;
+}
+
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'zone' [, 'shrinking'])",
 "  Run the garbage collector. When obj is given, GC only its zone.\n"
 "  If 'zone' is given, GC any zones that were scheduled for\n"
 "  GC via schedulegc.\n"
 "  If 'shrinking' is passed as the optional second argument, perform a\n"
 "  shrinking GC rather than a normal GC."),
@@ -4748,16 +4759,21 @@ gc::ZealModeHelpText),
 "  Disables the deprecated, non-standard for-each.\n"),
 
 #if defined(FUZZING) && defined(__AFL_COMPILER)
     JS_FN_HELP("aflloop", AflLoop, 1, 0,
 "aflloop(max_cnt)",
 "  Call the __AFL_LOOP() runtime function (see AFL docs)\n"),
 #endif
 
+    JS_FN_HELP("timeSinceCreation", TimeSinceCreation, 0, 0,
+"TimeSinceCreation()",
+"  Returns the time in milliseconds since process creation.\n"
+"  This uses a clock compatible with the profiler.\n"),
+
     JS_FS_HELP_END
 };
 
 static const JSFunctionSpecWithHelp FuzzingUnsafeTestingFunctions[] = {
 #ifdef DEBUG
     JS_FN_HELP("parseRegExp", ParseRegExp, 3, 0,
 "parseRegExp(pattern[, flags[, match_only])",
 "  Parses a RegExp pattern and returns a tree, potentially throwing."),
--- a/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-14.js
+++ b/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-14.js
@@ -1,28 +1,28 @@
 // Test that drainAllocationsLog returns some timestamps.
 
 load(libdir + 'asserts.js');
 
 var allocTimes = [];
 
-allocTimes.push(dateNow());
+allocTimes.push(timeSinceCreation());
 
 const root = newGlobal();
 const dbg = new Debugger(root);
 
 dbg.memory.trackingAllocationSites = true;
 root.eval("this.alloc1 = {}");
-allocTimes.push(dateNow());
+allocTimes.push(timeSinceCreation());
 root.eval("this.alloc2 = {}");
-allocTimes.push(dateNow());
+allocTimes.push(timeSinceCreation());
 root.eval("this.alloc3 = {}");
-allocTimes.push(dateNow());
+allocTimes.push(timeSinceCreation());
 root.eval("this.alloc4 = {}");
-allocTimes.push(dateNow());
+allocTimes.push(timeSinceCreation());
 
 allocs = dbg.memory.drainAllocationsLog();
 assertEq(allocs.length >= 4, true);
 assertEq(allocs[0].timestamp >= allocTimes[0], true);
 var seenAlloc = 0;
 var lastIndexSeenAllocIncremented = 0;
 for (i = 1; i < allocs.length; ++i) {
     assertEq(allocs[i].timestamp >= allocs[i - 1].timestamp, true);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -481,32 +481,16 @@ JS_NewContext(uint32_t maxbytes, uint32_
 }
 
 JS_PUBLIC_API(void)
 JS_DestroyContext(JSContext* cx)
 {
     DestroyContext(cx);
 }
 
-static JS_CurrentEmbedderTimeFunction currentEmbedderTimeFunction;
-
-JS_PUBLIC_API(void)
-JS_SetCurrentEmbedderTimeFunction(JS_CurrentEmbedderTimeFunction timeFn)
-{
-    currentEmbedderTimeFunction = timeFn;
-}
-
-JS_PUBLIC_API(double)
-JS_GetCurrentEmbedderTime()
-{
-    if (currentEmbedderTimeFunction)
-        return currentEmbedderTimeFunction();
-    return PRMJ_Now() / static_cast<double>(PRMJ_USEC_PER_MSEC);
-}
-
 JS_PUBLIC_API(void*)
 JS_GetContextPrivate(JSContext* cx)
 {
     return cx->data;
 }
 
 JS_PUBLIC_API(void)
 JS_SetContextPrivate(JSContext* cx, void* data)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -999,35 +999,16 @@ JS_IsBuiltinFunctionConstructor(JSFuncti
 extern JS_PUBLIC_API(JSContext*)
 JS_NewContext(uint32_t maxbytes,
               uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
               JSContext* parentContext = nullptr);
 
 extern JS_PUBLIC_API(void)
 JS_DestroyContext(JSContext* cx);
 
-typedef double (*JS_CurrentEmbedderTimeFunction)();
-
-/**
- * The embedding can specify a time function that will be used in some
- * situations.  The function can return the time however it likes; but
- * the norm is to return times in units of milliseconds since an
- * arbitrary, but consistent, epoch.  If the time function is not set,
- * a built-in default will be used.
- */
-JS_PUBLIC_API(void)
-JS_SetCurrentEmbedderTimeFunction(JS_CurrentEmbedderTimeFunction timeFn);
-
-/**
- * Return the time as computed using the current time function, or a
- * suitable default if one has not been set.
- */
-JS_PUBLIC_API(double)
-JS_GetCurrentEmbedderTime();
-
 JS_PUBLIC_API(void*)
 JS_GetContextPrivate(JSContext* cx);
 
 JS_PUBLIC_API(void)
 JS_SetContextPrivate(JSContext* cx, void* data);
 
 extern JS_PUBLIC_API(JSContext*)
 JS_GetParentContext(JSContext* cx);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2242,17 +2242,17 @@ Debugger::slowPathOnNewGlobalObject(JSCo
                 break;
         }
     }
     MOZ_ASSERT(!cx->isExceptionPending());
 }
 
 /* static */ bool
 Debugger::slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
-                                      double when, GlobalObject::DebuggerVector& dbgs)
+                                      mozilla::TimeStamp when, GlobalObject::DebuggerVector& dbgs)
 {
     MOZ_ASSERT(!dbgs.empty());
     mozilla::DebugOnly<ReadBarriered<Debugger*>*> begin = dbgs.begin();
 
     // Root all the Debuggers while we're iterating over them;
     // appendAllocationSite calls JSCompartment::wrap, and thus can GC.
     //
     // SpiderMonkey protocol is generally for the caller to prove that it has
@@ -2285,17 +2285,17 @@ bool
 Debugger::isDebuggeeUnbarriered(const JSCompartment* compartment) const
 {
     MOZ_ASSERT(compartment);
     return compartment->isDebuggee() && debuggees.has(compartment->unsafeUnbarrieredMaybeGlobal());
 }
 
 bool
 Debugger::appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
-                               double when)
+                               mozilla::TimeStamp when)
 {
     MOZ_ASSERT(trackingAllocationSites && enabled);
 
     AutoCompartment ac(cx, object);
     RootedObject wrappedFrame(cx, frame);
     if (!cx->compartment()->wrap(cx, &wrappedFrame))
         return false;
 
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_Debugger_h
 #define vm_Debugger_h
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/Range.h"
+#include "mozilla/TimeStamp.h"
 #include "mozilla/Vector.h"
 
 #include "jsclist.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsweakmap.h"
 #include "jswrapper.h"
 
@@ -337,30 +338,30 @@ class Debugger : private mozilla::Linked
     bool isEnabled() const {
         return enabled;
     }
 
     static SavedFrame* getObjectAllocationSite(JSObject& obj);
 
     struct AllocationsLogEntry
     {
-        AllocationsLogEntry(HandleObject frame, double when, const char* className,
+        AllocationsLogEntry(HandleObject frame, mozilla::TimeStamp when, const char* className,
                             HandleAtom ctorName, size_t size, bool inNursery)
             : frame(frame),
               when(when),
               className(className),
               ctorName(ctorName),
               size(size),
               inNursery(inNursery)
         {
             MOZ_ASSERT_IF(frame, UncheckedUnwrap(frame)->is<SavedFrame>());
         };
 
         HeapPtr<JSObject*> frame;
-        double when;
+        mozilla::TimeStamp when;
         const char* className;
         HeapPtr<JSAtom*> ctorName;
         size_t size;
         bool inNursery;
 
         void trace(JSTracer* trc) {
             TraceNullableEdge(trc, &frame, "Debugger::AllocationsLogEntry::frame");
             TraceNullableEdge(trc, &ctorName, "Debugger::AllocationsLogEntry::ctorName");
@@ -397,17 +398,17 @@ class Debugger : private mozilla::Linked
     bool trackingAllocationSites;
     double allocationSamplingProbability;
     size_t maxAllocationsLogLength;
     bool allocationsLogOverflowed;
 
     static const size_t DEFAULT_MAX_LOG_LENGTH = 5000;
 
     MOZ_MUST_USE bool appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
-                                           double when);
+                                           mozilla::TimeStamp when);
 
     /*
      * Recompute the set of debuggee zones based on the set of debuggee globals.
      */
     void recomputeDebuggeeZoneSet();
 
     /*
      * Return true if there is an existing object metadata callback for the
@@ -708,17 +709,18 @@ class Debugger : private mozilla::Linked
     static MOZ_MUST_USE bool slowPathOnLeaveFrame(JSContext* cx, AbstractFramePtr frame,
                                                   jsbytecode* pc, bool ok);
     static JSTrapStatus slowPathOnDebuggerStatement(JSContext* cx, AbstractFramePtr frame);
     static JSTrapStatus slowPathOnExceptionUnwind(JSContext* cx, AbstractFramePtr frame);
     static void slowPathOnNewScript(JSContext* cx, HandleScript script);
     static void slowPathOnNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance);
     static void slowPathOnNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global);
     static MOZ_MUST_USE bool slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj,
-                                                         HandleSavedFrame frame, double when,
+                                                         HandleSavedFrame frame,
+                                                         mozilla::TimeStamp when,
                                                          GlobalObject::DebuggerVector& dbgs);
     static void slowPathPromiseHook(JSContext* cx, Hook hook, HandleObject promise);
 
     template <typename HookIsEnabledFun /* bool (Debugger*) */,
               typename FireHookFun /* JSTrapStatus (Debugger*) */>
     static JSTrapStatus dispatchHook(JSContext* cx, HookIsEnabledFun hookIsEnabled,
                                      FireHookFun fireHook);
 
@@ -895,17 +897,17 @@ class Debugger : private mozilla::Linked
      */
     static inline MOZ_MUST_USE bool onLeaveFrame(JSContext* cx, AbstractFramePtr frame,
                                                  jsbytecode* pc, bool ok);
 
     static inline void onNewScript(JSContext* cx, HandleScript script);
     static inline void onNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance);
     static inline void onNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global);
     static inline MOZ_MUST_USE bool onLogAllocationSite(JSContext* cx, JSObject* obj,
-                                                        HandleSavedFrame frame, double when);
+                                                        HandleSavedFrame frame, mozilla::TimeStamp when);
     static JSTrapStatus onTrap(JSContext* cx, MutableHandleValue vp);
     static JSTrapStatus onSingleStep(JSContext* cx, MutableHandleValue vp);
     static MOZ_MUST_USE bool handleBaselineOsr(JSContext* cx, InterpreterFrame* from,
                                                jit::BaselineFrame* to);
     static MOZ_MUST_USE bool handleIonBailout(JSContext* cx, jit::RematerializedFrame* from,
                                               jit::BaselineFrame* to);
     static void handleUnrecoverableIonBailoutError(JSContext* cx, jit::RematerializedFrame* frame);
     static void propagateForcedReturn(JSContext* cx, AbstractFramePtr frame, HandleValue rval);
@@ -1755,17 +1757,17 @@ Debugger::onNewGlobalObject(JSContext* c
 #ifdef DEBUG
     global->compartment()->firedOnNewGlobalObject = true;
 #endif
     if (!JS_CLIST_IS_EMPTY(&cx->runtime()->onNewGlobalObjectWatchers))
         Debugger::slowPathOnNewGlobalObject(cx, global);
 }
 
 /* static */ bool
-Debugger::onLogAllocationSite(JSContext* cx, JSObject* obj, HandleSavedFrame frame, double when)
+Debugger::onLogAllocationSite(JSContext* cx, JSObject* obj, HandleSavedFrame frame, mozilla::TimeStamp when)
 {
     GlobalObject::DebuggerVector* dbgs = cx->global()->getDebuggers();
     if (!dbgs || dbgs->empty())
         return true;
     RootedObject hobj(cx, obj);
     return Debugger::slowPathOnLogAllocationSite(cx, hobj, frame, when, *dbgs);
 }
 
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -201,17 +201,19 @@ DebuggerMemory::drainAllocationsLog(JSCo
         // we must edit them with great care. Use the queue entry in place, and
         // then pop and delete together.
         Debugger::AllocationsLogEntry& entry = dbg->allocationsLog.front();
 
         RootedValue frame(cx, ObjectOrNullValue(entry.frame));
         if (!DefineProperty(cx, obj, cx->names().frame, frame))
             return false;
 
-        RootedValue timestampValue(cx, NumberValue(entry.when));
+        bool ignore;
+        double when = (entry.when - mozilla::TimeStamp::ProcessCreation(ignore)).ToMilliseconds();
+        RootedValue timestampValue(cx, NumberValue(when));
         if (!DefineProperty(cx, obj, cx->names().timestamp, timestampValue))
             return false;
 
         RootedString className(cx, Atomize(cx, entry.className, strlen(entry.className)));
         if (!className)
             return false;
         RootedValue classNameValue(cx, StringValue(className));
         if (!DefineProperty(cx, obj, cx->names().class_, classNameValue))
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -1635,17 +1635,17 @@ SavedStacks::MetadataBuilder::build(JSCo
     SavedStacks& stacks = cx->compartment()->savedStacks();
     if (!stacks.bernoulli.trial())
         return nullptr;
 
     RootedSavedFrame frame(cx);
     if (!stacks.saveCurrentStack(cx, &frame))
         oomUnsafe.crash("SavedStacksMetadataBuilder");
 
-    if (!Debugger::onLogAllocationSite(cx, obj, frame, JS_GetCurrentEmbedderTime()))
+    if (!Debugger::onLogAllocationSite(cx, obj, frame, mozilla::TimeStamp::Now()))
         oomUnsafe.crash("SavedStacksMetadataBuilder");
 
     MOZ_ASSERT_IF(frame, !frame->is<WrapperObject>());
     return frame;
 }
 
 const SavedStacks::MetadataBuilder SavedStacks::metadataBuilder;
 
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -465,23 +465,16 @@ private:
 };
 
 NS_IMPL_ISUPPORTS(VPXReporter, nsIMemoryReporter)
 
 /* static */ template<> Atomic<size_t>
 CountingAllocatorBase<VPXReporter>::sAmount(0);
 #endif /* MOZ_VPX */
 
-static double
-TimeSinceProcessCreation()
-{
-  bool ignore;
-  return (TimeStamp::Now() - TimeStamp::ProcessCreation(ignore)).ToMilliseconds();
-}
-
 static bool sInitializedJS = false;
 
 // Note that on OSX, aBinDirectory will point to .app/Contents/Resources/browser
 EXPORT_XPCOM_API(nsresult)
 NS_InitXPCOM2(nsIServiceManager** aResult,
               nsIFile* aBinDirectory,
               nsIDirectoryServiceProvider* aAppFileLocationProvider)
 {
@@ -495,18 +488,16 @@ NS_InitXPCOM2(nsIServiceManager** aResul
   mozPoisonValueInit();
 
   NS_LogInit();
 
   NS_InitAtomTable();
 
   mozilla::LogModule::Init();
 
-  JS_SetCurrentEmbedderTimeFunction(TimeSinceProcessCreation);
-
   char aLocal;
   profiler_init(&aLocal);
   nsresult rv = NS_OK;
 
   // We are not shutting down
   gXPCOMShuttingDown = false;
 
   // Initialize the available memory tracker before other threads have had a