--- 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