author | David Rajchenbach-Teller <dteller@mozilla.com> |
Sat, 18 Apr 2015 13:21:31 +0200 | |
changeset 246400 | d606c1796afd1a488821aff6429ceb56c92a0e5c |
parent 246300 | 59226e937b8554471707206a668349d3d7f0c7bb |
child 246401 | 22242ca54fd5537e3ef9991b2f3a6c3f65dbb970 |
push id | 28829 |
push user | cbook@mozilla.com |
push date | Mon, 01 Jun 2015 12:18:22 +0000 |
treeherder | mozilla-central@2fa4bb097f03 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem, bholley |
bugs | 1149486 |
milestone | 41.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
|
--- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -269,82 +269,64 @@ JS_GetEmptyString(JSRuntime* rt) { MOZ_ASSERT(rt->hasContexts()); return rt->emptyString; } namespace js { JS_PUBLIC_API(bool) -GetPerformanceStats(JSRuntime* rt, - PerformanceStatsVector& stats, - PerformanceStats& processStats) +IterPerformanceStats(JSContext* cx, + PerformanceStatsWalker walker, + PerformanceData* processStats, + void* closure) { // As a PerformanceGroup is typically associated to several // compartments, use a HashSet to make sure that we only report // each PerformanceGroup once. typedef HashSet<js::PerformanceGroup*, js::DefaultHasher<js::PerformanceGroup*>, js::SystemAllocPolicy> Set; Set set; if (!set.init(100)) { return false; } + JSRuntime* rt = JS_GetRuntime(cx); for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) { JSCompartment* compartment = c.get(); if (!compartment->performanceMonitoring.isLinked()) { // Don't report compartments that do not even have a PerformanceGroup. continue; } - PerformanceGroup* group = compartment->performanceMonitoring.getGroup(); + + js::AutoCompartment autoCompartment(cx, compartment); + PerformanceGroup* group = compartment->performanceMonitoring.getGroup(cx); if (group->data.ticks == 0) { // Don't report compartments that have never been used. continue; } Set::AddPtr ptr = set.lookupForAdd(group); if (ptr) { // Don't report the same group twice. continue; } - if (!stats.growBy(1)) { - // Memory issue + if (!(*walker)(cx, group->data, closure)) { + // Issue in callback return false; } - PerformanceStats* stat = &stats.back(); - stat->isSystem = compartment->isSystem(); - if (compartment->addonId) - stat->addonId = compartment->addonId; - - if (compartment->addonId || !compartment->isSystem()) { - if (rt->compartmentNameCallback) { - (*rt->compartmentNameCallback)(rt, compartment, - stat->name, - mozilla::ArrayLength(stat->name)); - } else { - strcpy(stat->name, "<unknown>"); - } - } else { - strcpy(stat->name, "<platform>"); - } - stat->performance = group->data; if (!set.add(ptr, group)) { // Memory issue return false; } } - - strcpy(processStats.name, "<process>"); - processStats.addonId = nullptr; - processStats.isSystem = true; - processStats.performance = rt->stopwatch.performance; - + *processStats = rt->stopwatch.performance; return true; } void AssertHeapIsIdle(JSRuntime* rt) { MOZ_ASSERT(!rt->isHeapBusy()); } @@ -924,16 +906,17 @@ JSAutoCompartment::JSAutoCompartment(JSC : cx_(cx), oldCompartment_(cx->compartment()) { AssertHeapIsIdleOrIterating(cx_); MOZ_GUARD_OBJECT_NOTIFIER_INIT; cx_->enterCompartment(target->compartment()); } + JSAutoCompartment::~JSAutoCompartment() { cx_->leaveCompartment(oldCompartment_); } JSAutoNullableCompartment::JSAutoNullableCompartment(JSContext* cx, JSObject* targetOrNull MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
--- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -715,16 +715,28 @@ typedef void typedef void (* JSZoneCallback)(JS::Zone* zone); typedef void (* JSCompartmentNameCallback)(JSRuntime* rt, JSCompartment* compartment, char* buf, size_t bufsize); +/** + * Callback used to ask the embedding to determine in which + * Performance Group the current execution belongs. Typically, this is + * used to regroup JSCompartments from several iframes from the same + * page or from several compartments of the same addon into a single + * Performance Group. + * + * Returns an opaque key. + */ +typedef void* +(* JSCurrentPerfGroupCallback)(JSContext*); + /************************************************************************/ static MOZ_ALWAYS_INLINE jsval JS_NumberValue(double d) { int32_t i; d = JS::CanonicalizeNaN(d); if (mozilla::NumberIsInt32(d, &i)) @@ -5441,19 +5453,20 @@ struct PerformanceGroup { void releaseStopwatch(uint64_t iteration, const AutoStopwatch* stopwatch) { if (iteration_ != iteration) return; MOZ_ASSERT(stopwatch == stopwatch_ || stopwatch_ == nullptr); stopwatch_ = nullptr; } - PerformanceGroup() + explicit PerformanceGroup(void* key) : stopwatch_(nullptr) , iteration_(0) + , key_(key) , refCount_(0) { } ~PerformanceGroup() { MOZ_ASSERT(refCount_ == 0); } private: PerformanceGroup& operator=(const PerformanceGroup&) = delete; @@ -5462,69 +5475,70 @@ struct PerformanceGroup { // The stopwatch currently monitoring the group, // or `nullptr` if none. Used ony for comparison. const AutoStopwatch* stopwatch_; // The current iteration of the event loop. If necessary, // may safely overflow. uint64_t iteration_; + // The hash key for this PerformanceGroup. + void* const key_; + // Increment/decrement the refcounter, return the updated value. uint64_t incRefCount() { MOZ_ASSERT(refCount_ + 1 > 0); return ++refCount_; } uint64_t decRefCount() { MOZ_ASSERT(refCount_ > 0); return --refCount_; } friend struct PerformanceGroupHolder; - private: +private: // A reference counter. Maintained by PerformanceGroupHolder. uint64_t refCount_; }; // // Indirection towards a PerformanceGroup. // This structure handles reference counting for instances of PerformanceGroup. // struct PerformanceGroupHolder { // Get the group. // On first call, this causes a single Hashtable lookup. // Successive calls do not require further lookups. - js::PerformanceGroup* getGroup(); + js::PerformanceGroup* getGroup(JSContext*); // `true` if the this holder is currently associated to a // PerformanceGroup, `false` otherwise. Use this method to avoid // instantiating a PerformanceGroup if you only need to get // available performance data. inline bool isLinked() const { return group_ != nullptr; } // Remove the link to the PerformanceGroup. This method is designed // as an invalidation mechanism if the JSCompartment changes nature // (new values of `isSystem()`, `principals()` or `addonId`). void unlink(); - PerformanceGroupHolder(JSRuntime* runtime, JSCompartment* compartment) + explicit PerformanceGroupHolder(JSRuntime* runtime) : runtime_(runtime) - , compartment_(compartment) , group_(nullptr) { } ~PerformanceGroupHolder(); private: // Return the key representing this PerformanceGroup in // Runtime::Stopwatch. // Do not deallocate the key. - void* getHashKey(); - - JSRuntime* runtime_; - JSCompartment* compartment_; + void* getHashKey(JSContext* cx); + + JSRuntime *runtime_; // The PerformanceGroup held by this object. // Initially set to `nullptr` until the first cal to `getGroup`. // May be reset to `nullptr` by a call to `unlink`. js::PerformanceGroup* group_; }; /** @@ -5547,61 +5561,35 @@ extern JS_PUBLIC_API(bool) IsStopwatchActive(JSRuntime*); /** * Access the performance information stored in a compartment. */ extern JS_PUBLIC_API(PerformanceData*) GetPerformanceData(JSRuntime*); +typedef bool +(PerformanceStatsWalker)(JSContext* cx, const PerformanceData& stats, void* closure); + /** - * Performance statistics for a performance group (a process, an - * add-on, a webpage, the built-ins or a special compartment). - */ -struct PerformanceStats { - /** - * If this group represents an add-on, the ID of the addon, - * otherwise `nullptr`. - */ - JSAddonId* addonId; - - /** - * If this group represents a webpage, the process itself or a special - * compartment, a human-readable name. Unspecified for add-ons. - */ - char name[1024]; - - /** - * `true` if the group represents in system compartments, `false` - * otherwise. A group may never contain both system and non-system - * compartments. - */ - bool isSystem; - - /** - * Performance information. - */ - js::PerformanceData performance; - - PerformanceStats() - : addonId(nullptr) - , isSystem(false) - { - name[0] = '\0'; - } -}; - -typedef js::Vector<PerformanceStats, 0, js::SystemAllocPolicy> PerformanceStatsVector; - - /** * Extract the performance statistics. * - * After a successful call, `stats` holds the `PerformanceStats` for - * all performance groups, and `global` holds a `PerformanceStats` - * representing the entire process. + * Note that before calling `walker`, we enter the corresponding context. */ extern JS_PUBLIC_API(bool) -GetPerformanceStats(JSRuntime* rt, js::PerformanceStatsVector& stats, js::PerformanceStats& global); +IterPerformanceStats(JSContext* cx, PerformanceStatsWalker* walker, js::PerformanceData* process, void* closure); } /* namespace js */ +/** + * Callback used to ask the embedding to determine in which + * Performance Group a compartment belongs. Typically, this is used to + * regroup JSCompartments from several iframes from the same page or + * from several compartments of the same addon into a single + * Performance Group. + * + * Returns an opaque key. + */ +extern JS_PUBLIC_API(void) +JS_SetCurrentPerfGroupCallback(JSRuntime *rt, JSCurrentPerfGroupCallback cb); + #endif /* jsapi_h */
--- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -48,17 +48,17 @@ JSCompartment::JSCompartment(Zone* zone, warnedAboutNoSuchMethod(false), warnedAboutFlagsArgument(false), addonId(options.addonIdOrNull()), #ifdef DEBUG firedOnNewGlobalObject(false), #endif global_(nullptr), enterCompartmentDepth(0), - performanceMonitoring(runtime_, this), + performanceMonitoring(runtime_), data(nullptr), objectMetadataCallback(nullptr), lastAnimationTime(0), regExps(runtime_), globalWriteBarriered(false), neuteredTypedObjects(0), propertyTree(thisForCtor()), selfHostingScriptSource(nullptr),
--- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -404,111 +404,114 @@ namespace js { struct AutoStopwatch final { // If the stopwatch is active, constructing an instance of // AutoStopwatch causes it to become the current owner of the // stopwatch. // // Previous owner is restored upon destruction. explicit inline AutoStopwatch(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : compartment_(nullptr) - , runtime_(nullptr) + : cx_(cx) , iteration_(0) , isActive_(false) , isTop_(false) , userTimeStart_(0) , systemTimeStart_(0) , CPOWTimeStart_(0) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; - runtime_ = cx->runtime(); - if (!runtime_->stopwatch.isActive()) + + JSRuntime* runtime = JS_GetRuntime(cx_); + if (!runtime->stopwatch.isActive()) return; - compartment_ = cx->compartment(); - MOZ_ASSERT(compartment_); - if (compartment_->scheduledForDestruction) + + JSCompartment* compartment = cx_->compartment(); + if (compartment->scheduledForDestruction) return; - iteration_ = runtime_->stopwatch.iteration; - - PerformanceGroup* group = compartment_->performanceMonitoring.getGroup(); + iteration_ = runtime->stopwatch.iteration; + + PerformanceGroup *group = compartment->performanceMonitoring.getGroup(cx); MOZ_ASSERT(group); if (group->hasStopwatch(iteration_)) { // Someone is already monitoring this group during this // tick, no need for further monitoring. return; } // Start the stopwatch. - if (!this->getTimes(&userTimeStart_, &systemTimeStart_)) + if (!this->getTimes(runtime, &userTimeStart_, &systemTimeStart_)) return; isActive_ = true; - CPOWTimeStart_ = runtime_->stopwatch.performance.totalCPOWTime; + CPOWTimeStart_ = runtime->stopwatch.performance.totalCPOWTime; // We are now in charge of monitoring this group for the tick, // until destruction of `this` or until we enter a nested event // loop and `iteration_` is incremented. group->acquireStopwatch(iteration_, this); - if (runtime_->stopwatch.isEmpty) { + if (runtime->stopwatch.isEmpty) { // This is the topmost stopwatch on the stack. // It will be in charge of updating the per-process // performance data. - runtime_->stopwatch.isEmpty = false; - runtime_->stopwatch.performance.ticks++; + runtime->stopwatch.isEmpty = false; + runtime->stopwatch.performance.ticks++; isTop_ = true; } } inline ~AutoStopwatch() { if (!isActive_) { // We are not in charge of monitoring anything. return; } - MOZ_ASSERT(!compartment_->scheduledForDestruction); - - if (!runtime_->stopwatch.isActive()) { + JSRuntime* runtime = JS_GetRuntime(cx_); + JSCompartment* compartment = cx_->compartment(); + + MOZ_ASSERT(!compartment->scheduledForDestruction); + + if (!runtime->stopwatch.isActive()) { // Monitoring has been stopped while we were // executing the code. Drop everything. return; } - if (iteration_ != runtime_->stopwatch.iteration) { + if (iteration_ != runtime->stopwatch.iteration) { // We have entered a nested event loop at some point. // Any information we may have is obsolete. return; } - PerformanceGroup* group = compartment_->performanceMonitoring.getGroup(); + PerformanceGroup *group = compartment->performanceMonitoring.getGroup(cx_); MOZ_ASSERT(group); // Compute time spent. group->releaseStopwatch(iteration_, this); uint64_t userTimeEnd, systemTimeEnd; - if (!this->getTimes(&userTimeEnd, &systemTimeEnd)) + if (!this->getTimes(runtime, &userTimeEnd, &systemTimeEnd)) return; uint64_t userTimeDelta = userTimeEnd - userTimeStart_; uint64_t systemTimeDelta = systemTimeEnd - systemTimeStart_; - uint64_t CPOWTimeDelta = runtime_->stopwatch.performance.totalCPOWTime - CPOWTimeStart_; + uint64_t CPOWTimeDelta = runtime->stopwatch.performance.totalCPOWTime - CPOWTimeStart_; group->data.totalUserTime += userTimeDelta; group->data.totalSystemTime += systemTimeDelta; group->data.totalCPOWTime += CPOWTimeDelta; uint64_t totalTimeDelta = userTimeDelta + systemTimeDelta; updateDurations(totalTimeDelta, group->data.durations); group->data.ticks++; if (isTop_) { // This is the topmost stopwatch on the stack. // Record the timing information. - runtime_->stopwatch.performance.totalUserTime = userTimeEnd; - runtime_->stopwatch.performance.totalSystemTime = systemTimeEnd; - updateDurations(totalTimeDelta, runtime_->stopwatch.performance.durations); - runtime_->stopwatch.isEmpty = true; + runtime->stopwatch.performance.totalUserTime = userTimeEnd; + runtime->stopwatch.performance.totalSystemTime = systemTimeEnd; + updateDurations(totalTimeDelta, runtime->stopwatch.performance.durations); + runtime->stopwatch.isEmpty = true; } } private: // Update an array containing the number of times we have missed // at least 2^0 successive ms, 2^1 successive ms, ... // 2^i successive ms. @@ -522,17 +525,17 @@ struct AutoStopwatch final ++i, duration *= 2) { array[i]++; } } // Get the OS-reported time spent in userland/systemland, in // microseconds. On most platforms, this data is per-thread, // but on some platforms we need to fall back to per-process. - bool getTimes(uint64_t* userTime, uint64_t* systemTime) const { + bool getTimes(JSRuntime* runtime, uint64_t* userTime, uint64_t* systemTime) const { MOZ_ASSERT(userTime); MOZ_ASSERT(systemTime); #if defined(XP_MACOSX) // On MacOS X, to get we per-thread data, we need to // reach into the kernel. mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT; @@ -586,36 +589,32 @@ struct AutoStopwatch final if (!success) return false; ULARGE_INTEGER kernelTimeInt; ULARGE_INTEGER userTimeInt; kernelTimeInt.LowPart = kernelFileTime.dwLowDateTime; kernelTimeInt.HighPart = kernelFileTime.dwHighDateTime; // Convert 100 ns to 1 us, make sure that the result is monotonic - *systemTime = runtime_-> stopwatch.systemTimeFix.monotonize(kernelTimeInt.QuadPart / 10); + *systemTime = runtime->stopwatch.systemTimeFix.monotonize(kernelTimeInt.QuadPart / 10); userTimeInt.LowPart = userFileTime.dwLowDateTime; userTimeInt.HighPart = userFileTime.dwHighDateTime; // Convert 100 ns to 1 us, make sure that the result is monotonic - *userTime = runtime_-> stopwatch.userTimeFix.monotonize(userTimeInt.QuadPart / 10); + *userTime = runtime->stopwatch.userTimeFix.monotonize(userTimeInt.QuadPart / 10); #endif // defined(XP_MACOSX) || defined(XP_UNIX) || defined(XP_WIN) return true; } private: - // The compartment with which this object was initialized. + // The context with which this object was initialized. // Non-null. - JSCompartment* compartment_; - - // The runtime with which this object was initialized. - // Non-null. - JSRuntime* runtime_; + JSContext* const cx_; // An indication of the number of times we have entered the event // loop. Used only for comparison. uint64_t iteration_; // `true` if this object is currently used to monitor performance, // `false` otherwise, i.e. if the stopwatch mechanism is off or if // another stopwatch is already in charge of monitoring for the
--- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -893,25 +893,24 @@ js::IsStopwatchActive(JSRuntime* rt) } js::PerformanceGroupHolder::~PerformanceGroupHolder() { unlink(); } void* -js::PerformanceGroupHolder::getHashKey() +js::PerformanceGroupHolder::getHashKey(JSContext* cx) { - return compartment_->isSystem() ? - (void*)compartment_->addonId : - (void*)JS_GetCompartmentPrincipals(compartment_); - // This key may be `nullptr` if we have `isSystem() == true` - // and `compartment_->addonId`. This is absolutely correct, - // and this represents the `PerformanceGroup` used to track - // the performance of the the platform compartments. + if (runtime_->stopwatch.currentPerfGroupCallback) { + return (*runtime_->stopwatch.currentPerfGroupCallback)(cx); + } + + // As a fallback, put everything in the same PerformanceGroup. + return nullptr; } void js::PerformanceGroupHolder::unlink() { if (!group_) { // The group has never been instantiated. return; @@ -922,41 +921,47 @@ js::PerformanceGroupHolder::unlink() if (group->decRefCount() > 0) { // The group has at least another owner. return; } JSRuntime::Stopwatch::Groups::Ptr ptr = - runtime_->stopwatch.groups_.lookup(getHashKey()); + runtime_->stopwatch.groups_.lookup(group->key_); MOZ_ASSERT(ptr); runtime_->stopwatch.groups_.remove(ptr); js_delete(group); } PerformanceGroup* -js::PerformanceGroupHolder::getGroup() +js::PerformanceGroupHolder::getGroup(JSContext* cx) { if (group_) return group_; - void* key = getHashKey(); + void* key = getHashKey(cx); JSRuntime::Stopwatch::Groups::AddPtr ptr = runtime_->stopwatch.groups_.lookupForAdd(key); if (ptr) { group_ = ptr->value(); MOZ_ASSERT(group_); } else { - group_ = runtime_->new_<PerformanceGroup>(); + group_ = runtime_->new_<PerformanceGroup>(key); runtime_->stopwatch.groups_.add(ptr, key, group_); } group_->incRefCount(); return group_; } PerformanceData* js::GetPerformanceData(JSRuntime* rt) { return &rt->stopwatch.performance; } + +void +JS_SetCurrentPerfGroupCallback(JSRuntime *rt, JSCurrentPerfGroupCallback cb) +{ + rt->stopwatch.currentPerfGroupCallback = cb; +}
--- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1487,19 +1487,32 @@ struct JSRuntime : public JS::shadow::Ru */ bool isEmpty; /** * Performance data on the entire runtime. */ js::PerformanceData performance; + /** + * Callback used to ask the embedding to determine in which + * Performance Group the current execution belongs. Typically, this is + * used to regroup JSCompartments from several iframes from the same + * page or from several compartments of the same addon into a single + * Performance Group. + * + * May be `nullptr`, in which case we put all the JSCompartments + * in the same PerformanceGroup. + */ + JSCurrentPerfGroupCallback currentPerfGroupCallback; + Stopwatch() : iteration(0) , isEmpty(true) + , currentPerfGroupCallback(nullptr) , isActive_(false) { } /** * Reset the stopwatch. * * This method is meant to be called whenever we start processing * an event, to ensure that stop any ongoing measurement that would
--- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1774,16 +1774,30 @@ GetCompartmentName(JSCompartment* c, nsC // (such as about:memory) have to undo this change. if (replaceSlashes) name.ReplaceChar('/', '\\'); } else { name.AssignLiteral("null-principal"); } } +extern void +xpc::GetCurrentCompartmentName(JSContext* cx, nsCString& name) +{ + RootedObject global(cx, JS::CurrentGlobalOrNull(cx)); + if (!global) { + name.AssignLiteral("no global"); + return; + } + + JSCompartment* compartment = GetObjectCompartment(global); + int anonymizeID = 0; + GetCompartmentName(compartment, name, &anonymizeID, false); +} + static int64_t JSMainRuntimeGCHeapDistinguishedAmount() { JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime(); return int64_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * js::gc::ChunkSize; } @@ -3297,16 +3311,57 @@ class XPCJSSourceHook: public js::Source } }; static const JSWrapObjectCallbacks WrapObjectCallbacks = { xpc::WrapperFactory::Rewrap, xpc::WrapperFactory::PrepareForWrapping }; +/** + * Group JSCompartments into PerformanceGroups. + * + * - All JSCompartments from the same add-on belong to the same + * PerformanceGroup. + * - All JSCompartments from the same same webpage (including + * frames) belong to the same PerformanceGroup. + * - All other JSCompartments (normally, system add-ons) + * belong to to a big uncategorized PerformanceGroup. + */ +static void* +GetCurrentPerfGroupCallback(JSContext* cx) { + RootedObject global(cx, CurrentGlobalOrNull(cx)); + if (!global) { + // This can happen for the atom compartments, which is system + // code. + return nullptr; + } + + JSAddonId* addonId = AddonIdOfObject(global); + if (addonId) { + // If this is an add-on, use the id as key. + return addonId; + } + + // If the compartment belongs to a webpage, use the address of the + // topmost scriptable window, hence regrouping all frames of a + // window. + nsRefPtr<nsGlobalWindow> win = WindowOrNull(global); + if (win) { + nsCOMPtr<nsIDOMWindow> top; + nsresult rv = win->GetScriptableTop(getter_AddRefs(top)); + NS_ENSURE_SUCCESS(rv, nullptr); + + return top.get(); + } + + // Otherwise, this is platform code, use `nullptr` as key. + return nullptr; +} + XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) : CycleCollectedJSRuntime(nullptr, JS::DefaultHeapMaxBytes, JS::DefaultNurseryBytes), mJSContextStack(new XPCJSContextStack(this)), mCallContext(nullptr), mAutoRoots(nullptr), mResolveName(JSID_VOID), mResolvingWrapper(nullptr), mWrappedJSMap(JSObject2WrappedJSMap::newMap(XPC_JS_MAP_LENGTH)), @@ -3476,16 +3531,18 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* RegisterJSMainRuntimeTemporaryPeakDistinguishedAmount(JSMainRuntimeTemporaryPeakDistinguishedAmount); RegisterJSMainRuntimeCompartmentsSystemDistinguishedAmount(JSMainRuntimeCompartmentsSystemDistinguishedAmount); RegisterJSMainRuntimeCompartmentsUserDistinguishedAmount(JSMainRuntimeCompartmentsUserDistinguishedAmount); mozilla::RegisterJSSizeOfTab(JSSizeOfTab); // Watch for the JS boolean options. ReloadPrefsCallback(nullptr, this); Preferences::RegisterCallback(ReloadPrefsCallback, JS_OPTIONS_DOT_STR, this); + + JS_SetCurrentPerfGroupCallback(runtime, ::GetCurrentPerfGroupCallback); } // static XPCJSRuntime* XPCJSRuntime::newXPCJSRuntime(nsXPConnect* aXPConnect) { NS_PRECONDITION(aXPConnect,"bad param");
--- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -134,19 +134,16 @@ IsXrayWrapper(JSObject* obj); // To emphasize the obvious: the return value here is not necessarily same- // compartment with the argument. JSObject* XrayAwareCalleeGlobal(JSObject* fun); void TraceXPCGlobal(JSTracer* trc, JSObject* obj); -uint64_t -GetCompartmentCPOWMicroseconds(JSCompartment* compartment); - } /* namespace xpc */ namespace JS { struct RuntimeStats; } @@ -527,16 +524,22 @@ class ErrorReport { private: ~ErrorReport() {} }; void DispatchScriptErrorEvent(nsPIDOMWindow* win, JSRuntime* rt, xpc::ErrorReport* xpcReport, JS::Handle<JS::Value> exception); +// Return a name for the compartment. +// This function makes reasonable efforts to make this name both mostly human-readable +// and unique. However, there are no guarantees of either property. +extern void +GetCurrentCompartmentName(JSContext*, nsCString& name); + } // namespace xpc namespace mozilla { namespace dom { typedef JSObject* (*DefineInterface)(JSContext* cx, JS::Handle<JSObject*> global, JS::Handle<jsid> id, bool defineOnGlobal);