Backed out changeset 00726df4997c (bug 1190074) for bustage on a CLOSED TREE

This commit is contained in:
Carsten "Tomcat" Book 2015-08-03 17:06:15 +02:00
parent 20e2d7698e
commit c69b66877e
5 changed files with 186 additions and 146 deletions

View File

@ -368,12 +368,12 @@ IterPerformanceStats(JSContext* cx,
continue;
}
js::AutoCompartment autoCompartment(cx, compartment);
mozilla::RefPtr<PerformanceGroup> ownGroup = compartment->performanceMonitoring.getOwnGroup();
PerformanceGroup* ownGroup = compartment->performanceMonitoring.getOwnGroup(cx);
if (ownGroup->data.ticks == 0) {
// Don't report compartments that have never been used.
continue;
}
mozilla::RefPtr<PerformanceGroup> sharedGroup = compartment->performanceMonitoring.getSharedGroup(cx);
PerformanceGroup* sharedGroup = compartment->performanceMonitoring.getSharedGroup(cx);
if (!(*walker)(cx,
ownGroup->data, ownGroup->uid, &sharedGroup->uid,
closure)) {
@ -383,7 +383,7 @@ IterPerformanceStats(JSContext* cx,
}
// Finally, report the process stats
*processStats = rt->stopwatch.performance.getOwnGroup()->data;
*processStats = rt->stopwatch.performance;
return true;
}

View File

@ -13,7 +13,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Range.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/RefPtr.h"
#include <stdarg.h>
#include <stddef.h>
@ -5515,22 +5514,15 @@ struct PerformanceGroup {
stopwatch_ = nullptr;
}
// Refcounting. For use with mozilla::RefPtr.
void AddRef();
void Release();
// Construct a PerformanceGroup for a single compartment.
explicit PerformanceGroup(JSRuntime* rt);
// Construct a PerformanceGroup for a group of compartments.
explicit PerformanceGroup(JSContext* rt, void* key);
private:
explicit PerformanceGroup(JSContext* cx, void* key);
~PerformanceGroup()
{
MOZ_ASSERT(refCount_ == 0);
}
private:
PerformanceGroup& operator=(const PerformanceGroup&) = delete;
PerformanceGroup(const PerformanceGroup&) = delete;
JSRuntime* runtime_;
// The stopwatch currently monitoring the group,
// or `nullptr` if none. Used ony for comparison.
const AutoStopwatch* stopwatch_;
@ -5542,14 +5534,20 @@ private:
// The hash key for this PerformanceGroup.
void* const key_;
// A reference counter.
// 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:
// A reference counter. Maintained by PerformanceGroupHolder.
uint64_t refCount_;
// `true` if this PerformanceGroup may be shared by several
// compartments, `false` if it is dedicated to a single
// compartment.
const bool isSharedGroup_;
};
//
@ -5566,7 +5564,7 @@ struct PerformanceGroupHolder {
js::PerformanceGroup* getSharedGroup(JSContext*);
// Get the own group.
js::PerformanceGroup* getOwnGroup();
js::PerformanceGroup* getOwnGroup(JSContext*);
// `true` if the this holder is currently associated to a shared
// PerformanceGroup, `false` otherwise. Use this method to avoid
@ -5586,6 +5584,8 @@ struct PerformanceGroupHolder {
explicit PerformanceGroupHolder(JSRuntime* runtime)
: runtime_(runtime)
, sharedGroup_(nullptr)
, ownGroup_(nullptr)
{ }
~PerformanceGroupHolder();
@ -5600,8 +5600,8 @@ struct PerformanceGroupHolder {
// The PerformanceGroups held by this object.
// Initially set to `nullptr` until the first call to `getGroup`.
// May be reset to `nullptr` by a call to `unlink`.
mozilla::RefPtr<js::PerformanceGroup> sharedGroup_;
mozilla::RefPtr<js::PerformanceGroup> ownGroup_;
js::PerformanceGroup* sharedGroup_;
js::PerformanceGroup* ownGroup_;
};
/**

View File

@ -389,6 +389,22 @@ class AutoStopwatch final
// loop. Used only for comparison.
uint64_t iteration_;
// `true` if this object is currently used to monitor performance
// for a shared PerformanceGroup, `false` otherwise, i.e. if the
// stopwatch mechanism is off or if another stopwatch is already
// in charge of monitoring for the same PerformanceGroup.
bool isMonitoringForGroup_;
// `true` if this object is currently used to monitor performance
// for a single compartment, `false` otherwise, i.e. if the
// stopwatch mechanism is off or if another stopwatch is already
// in charge of monitoring for the same PerformanceGroup.
bool isMonitoringForSelf_;
// `true` if this stopwatch is the topmost stopwatch on the stack
// for this event, `false` otherwise.
bool isMonitoringForTop_;
// `true` if we are monitoring jank, `false` otherwise.
bool isMonitoringJank_;
// `true` if we are monitoring CPOW, `false` otherwise.
@ -399,20 +415,6 @@ class AutoStopwatch final
uint64_t systemTimeStart_;
uint64_t CPOWTimeStart_;
// The performance group shared by this compartment and possibly
// others, or `nullptr` if another AutoStopwatch is already in
// charge of monitoring that group.
mozilla::RefPtr<js::PerformanceGroup> sharedGroup_;
// The toplevel group, representing the entire process, or `nullptr`
// if another AutoStopwatch is already in charge of monitoring that group.
mozilla::RefPtr<js::PerformanceGroup> topGroup_;
// The performance group specific to this compartment, or
// `nullptr` if another AutoStopwatch is already in charge of
// monitoring that group.
mozilla::RefPtr<js::PerformanceGroup> ownGroup_;
public:
// If the stopwatch is active, constructing an instance of
// AutoStopwatch causes it to become the current owner of the
@ -422,6 +424,9 @@ class AutoStopwatch final
explicit inline AutoStopwatch(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: cx_(cx)
, iteration_(0)
, isMonitoringForGroup_(false)
, isMonitoringForSelf_(false)
, isMonitoringForTop_(false)
, isMonitoringJank_(false)
, isMonitoringCPOW_(false)
, userTimeStart_(0)
@ -437,23 +442,52 @@ class AutoStopwatch final
JSRuntime* runtime = cx_->runtime();
iteration_ = runtime->stopwatch.iteration;
sharedGroup_ = acquireGroup(compartment->performanceMonitoring.getSharedGroup(cx));
if (sharedGroup_)
topGroup_ = acquireGroup(runtime->stopwatch.performance.getOwnGroup());
PerformanceGroup* sharedGroup = compartment->performanceMonitoring.getSharedGroup(cx);
if (!sharedGroup) {
// Either this Runtime is not configured for Performance Monitoring, or we couldn't
// allocate the group, or there was a problem with the hashtable.
return;
}
if (runtime->stopwatch.isMonitoringPerCompartment())
ownGroup_ = acquireGroup(compartment->performanceMonitoring.getOwnGroup());
if (!sharedGroup->hasStopwatch(iteration_)) {
// 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.
sharedGroup->acquireStopwatch(iteration_, this);
isMonitoringForGroup_ = true;
}
if (!sharedGroup_ && !ownGroup_) {
PerformanceGroup* ownGroup = nullptr;
if (runtime->stopwatch.isMonitoringPerCompartment()) {
// As above, but for the group representing just this compartment.
ownGroup = compartment->performanceMonitoring.getOwnGroup(cx);
if (!ownGroup->hasStopwatch(iteration_)) {
ownGroup->acquireStopwatch(iteration_, this);
isMonitoringForSelf_ = true;
}
}
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;
isMonitoringForTop_ = true;
MOZ_ASSERT(isMonitoringForGroup_);
}
if (!isMonitoringForGroup_ && !isMonitoringForSelf_) {
// We are not in charge of monitoring anything.
// (isMonitoringForTop_ implies isMonitoringForGroup_,
// so we do not need to check it)
return;
}
enter();
}
~AutoStopwatch()
{
if (!sharedGroup_ && !ownGroup_) {
~AutoStopwatch() {
if (!isMonitoringForGroup_ && !isMonitoringForSelf_) {
// We are not in charge of monitoring anything.
// (isMonitoringForTop_ implies isMonitoringForGroup_,
// so we do not need to check it)
@ -471,19 +505,31 @@ class AutoStopwatch final
return;
}
releaseGroup(sharedGroup_);
releaseGroup(topGroup_);
releaseGroup(ownGroup_);
// Finish and commit measures
exit();
// Now release groups.
if (isMonitoringForGroup_) {
PerformanceGroup* sharedGroup = compartment->performanceMonitoring.getSharedGroup(cx_);
MOZ_ASSERT(sharedGroup);
sharedGroup->releaseStopwatch(iteration_, this);
}
if (isMonitoringForSelf_) {
PerformanceGroup* ownGroup = compartment->performanceMonitoring.getOwnGroup(cx_);
MOZ_ASSERT(ownGroup);
ownGroup->releaseStopwatch(iteration_, this);
}
if (isMonitoringForTop_)
runtime->stopwatch.isEmpty = true;
}
private:
void enter() {
JSRuntime* runtime = cx_->runtime();
if (runtime->stopwatch.isMonitoringCPOW()) {
CPOWTimeStart_ = runtime->stopwatch.performance.getOwnGroup()->data.totalCPOWTime;
CPOWTimeStart_ = runtime->stopwatch.performance.totalCPOWTime;
isMonitoringCPOW_ = true;
}
@ -517,54 +563,46 @@ class AutoStopwatch final
uint64_t CPOWTimeDelta = 0;
if (isMonitoringCPOW_ && runtime->stopwatch.isMonitoringCPOW()) {
// We were monitoring CPOW when we entered and we still are.
CPOWTimeDelta = runtime->stopwatch.performance.getOwnGroup()->data.totalCPOWTime - CPOWTimeStart_;
CPOWTimeDelta = runtime->stopwatch.performance.totalCPOWTime - CPOWTimeStart_;
}
commitDeltasToGroups(userTimeDelta, systemTimeDelta, CPOWTimeDelta);
}
// Attempt to acquire a group
// If the group is `null` or if the group already has a stopwatch,
// do nothing and return `null`.
// Otherwise, bind the group to `this` for the current iteration
// and return `group`.
PerformanceGroup* acquireGroup(PerformanceGroup* group) {
if (!group)
return nullptr;
void commitDeltasToGroups(uint64_t userTimeDelta,
uint64_t systemTimeDelta,
uint64_t CPOWTimeDelta)
{
JSCompartment* compartment = cx_->compartment();
if (group->hasStopwatch(iteration_))
return nullptr;
PerformanceGroup* sharedGroup = compartment->performanceMonitoring.getSharedGroup(cx_);
MOZ_ASSERT(sharedGroup);
applyDeltas(userTimeDelta, systemTimeDelta, CPOWTimeDelta, sharedGroup->data);
group->acquireStopwatch(iteration_, this);
return group;
if (isMonitoringForSelf_) {
PerformanceGroup* ownGroup = compartment->performanceMonitoring.getOwnGroup(cx_);
MOZ_ASSERT(ownGroup);
applyDeltas(userTimeDelta, systemTimeDelta, CPOWTimeDelta, ownGroup->data);
}
if (isMonitoringForTop_) {
JSRuntime* runtime = cx_->runtime();
applyDeltas(userTimeDelta, systemTimeDelta, CPOWTimeDelta, runtime->stopwatch.performance);
}
}
// Release a group.
// Noop if `group` is null or if `this` is not the stopwatch
// of `group` for the current iteration.
void releaseGroup(PerformanceGroup* group) {
if (group)
group->releaseStopwatch(iteration_, this);
}
void commitDeltasToGroups(uint64_t userTimeDelta, uint64_t systemTimeDelta,
uint64_t CPOWTimeDelta) const {
applyDeltas(userTimeDelta, systemTimeDelta, CPOWTimeDelta, sharedGroup_);
applyDeltas(userTimeDelta, systemTimeDelta, CPOWTimeDelta, topGroup_);
applyDeltas(userTimeDelta, systemTimeDelta, CPOWTimeDelta, ownGroup_);
}
void applyDeltas(uint64_t userTimeDelta,
uint64_t systemTimeDelta,
uint64_t CPOWTimeDelta,
PerformanceData& data) const {
void applyDeltas(uint64_t userTimeDelta, uint64_t systemTimeDelta,
uint64_t CPOWTimeDelta, PerformanceGroup* group) const {
if (!group)
return;
group->data.ticks++;
data.ticks++;
uint64_t totalTimeDelta = userTimeDelta + systemTimeDelta;
group->data.totalUserTime += userTimeDelta;
group->data.totalSystemTime += systemTimeDelta;
group->data.totalCPOWTime += CPOWTimeDelta;
data.totalUserTime += userTimeDelta;
data.totalSystemTime += systemTimeDelta;
data.totalCPOWTime += CPOWTimeDelta;
// Update an array containing the number of times we have missed
// at least 2^0 successive ms, 2^1 successive ms, ...
@ -574,10 +612,10 @@ class AutoStopwatch final
size_t i = 0;
uint64_t duration = 1000;
for (i = 0, duration = 1000;
i < ArrayLength(group->data.durations) && duration < totalTimeDelta;
i < ArrayLength(data.durations) && duration < totalTimeDelta;
++i, duration *= 2)
{
group->data.durations[i]++;
data.durations[i]++;
}
}

View File

@ -222,8 +222,7 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
largeAllocationFailureCallback(nullptr),
oomCallback(nullptr),
debuggerMallocSizeOf(ReturnZeroSize),
lastAnimationTime(0),
stopwatch(thisFromCtor())
lastAnimationTime(0)
{
setGCStoreBufferPtr(&gc.storeBuffer);
@ -931,17 +930,40 @@ js::PerformanceGroupHolder::getHashKey(JSContext* cx)
void
js::PerformanceGroupHolder::unlink()
{
ownGroup_ = nullptr;
if (ownGroup_) {
js_delete(ownGroup_);
ownGroup_ = nullptr;
}
if (!sharedGroup_) {
// The group has never been instantiated.
return;
}
js::PerformanceGroup* group = sharedGroup_;
sharedGroup_ = nullptr;
if (group->decRefCount() > 0) {
// The group has at least another owner.
return;
}
JSRuntime::Stopwatch::Groups::Ptr ptr =
runtime_->stopwatch.groups().lookup(group->key_);
MOZ_ASSERT(ptr);
runtime_->stopwatch.groups().remove(ptr);
js_delete(group);
}
PerformanceGroup*
js::PerformanceGroupHolder::getOwnGroup()
js::PerformanceGroupHolder::getOwnGroup(JSContext* cx)
{
if (ownGroup_)
return ownGroup_;
return ownGroup_ = runtime_->new_<PerformanceGroup>(runtime_);
ownGroup_ = runtime_->new_<PerformanceGroup>(cx, nullptr);
return ownGroup_;
}
PerformanceGroup*
@ -963,58 +985,31 @@ js::PerformanceGroupHolder::getSharedGroup(JSContext* cx)
if (!sharedGroup_)
return nullptr;
runtime_->stopwatch.groups().add(ptr, key, sharedGroup_);
if (!runtime_->stopwatch.groups().add(ptr, key, sharedGroup_)) {
js_delete(sharedGroup_);
sharedGroup_ = nullptr;
return nullptr;
}
}
sharedGroup_->incRefCount();
return sharedGroup_;
}
PerformanceData*
js::GetPerformanceData(JSRuntime* rt)
{
return &rt->stopwatch.performance.getOwnGroup()->data;
return &rt->stopwatch.performance;
}
js::PerformanceGroup::PerformanceGroup(JSRuntime* rt)
: uid(rt->stopwatch.uniqueId()),
runtime_(rt),
stopwatch_(nullptr),
iteration_(0),
key_(nullptr),
refCount_(0),
isSharedGroup_(false)
{ }
js::PerformanceGroup::PerformanceGroup(JSContext* cx, void* key)
: uid(cx->runtime()->stopwatch.uniqueId()),
runtime_(cx->runtime()),
stopwatch_(nullptr),
iteration_(0),
key_(key),
refCount_(0),
isSharedGroup_(true)
{ }
void
js::PerformanceGroup::AddRef()
js::PerformanceGroup::PerformanceGroup(JSContext* cx, void* key)
: uid(cx->runtime()->stopwatch.uniqueId())
, stopwatch_(nullptr)
, iteration_(0)
, key_(key)
, refCount_(0)
{
++refCount_;
}
void
js::PerformanceGroup::Release()
{
MOZ_ASSERT(refCount_ > 0);
--refCount_;
if (refCount_ > 0)
return;
if (!isSharedGroup_)
return;
JSRuntime::Stopwatch::Groups::Ptr ptr = runtime_->stopwatch.groups().lookup(key_);
MOZ_ASSERT(ptr);
runtime_->stopwatch.groups().remove(ptr);
js_delete(this);
}
void

View File

@ -1512,11 +1512,6 @@ struct JSRuntime : public JS::shadow::Runtime,
return groups_;
}
/**
* Performance data on the entire runtime.
*/
js::PerformanceGroupHolder performance;
/**
* The number of times we have entered the event loop.
* Used to reset counters whenever we enter the loop,
@ -1528,6 +1523,17 @@ struct JSRuntime : public JS::shadow::Runtime,
*/
uint64_t iteration;
/**
* `true` if no stopwatch has been registered for the
* current run of the event loop, `false` until then.
*/
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
@ -1540,9 +1546,9 @@ struct JSRuntime : public JS::shadow::Runtime,
*/
JSCurrentPerfGroupCallback currentPerfGroupCallback;
Stopwatch(JSRuntime* runtime)
: performance(runtime)
, iteration(0)
Stopwatch()
: iteration(0)
, isEmpty(true)
, currentPerfGroupCallback(nullptr)
, isMonitoringJank_(false)
, isMonitoringCPOW_(false)
@ -1559,6 +1565,7 @@ struct JSRuntime : public JS::shadow::Runtime,
*/
void reset() {
++iteration;
isEmpty = true;
}
/**
* Activate/deactivate stopwatch measurement of jank.