зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1231763 - Extract breakdown parsing from JS::ubi::Census. r=jimb
This commit is contained in:
Родитель
514b142f92
Коммит
ffd963dd3f
|
@ -4,25 +4,11 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/devtools/DominatorTree.h"
|
||||
#include "js/Debug.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/dom/DominatorTreeBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace devtools {
|
||||
|
||||
static MallocSizeOf
|
||||
getCurrentThreadDebuggerMallocSizeOf()
|
||||
{
|
||||
auto ccrt = CycleCollectedJSRuntime::Get();
|
||||
MOZ_ASSERT(ccrt);
|
||||
auto rt = ccrt->Runtime();
|
||||
MOZ_ASSERT(rt);
|
||||
auto mallocSizeOf = JS::dbg::GetDebuggerMallocSizeOf(rt);
|
||||
MOZ_ASSERT(mallocSizeOf);
|
||||
return mallocSizeOf;
|
||||
}
|
||||
|
||||
dom::Nullable<uint64_t>
|
||||
DominatorTree::GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv)
|
||||
{
|
||||
|
@ -31,7 +17,7 @@ DominatorTree::GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv)
|
|||
if (node.isNothing())
|
||||
return dom::Nullable<uint64_t>();
|
||||
|
||||
auto mallocSizeOf = getCurrentThreadDebuggerMallocSizeOf();
|
||||
auto mallocSizeOf = GetCurrentThreadDebuggerMallocSizeOf();
|
||||
JS::ubi::Node::Size size = 0;
|
||||
if (!mDominatorTree.getRetainedSize(*node, mallocSizeOf, size)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -83,7 +69,7 @@ DominatorTree::GetImmediatelyDominated(uint64_t aNodeId,
|
|||
return;
|
||||
|
||||
// Get all immediately dominated nodes and their retained sizes.
|
||||
MallocSizeOf mallocSizeOf = getCurrentThreadDebuggerMallocSizeOf();
|
||||
MallocSizeOf mallocSizeOf = GetCurrentThreadDebuggerMallocSizeOf();
|
||||
Maybe<JS::ubi::DominatorTree::DominatedSetRange> range = mDominatorTree.getDominatedSet(*node);
|
||||
MOZ_ASSERT(range.isSome(), "The node should be known, since we got it from the heap snapshot.");
|
||||
size_t length = range->length();
|
||||
|
|
|
@ -55,6 +55,18 @@ using ::google::protobuf::io::ZeroCopyInputStream;
|
|||
|
||||
using JS::ubi::AtomOrTwoByteChars;
|
||||
|
||||
MallocSizeOf
|
||||
GetCurrentThreadDebuggerMallocSizeOf()
|
||||
{
|
||||
auto ccrt = CycleCollectedJSRuntime::Get();
|
||||
MOZ_ASSERT(ccrt);
|
||||
auto rt = ccrt->Runtime();
|
||||
MOZ_ASSERT(rt);
|
||||
auto mallocSizeOf = JS::dbg::GetDebuggerMallocSizeOf(rt);
|
||||
MOZ_ASSERT(mallocSizeOf);
|
||||
return mallocSizeOf;
|
||||
}
|
||||
|
||||
/*** Cycle Collection Boilerplate *****************************************************************/
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(HeapSnapshot, mParent)
|
||||
|
@ -482,7 +494,7 @@ HeapSnapshot::TakeCensus(JSContext* cx, JS::HandleObject options,
|
|||
return;
|
||||
}
|
||||
|
||||
JS::ubi::CensusHandler handler(census, rootCount);
|
||||
JS::ubi::CensusHandler handler(census, rootCount, GetCurrentThreadDebuggerMallocSizeOf());
|
||||
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
@ -504,7 +516,7 @@ HeapSnapshot::TakeCensus(JSContext* cx, JS::HandleObject options,
|
|||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!handler.report(rval))) {
|
||||
if (NS_WARN_IF(!handler.report(cx, rval))) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -221,6 +221,9 @@ WriteHeapGraph(JSContext* cx,
|
|||
ignoreNodeCount, ignoreEdgeCount);
|
||||
}
|
||||
|
||||
// Get the mozilla::MallocSizeOf for the current thread's JSRuntime.
|
||||
MallocSizeOf GetCurrentThreadDebuggerMallocSizeOf();
|
||||
|
||||
} // namespace devtools
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ using CountBasePtr = UniquePtr<CountBase, CountDeleter>;
|
|||
|
||||
// Abstract base class for CountType nodes.
|
||||
struct CountType {
|
||||
explicit CountType(Census& census) : census(census) { }
|
||||
explicit CountType() { }
|
||||
virtual ~CountType() { }
|
||||
|
||||
// Destruct a count tree node that this type instance constructed.
|
||||
|
@ -102,14 +102,13 @@ struct CountType {
|
|||
|
||||
// Implement the 'count' method for counts returned by this CountType
|
||||
// instance's 'newCount' method.
|
||||
virtual bool count(CountBase& count, const Node& node) = 0;
|
||||
virtual bool count(CountBase& count,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
const Node& node) = 0;
|
||||
|
||||
// Implement the 'report' method for counts returned by this CountType
|
||||
// instance's 'newCount' method.
|
||||
virtual bool report(CountBase& count, MutableHandleValue report) = 0;
|
||||
|
||||
protected:
|
||||
Census& census;
|
||||
virtual bool report(JSContext* cx, CountBase& count, MutableHandleValue report) = 0;
|
||||
};
|
||||
|
||||
using CountTypePtr = UniquePtr<CountType, JS::DeletePolicy<CountType>>;
|
||||
|
@ -129,12 +128,16 @@ class CountBase {
|
|||
explicit CountBase(CountType& type) : type(type), total_(0) { }
|
||||
|
||||
// Categorize and count |node| as appropriate for this count's type.
|
||||
bool count(const Node& node) { return type.count(*this, node); }
|
||||
bool count(mozilla::MallocSizeOf mallocSizeOf, const Node& node) {
|
||||
return type.count(*this, mallocSizeOf, node);
|
||||
}
|
||||
|
||||
// Construct a JavaScript object reporting the counts recorded in this
|
||||
// count, and store it in |report|. Return true on success, or false on
|
||||
// failure.
|
||||
bool report(MutableHandleValue report) { return type.report(*this, report); }
|
||||
bool report(JSContext* cx, MutableHandleValue report) {
|
||||
return type.report(cx, *this, report);
|
||||
}
|
||||
|
||||
// Down-cast this CountBase to its true type, based on its 'type' member,
|
||||
// and run its destructor.
|
||||
|
@ -173,18 +176,6 @@ struct Census {
|
|||
explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
|
||||
|
||||
bool init();
|
||||
|
||||
// A 'new' work-alike that behaves like TempAllocPolicy: report OOM on this
|
||||
// census's context, but don't charge the memory allocated to our context's
|
||||
// GC pressure counters.
|
||||
template<typename T, typename... Args>
|
||||
T* new_(Args&&... args) MOZ_HEAP_ALLOCATOR {
|
||||
void* memory = js_malloc(sizeof(T));
|
||||
if (MOZ_UNLIKELY(!memory)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new(memory) T(mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// A BreadthFirst handler type that conducts a census, using a CountBase to
|
||||
|
@ -192,15 +183,17 @@ struct Census {
|
|||
class CensusHandler {
|
||||
Census& census;
|
||||
CountBasePtr& rootCount;
|
||||
mozilla::MallocSizeOf mallocSizeOf;
|
||||
|
||||
public:
|
||||
CensusHandler(Census& census, CountBasePtr& rootCount)
|
||||
CensusHandler(Census& census, CountBasePtr& rootCount, mozilla::MallocSizeOf mallocSizeOf)
|
||||
: census(census),
|
||||
rootCount(rootCount)
|
||||
rootCount(rootCount),
|
||||
mallocSizeOf(mallocSizeOf)
|
||||
{ }
|
||||
|
||||
bool report(MutableHandleValue report) {
|
||||
return rootCount->report(report);
|
||||
bool report(JSContext* cx, MutableHandleValue report) {
|
||||
return rootCount->report(cx, report);
|
||||
}
|
||||
|
||||
// This class needs to retain no per-node data.
|
||||
|
@ -213,11 +206,17 @@ class CensusHandler {
|
|||
|
||||
using CensusTraversal = BreadthFirst<CensusHandler>;
|
||||
|
||||
// Examine the census options supplied by the API consumer, and use that to
|
||||
// build a CountType tree.
|
||||
// Examine the census options supplied by the API consumer, and (among other
|
||||
// things) use that to build a CountType tree.
|
||||
bool ParseCensusOptions(JSContext* cx, Census& census, HandleObject options,
|
||||
CountTypePtr& outResult);
|
||||
|
||||
// Parse the breakdown language (as described in
|
||||
// js/src/doc/Debugger/Debugger.Memory.md) into a CountTypePtr. A null pointer
|
||||
// is returned on error and is reported to the cx.
|
||||
CountTypePtr ParseBreakdown(JSContext* cx, HandleValue breakdownValue);
|
||||
|
||||
|
||||
} // namespace ubi
|
||||
} // namespace JS
|
||||
|
||||
|
|
|
@ -539,7 +539,7 @@ DebuggerMemory::takeCensus(JSContext* cx, unsigned argc, Value* vp)
|
|||
JS::ubi::RootedCount rootCount(cx, rootType->makeCount());
|
||||
if (!rootCount)
|
||||
return false;
|
||||
JS::ubi::CensusHandler handler(census, rootCount);
|
||||
JS::ubi::CensusHandler handler(census, rootCount, cx->runtime()->debuggerMallocSizeOf);
|
||||
|
||||
Debugger* dbg = memory->getDebugger();
|
||||
RootedObject dbgObj(cx, dbg->object);
|
||||
|
@ -573,7 +573,7 @@ DebuggerMemory::takeCensus(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
}
|
||||
|
||||
return handler.report(args.rval());
|
||||
return handler.report(cx, args.rval());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,18 +54,17 @@ class SimpleCount : public CountType {
|
|||
bool reportBytes : 1;
|
||||
|
||||
public:
|
||||
SimpleCount(Census& census,
|
||||
UniquePtr<char16_t[], JS::FreePolicy>& label,
|
||||
bool reportCount=true,
|
||||
bool reportBytes=true)
|
||||
: CountType(census),
|
||||
explicit SimpleCount(UniquePtr<char16_t[], JS::FreePolicy>& label,
|
||||
bool reportCount=true,
|
||||
bool reportBytes=true)
|
||||
: CountType(),
|
||||
label(Move(label)),
|
||||
reportCount(reportCount),
|
||||
reportBytes(reportBytes)
|
||||
{ }
|
||||
|
||||
explicit SimpleCount(Census& census)
|
||||
: CountType(census),
|
||||
explicit SimpleCount()
|
||||
: CountType(),
|
||||
label(nullptr),
|
||||
reportCount(true),
|
||||
reportBytes(true)
|
||||
|
@ -76,45 +75,45 @@ class SimpleCount : public CountType {
|
|||
count.~Count();
|
||||
}
|
||||
|
||||
CountBasePtr makeCount() override { return CountBasePtr(census.new_<Count>(*this)); }
|
||||
CountBasePtr makeCount() override { return CountBasePtr(js_new<Count>(*this)); }
|
||||
void traceCount(CountBase& countBase, JSTracer* trc) override { }
|
||||
bool count(CountBase& countBase, const Node& node) override;
|
||||
bool report(CountBase& countBase, MutableHandleValue report) override;
|
||||
bool count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node) override;
|
||||
bool report(JSContext* cx, CountBase& countBase, MutableHandleValue report) override;
|
||||
};
|
||||
|
||||
bool
|
||||
SimpleCount::count(CountBase& countBase, const Node& node)
|
||||
SimpleCount::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
count.total_++;
|
||||
if (reportBytes)
|
||||
count.totalBytes_ += node.size(census.cx->runtime()->debuggerMallocSizeOf);
|
||||
count.totalBytes_ += node.size(mallocSizeOf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SimpleCount::report(CountBase& countBase, MutableHandleValue report)
|
||||
SimpleCount::report(JSContext* cx, CountBase& countBase, MutableHandleValue report)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
|
||||
RootedPlainObject obj(census.cx, NewBuiltinClassInstance<PlainObject>(census.cx));
|
||||
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
RootedValue countValue(census.cx, NumberValue(count.total_));
|
||||
if (reportCount && !DefineProperty(census.cx, obj, census.cx->names().count, countValue))
|
||||
RootedValue countValue(cx, NumberValue(count.total_));
|
||||
if (reportCount && !DefineProperty(cx, obj, cx->names().count, countValue))
|
||||
return false;
|
||||
|
||||
RootedValue bytesValue(census.cx, NumberValue(count.totalBytes_));
|
||||
if (reportBytes && !DefineProperty(census.cx, obj, census.cx->names().bytes, bytesValue))
|
||||
RootedValue bytesValue(cx, NumberValue(count.totalBytes_));
|
||||
if (reportBytes && !DefineProperty(cx, obj, cx->names().bytes, bytesValue))
|
||||
return false;
|
||||
|
||||
if (label) {
|
||||
JSString* labelString = JS_NewUCStringCopyZ(census.cx, label.get());
|
||||
JSString* labelString = JS_NewUCStringCopyZ(cx, label.get());
|
||||
if (!labelString)
|
||||
return false;
|
||||
RootedValue labelValue(census.cx, StringValue(labelString));
|
||||
if (!DefineProperty(census.cx, obj, census.cx->names().label, labelValue))
|
||||
RootedValue labelValue(cx, StringValue(labelString));
|
||||
if (!DefineProperty(cx, obj, cx->names().label, labelValue))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -155,12 +154,11 @@ class ByCoarseType : public CountType {
|
|||
};
|
||||
|
||||
public:
|
||||
ByCoarseType(Census& census,
|
||||
CountTypePtr& objects,
|
||||
ByCoarseType(CountTypePtr& objects,
|
||||
CountTypePtr& scripts,
|
||||
CountTypePtr& strings,
|
||||
CountTypePtr& other)
|
||||
: CountType(census),
|
||||
: CountType(),
|
||||
objects(Move(objects)),
|
||||
scripts(Move(scripts)),
|
||||
strings(Move(strings)),
|
||||
|
@ -174,8 +172,8 @@ class ByCoarseType : public CountType {
|
|||
|
||||
CountBasePtr makeCount() override;
|
||||
void traceCount(CountBase& countBase, JSTracer* trc) override;
|
||||
bool count(CountBase& countBase, const Node& node) override;
|
||||
bool report(CountBase& countBase, MutableHandleValue report) override;
|
||||
bool count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node) override;
|
||||
bool report(JSContext* cx, CountBase& countBase, MutableHandleValue report) override;
|
||||
};
|
||||
|
||||
CountBasePtr
|
||||
|
@ -189,11 +187,11 @@ ByCoarseType::makeCount()
|
|||
if (!objectsCount || !scriptsCount || !stringsCount || !otherCount)
|
||||
return CountBasePtr(nullptr);
|
||||
|
||||
return CountBasePtr(census.new_<Count>(*this,
|
||||
objectsCount,
|
||||
scriptsCount,
|
||||
stringsCount,
|
||||
otherCount));
|
||||
return CountBasePtr(js_new<Count>(*this,
|
||||
objectsCount,
|
||||
scriptsCount,
|
||||
stringsCount,
|
||||
otherCount));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -207,20 +205,20 @@ ByCoarseType::traceCount(CountBase& countBase, JSTracer* trc)
|
|||
}
|
||||
|
||||
bool
|
||||
ByCoarseType::count(CountBase& countBase, const Node& node)
|
||||
ByCoarseType::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
count.total_++;
|
||||
|
||||
switch (node.coarseType()) {
|
||||
case JS::ubi::CoarseType::Object:
|
||||
return count.objects->count(node);
|
||||
return count.objects->count(mallocSizeOf, node);
|
||||
case JS::ubi::CoarseType::Script:
|
||||
return count.scripts->count(node);
|
||||
return count.scripts->count(mallocSizeOf, node);
|
||||
case JS::ubi::CoarseType::String:
|
||||
return count.strings->count(node);
|
||||
return count.strings->count(mallocSizeOf, node);
|
||||
case JS::ubi::CoarseType::Other:
|
||||
return count.other->count(node);
|
||||
return count.other->count(mallocSizeOf, node);
|
||||
default:
|
||||
MOZ_CRASH("bad JS::ubi::CoarseType in JS::ubi::ByCoarseType::count");
|
||||
return false;
|
||||
|
@ -228,32 +226,31 @@ ByCoarseType::count(CountBase& countBase, const Node& node)
|
|||
}
|
||||
|
||||
bool
|
||||
ByCoarseType::report(CountBase& countBase, MutableHandleValue report)
|
||||
ByCoarseType::report(JSContext* cx, CountBase& countBase, MutableHandleValue report)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
JSContext* cx = census.cx;
|
||||
|
||||
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
RootedValue objectsReport(cx);
|
||||
if (!count.objects->report(&objectsReport) ||
|
||||
if (!count.objects->report(cx, &objectsReport) ||
|
||||
!DefineProperty(cx, obj, cx->names().objects, objectsReport))
|
||||
return false;
|
||||
|
||||
RootedValue scriptsReport(cx);
|
||||
if (!count.scripts->report(&scriptsReport) ||
|
||||
if (!count.scripts->report(cx, &scriptsReport) ||
|
||||
!DefineProperty(cx, obj, cx->names().scripts, scriptsReport))
|
||||
return false;
|
||||
|
||||
RootedValue stringsReport(cx);
|
||||
if (!count.strings->report(&stringsReport) ||
|
||||
if (!count.strings->report(cx, &stringsReport) ||
|
||||
!DefineProperty(cx, obj, cx->names().strings, stringsReport))
|
||||
return false;
|
||||
|
||||
RootedValue otherReport(cx);
|
||||
if (!count.other->report(&otherReport) ||
|
||||
if (!count.other->report(cx, &otherReport) ||
|
||||
!DefineProperty(cx, obj, cx->names().other, otherReport))
|
||||
return false;
|
||||
|
||||
|
@ -320,7 +317,7 @@ cStringCountMapToObject(JSContext* cx, CStringCountMap& map) {
|
|||
for (auto& entry : entries) {
|
||||
CountBasePtr& thenCount = entry->value();
|
||||
RootedValue thenReport(cx);
|
||||
if (!thenCount->report(&thenReport))
|
||||
if (!thenCount->report(cx, &thenReport))
|
||||
return nullptr;
|
||||
|
||||
const char* name = entry->key();
|
||||
|
@ -365,10 +362,8 @@ class ByObjectClass : public CountType {
|
|||
CountTypePtr otherType;
|
||||
|
||||
public:
|
||||
ByObjectClass(Census& census,
|
||||
CountTypePtr& classesType,
|
||||
CountTypePtr& otherType)
|
||||
: CountType(census),
|
||||
ByObjectClass(CountTypePtr& classesType, CountTypePtr& otherType)
|
||||
: CountType(),
|
||||
classesType(Move(classesType)),
|
||||
otherType(Move(otherType))
|
||||
{ }
|
||||
|
@ -380,8 +375,8 @@ class ByObjectClass : public CountType {
|
|||
|
||||
CountBasePtr makeCount() override;
|
||||
void traceCount(CountBase& countBase, JSTracer* trc) override;
|
||||
bool count(CountBase& countBase, const Node& node) override;
|
||||
bool report(CountBase& countBase, MutableHandleValue report) override;
|
||||
bool count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node) override;
|
||||
bool report(JSContext* cx, CountBase& countBase, MutableHandleValue report) override;
|
||||
};
|
||||
|
||||
CountBasePtr
|
||||
|
@ -391,7 +386,7 @@ ByObjectClass::makeCount()
|
|||
if (!otherCount)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<Count> count(census.new_<Count>(*this, otherCount));
|
||||
UniquePtr<Count> count(js_new<Count>(*this, otherCount));
|
||||
if (!count || !count->init())
|
||||
return nullptr;
|
||||
|
||||
|
@ -408,14 +403,14 @@ ByObjectClass::traceCount(CountBase& countBase, JSTracer* trc)
|
|||
}
|
||||
|
||||
bool
|
||||
ByObjectClass::count(CountBase& countBase, const Node& node)
|
||||
ByObjectClass::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
count.total_++;
|
||||
|
||||
const char* className = node.jsObjectClassName();
|
||||
if (!className)
|
||||
return count.other->count(node);
|
||||
return count.other->count(mallocSizeOf, node);
|
||||
|
||||
Table::AddPtr p = count.table.lookupForAdd(className);
|
||||
if (!p) {
|
||||
|
@ -423,21 +418,20 @@ ByObjectClass::count(CountBase& countBase, const Node& node)
|
|||
if (!classCount || !count.table.add(p, className, Move(classCount)))
|
||||
return false;
|
||||
}
|
||||
return p->value()->count(node);
|
||||
return p->value()->count(mallocSizeOf, node);
|
||||
}
|
||||
|
||||
bool
|
||||
ByObjectClass::report(CountBase& countBase, MutableHandleValue report)
|
||||
ByObjectClass::report(JSContext* cx, CountBase& countBase, MutableHandleValue report)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
JSContext* cx = census.cx;
|
||||
|
||||
RootedPlainObject obj(cx, cStringCountMapToObject(cx, count.table));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
RootedValue otherReport(cx);
|
||||
if (!count.other->report(&otherReport) ||
|
||||
if (!count.other->report(cx, &otherReport) ||
|
||||
!DefineProperty(cx, obj, cx->names().other, otherReport))
|
||||
return false;
|
||||
|
||||
|
@ -466,8 +460,8 @@ class ByUbinodeType : public CountType {
|
|||
CountTypePtr entryType;
|
||||
|
||||
public:
|
||||
ByUbinodeType(Census& census, CountTypePtr& entryType)
|
||||
: CountType(census),
|
||||
explicit ByUbinodeType(CountTypePtr& entryType)
|
||||
: CountType(),
|
||||
entryType(Move(entryType))
|
||||
{ }
|
||||
|
||||
|
@ -478,14 +472,14 @@ class ByUbinodeType : public CountType {
|
|||
|
||||
CountBasePtr makeCount() override;
|
||||
void traceCount(CountBase& countBase, JSTracer* trc) override;
|
||||
bool count(CountBase& countBase, const Node& node) override;
|
||||
bool report(CountBase& countBase, MutableHandleValue report) override;
|
||||
bool count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node) override;
|
||||
bool report(JSContext* cx, CountBase& countBase, MutableHandleValue report) override;
|
||||
};
|
||||
|
||||
CountBasePtr
|
||||
ByUbinodeType::makeCount()
|
||||
{
|
||||
UniquePtr<Count> count(census.new_<Count>(*this));
|
||||
UniquePtr<Count> count(js_new<Count>(*this));
|
||||
if (!count || !count->init())
|
||||
return nullptr;
|
||||
|
||||
|
@ -501,7 +495,7 @@ ByUbinodeType::traceCount(CountBase& countBase, JSTracer* trc)
|
|||
}
|
||||
|
||||
bool
|
||||
ByUbinodeType::count(CountBase& countBase, const Node& node)
|
||||
ByUbinodeType::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
count.total_++;
|
||||
|
@ -514,14 +508,13 @@ ByUbinodeType::count(CountBase& countBase, const Node& node)
|
|||
if (!typesCount || !count.table.add(p, key, Move(typesCount)))
|
||||
return false;
|
||||
}
|
||||
return p->value()->count(node);
|
||||
return p->value()->count(mallocSizeOf, node);
|
||||
}
|
||||
|
||||
bool
|
||||
ByUbinodeType::report(CountBase& countBase, MutableHandleValue report)
|
||||
ByUbinodeType::report(JSContext* cx, CountBase& countBase, MutableHandleValue report)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
JSContext* cx = census.cx;
|
||||
|
||||
// Build a vector of pointers to entries; sort by total; and then use
|
||||
// that to build the result object. This makes the ordering of entries
|
||||
|
@ -541,7 +534,7 @@ ByUbinodeType::report(CountBase& countBase, MutableHandleValue report)
|
|||
Entry& entry = **entryPtr;
|
||||
CountBasePtr& typeCount = entry.value();
|
||||
RootedValue typeReport(cx);
|
||||
if (!typeCount->report(&typeReport))
|
||||
if (!typeCount->report(cx, &typeReport))
|
||||
return false;
|
||||
|
||||
const char16_t* name = entry.key();
|
||||
|
@ -609,8 +602,8 @@ class ByAllocationStack : public CountType {
|
|||
CountTypePtr noStackType;
|
||||
|
||||
public:
|
||||
ByAllocationStack(Census& census, CountTypePtr& entryType, CountTypePtr& noStackType)
|
||||
: CountType(census),
|
||||
ByAllocationStack(CountTypePtr& entryType, CountTypePtr& noStackType)
|
||||
: CountType(),
|
||||
entryType(Move(entryType)),
|
||||
noStackType(Move(noStackType))
|
||||
{ }
|
||||
|
@ -622,8 +615,8 @@ class ByAllocationStack : public CountType {
|
|||
|
||||
CountBasePtr makeCount() override;
|
||||
void traceCount(CountBase& countBase, JSTracer* trc) override;
|
||||
bool count(CountBase& countBase, const Node& node) override;
|
||||
bool report(CountBase& countBase, MutableHandleValue report) override;
|
||||
bool count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node) override;
|
||||
bool report(JSContext* cx, CountBase& countBase, MutableHandleValue report) override;
|
||||
};
|
||||
|
||||
CountBasePtr
|
||||
|
@ -633,7 +626,7 @@ ByAllocationStack::makeCount()
|
|||
if (!noStackCount)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<Count> count(census.new_<Count>(*this, noStackCount));
|
||||
UniquePtr<Count> count(js_new<Count>(*this, noStackCount));
|
||||
if (!count || !count->init())
|
||||
return nullptr;
|
||||
return CountBasePtr(count.release());
|
||||
|
@ -657,7 +650,7 @@ ByAllocationStack::traceCount(CountBase& countBase, JSTracer* trc)
|
|||
}
|
||||
|
||||
bool
|
||||
ByAllocationStack::count(CountBase& countBase, const Node& node)
|
||||
ByAllocationStack::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
count.total_++;
|
||||
|
@ -673,18 +666,17 @@ ByAllocationStack::count(CountBase& countBase, const Node& node)
|
|||
return false;
|
||||
}
|
||||
MOZ_ASSERT(p);
|
||||
return p->value()->count(node);
|
||||
return p->value()->count(mallocSizeOf, node);
|
||||
}
|
||||
|
||||
// Otherwise, count it in the "no stack" category.
|
||||
return count.noStack->count(node);
|
||||
return count.noStack->count(mallocSizeOf, node);
|
||||
}
|
||||
|
||||
bool
|
||||
ByAllocationStack::report(CountBase& countBase, MutableHandleValue report)
|
||||
ByAllocationStack::report(JSContext* cx, CountBase& countBase, MutableHandleValue report)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
JSContext* cx = census.cx;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Check that nothing rehashes our table while we hold pointers into it.
|
||||
|
@ -719,7 +711,7 @@ ByAllocationStack::report(CountBase& countBase, MutableHandleValue report)
|
|||
|
||||
CountBasePtr& stackCount = entry.value();
|
||||
RootedValue stackReport(cx);
|
||||
if (!stackCount->report(&stackReport))
|
||||
if (!stackCount->report(cx, &stackReport))
|
||||
return false;
|
||||
|
||||
if (!MapObject::set(cx, map, stackVal, stackReport))
|
||||
|
@ -728,7 +720,7 @@ ByAllocationStack::report(CountBase& countBase, MutableHandleValue report)
|
|||
|
||||
if (count.noStack->total_ > 0) {
|
||||
RootedValue noStackReport(cx);
|
||||
if (!count.noStack->report(&noStackReport))
|
||||
if (!count.noStack->report(cx, &noStackReport))
|
||||
return false;
|
||||
RootedValue noStack(cx, StringValue(cx->names().noStack));
|
||||
if (!MapObject::set(cx, map, noStack, noStackReport))
|
||||
|
@ -767,10 +759,8 @@ class ByFilename : public CountType {
|
|||
CountTypePtr noFilenameType;
|
||||
|
||||
public:
|
||||
ByFilename(Census& census,
|
||||
CountTypePtr& thenType,
|
||||
CountTypePtr& noFilenameType)
|
||||
: CountType(census),
|
||||
ByFilename(CountTypePtr& thenType, CountTypePtr& noFilenameType)
|
||||
: CountType(),
|
||||
thenType(Move(thenType)),
|
||||
noFilenameType(Move(noFilenameType))
|
||||
{ }
|
||||
|
@ -782,8 +772,8 @@ class ByFilename : public CountType {
|
|||
|
||||
CountBasePtr makeCount() override;
|
||||
void traceCount(CountBase& countBase, JSTracer* trc) override;
|
||||
bool count(CountBase& countBase, const Node& node) override;
|
||||
bool report(CountBase& countBase, MutableHandleValue report) override;
|
||||
bool count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node) override;
|
||||
bool report(JSContext* cx, CountBase& countBase, MutableHandleValue report) override;
|
||||
};
|
||||
|
||||
CountBasePtr
|
||||
|
@ -797,7 +787,7 @@ ByFilename::makeCount()
|
|||
if (!noFilenameCount)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<Count> count(census.new_<Count>(*this, Move(thenCount), Move(noFilenameCount)));
|
||||
UniquePtr<Count> count(js_new<Count>(*this, Move(thenCount), Move(noFilenameCount)));
|
||||
if (!count || !count->init())
|
||||
return nullptr;
|
||||
|
||||
|
@ -814,14 +804,14 @@ ByFilename::traceCount(CountBase& countBase, JSTracer* trc)
|
|||
}
|
||||
|
||||
bool
|
||||
ByFilename::count(CountBase& countBase, const Node& node)
|
||||
ByFilename::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
count.total_++;
|
||||
|
||||
const char* filename = node.scriptFilename();
|
||||
if (!filename)
|
||||
return count.noFilename->count(node);
|
||||
return count.noFilename->count(mallocSizeOf, node);
|
||||
|
||||
Table::AddPtr p = count.table.lookupForAdd(filename);
|
||||
if (!p) {
|
||||
|
@ -829,21 +819,20 @@ ByFilename::count(CountBase& countBase, const Node& node)
|
|||
if (!thenCount || !count.table.add(p, filename, Move(thenCount)))
|
||||
return false;
|
||||
}
|
||||
return p->value()->count(node);
|
||||
return p->value()->count(mallocSizeOf, node);
|
||||
}
|
||||
|
||||
bool
|
||||
ByFilename::report(CountBase& countBase, MutableHandleValue report)
|
||||
ByFilename::report(JSContext* cx, CountBase& countBase, MutableHandleValue report)
|
||||
{
|
||||
Count& count = static_cast<Count&>(countBase);
|
||||
JSContext* cx = census.cx;
|
||||
|
||||
RootedPlainObject obj(cx, cStringCountMapToObject(cx, count.table));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
RootedValue noFilenameReport(cx);
|
||||
if (!count.noFilename->report(&noFilenameReport) ||
|
||||
if (!count.noFilename->report(cx, &noFilenameReport) ||
|
||||
!DefineProperty(cx, obj, cx->names().noFilename, noFilenameReport))
|
||||
{
|
||||
return false;
|
||||
|
@ -876,11 +865,11 @@ CensusHandler::operator() (BreadthFirst<CensusHandler>& traversal,
|
|||
Zone* zone = referent.zone();
|
||||
|
||||
if (census.targetZones.count() == 0 || census.targetZones.has(zone))
|
||||
return rootCount->count(referent);
|
||||
return rootCount->count(mallocSizeOf, referent);
|
||||
|
||||
if (zone == census.atomsZone) {
|
||||
traversal.abandonReferent();
|
||||
return rootCount->count(referent);
|
||||
return rootCount->count(mallocSizeOf, referent);
|
||||
}
|
||||
|
||||
traversal.abandonReferent();
|
||||
|
@ -890,26 +879,21 @@ CensusHandler::operator() (BreadthFirst<CensusHandler>& traversal,
|
|||
|
||||
/*** Parsing Breakdowns ***************************************************************************/
|
||||
|
||||
static CountTypePtr ParseBreakdown(Census& census, HandleValue breakdownValue);
|
||||
|
||||
static CountTypePtr
|
||||
ParseChildBreakdown(Census& census, HandleObject breakdown, PropertyName* prop)
|
||||
ParseChildBreakdown(JSContext* cx, HandleObject breakdown, PropertyName* prop)
|
||||
{
|
||||
JSContext* cx = census.cx;
|
||||
RootedValue v(cx);
|
||||
if (!GetProperty(cx, breakdown, breakdown, prop, &v))
|
||||
return nullptr;
|
||||
return ParseBreakdown(census, v);
|
||||
return ParseBreakdown(cx, v);
|
||||
}
|
||||
|
||||
static CountTypePtr
|
||||
ParseBreakdown(Census& census, HandleValue breakdownValue)
|
||||
CountTypePtr
|
||||
ParseBreakdown(JSContext* cx, HandleValue breakdownValue)
|
||||
{
|
||||
JSContext* cx = census.cx;
|
||||
|
||||
if (breakdownValue.isUndefined()) {
|
||||
// Construct the default type, { by: 'count' }
|
||||
CountTypePtr simple(census.new_<SimpleCount>(census));
|
||||
CountTypePtr simple(js_new<SimpleCount>());
|
||||
return simple;
|
||||
}
|
||||
|
||||
|
@ -967,75 +951,73 @@ ParseBreakdown(Census& census, HandleValue breakdownValue)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CountTypePtr simple(census.new_<SimpleCount>(census,
|
||||
labelUnique,
|
||||
ToBoolean(countValue),
|
||||
ToBoolean(bytesValue)));
|
||||
CountTypePtr simple(js_new<SimpleCount>(labelUnique,
|
||||
ToBoolean(countValue),
|
||||
ToBoolean(bytesValue)));
|
||||
return simple;
|
||||
}
|
||||
|
||||
if (StringEqualsAscii(by, "objectClass")) {
|
||||
CountTypePtr thenType(ParseChildBreakdown(census, breakdown, cx->names().then));
|
||||
CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
|
||||
if (!thenType)
|
||||
return nullptr;
|
||||
|
||||
CountTypePtr otherType(ParseChildBreakdown(census, breakdown, cx->names().other));
|
||||
CountTypePtr otherType(ParseChildBreakdown(cx, breakdown, cx->names().other));
|
||||
if (!otherType)
|
||||
return nullptr;
|
||||
|
||||
return CountTypePtr(census.new_<ByObjectClass>(census, thenType, otherType));
|
||||
return CountTypePtr(js_new<ByObjectClass>(thenType, otherType));
|
||||
}
|
||||
|
||||
if (StringEqualsAscii(by, "coarseType")) {
|
||||
CountTypePtr objectsType(ParseChildBreakdown(census, breakdown, cx->names().objects));
|
||||
CountTypePtr objectsType(ParseChildBreakdown(cx, breakdown, cx->names().objects));
|
||||
if (!objectsType)
|
||||
return nullptr;
|
||||
CountTypePtr scriptsType(ParseChildBreakdown(census, breakdown, cx->names().scripts));
|
||||
CountTypePtr scriptsType(ParseChildBreakdown(cx, breakdown, cx->names().scripts));
|
||||
if (!scriptsType)
|
||||
return nullptr;
|
||||
CountTypePtr stringsType(ParseChildBreakdown(census, breakdown, cx->names().strings));
|
||||
CountTypePtr stringsType(ParseChildBreakdown(cx, breakdown, cx->names().strings));
|
||||
if (!stringsType)
|
||||
return nullptr;
|
||||
CountTypePtr otherType(ParseChildBreakdown(census, breakdown, cx->names().other));
|
||||
CountTypePtr otherType(ParseChildBreakdown(cx, breakdown, cx->names().other));
|
||||
if (!otherType)
|
||||
return nullptr;
|
||||
|
||||
return CountTypePtr(census.new_<ByCoarseType>(census,
|
||||
objectsType,
|
||||
scriptsType,
|
||||
stringsType,
|
||||
otherType));
|
||||
return CountTypePtr(js_new<ByCoarseType>(objectsType,
|
||||
scriptsType,
|
||||
stringsType,
|
||||
otherType));
|
||||
}
|
||||
|
||||
if (StringEqualsAscii(by, "internalType")) {
|
||||
CountTypePtr thenType(ParseChildBreakdown(census, breakdown, cx->names().then));
|
||||
CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
|
||||
if (!thenType)
|
||||
return nullptr;
|
||||
|
||||
return CountTypePtr(census.new_<ByUbinodeType>(census, thenType));
|
||||
return CountTypePtr(js_new<ByUbinodeType>(thenType));
|
||||
}
|
||||
|
||||
if (StringEqualsAscii(by, "allocationStack")) {
|
||||
CountTypePtr thenType(ParseChildBreakdown(census, breakdown, cx->names().then));
|
||||
CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
|
||||
if (!thenType)
|
||||
return nullptr;
|
||||
CountTypePtr noStackType(ParseChildBreakdown(census, breakdown, cx->names().noStack));
|
||||
CountTypePtr noStackType(ParseChildBreakdown(cx, breakdown, cx->names().noStack));
|
||||
if (!noStackType)
|
||||
return nullptr;
|
||||
|
||||
return CountTypePtr(census.new_<ByAllocationStack>(census, thenType, noStackType));
|
||||
return CountTypePtr(js_new<ByAllocationStack>(thenType, noStackType));
|
||||
}
|
||||
|
||||
if (StringEqualsAscii(by, "filename")) {
|
||||
CountTypePtr thenType(ParseChildBreakdown(census, breakdown, cx->names().then));
|
||||
CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
|
||||
if (!thenType)
|
||||
return nullptr;
|
||||
|
||||
CountTypePtr noFilenameType(ParseChildBreakdown(census, breakdown, cx->names().noFilename));
|
||||
CountTypePtr noFilenameType(ParseChildBreakdown(cx, breakdown, cx->names().noFilename));
|
||||
if (!noFilenameType)
|
||||
return nullptr;
|
||||
|
||||
return CountTypePtr(census.new_<ByFilename>(census, thenType, noFilenameType));
|
||||
return CountTypePtr(js_new<ByFilename>(thenType, noFilenameType));
|
||||
}
|
||||
|
||||
// We didn't recognize the breakdown type; complain.
|
||||
|
@ -1059,25 +1041,22 @@ ParseBreakdown(Census& census, HandleValue breakdownValue)
|
|||
// other: { by: "internalType" }
|
||||
// }
|
||||
static CountTypePtr
|
||||
GetDefaultBreakdown(Census& census)
|
||||
GetDefaultBreakdown()
|
||||
{
|
||||
CountTypePtr byClass(census.new_<SimpleCount>(census));
|
||||
CountTypePtr byClassElse(census.new_<SimpleCount>(census));
|
||||
CountTypePtr objects(census.new_<ByObjectClass>(census,
|
||||
byClass,
|
||||
byClassElse));
|
||||
CountTypePtr byClass(js_new<SimpleCount>());
|
||||
CountTypePtr byClassElse(js_new<SimpleCount>());
|
||||
CountTypePtr objects(js_new<ByObjectClass>(byClass, byClassElse));
|
||||
|
||||
CountTypePtr scripts(census.new_<SimpleCount>(census));
|
||||
CountTypePtr strings(census.new_<SimpleCount>(census));
|
||||
CountTypePtr scripts(js_new<SimpleCount>());
|
||||
CountTypePtr strings(js_new<SimpleCount>());
|
||||
|
||||
CountTypePtr byType(census.new_<SimpleCount>(census));
|
||||
CountTypePtr other(census.new_<ByUbinodeType>(census, byType));
|
||||
CountTypePtr byType(js_new<SimpleCount>());
|
||||
CountTypePtr other(js_new<ByUbinodeType>(byType));
|
||||
|
||||
return CountTypePtr(census.new_<ByCoarseType>(census,
|
||||
objects,
|
||||
scripts,
|
||||
strings,
|
||||
other));
|
||||
return CountTypePtr(js_new<ByCoarseType>(objects,
|
||||
scripts,
|
||||
strings,
|
||||
other));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1088,8 +1067,8 @@ ParseCensusOptions(JSContext* cx, Census& census, HandleObject options, CountTyp
|
|||
return false;
|
||||
|
||||
outResult = breakdown.isUndefined()
|
||||
? GetDefaultBreakdown(census)
|
||||
: ParseBreakdown(census, breakdown);
|
||||
? GetDefaultBreakdown()
|
||||
: ParseBreakdown(cx, breakdown);
|
||||
return !!outResult;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче