зеркало из https://github.com/mozilla/gecko-dev.git
Bug 702300 (part 7) - Add the "compartments" multi-reporter. r=billm.
--HG-- extra : rebase_source : e45e59bd8657197dbd61c257f46ad6396cdda3c3
This commit is contained in:
Родитель
f9b9961d25
Коммит
d655a2dc1d
|
@ -55,10 +55,10 @@ namespace JS {
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CompartmentStatsCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
StatsCompartmentCallback(JSContext *cx, void *data, JSCompartment *compartment)
|
||||||
{
|
{
|
||||||
// Append a new CompartmentStats to the vector.
|
// Append a new CompartmentStats to the vector.
|
||||||
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
|
RuntimeStats *rtStats = static_cast<RuntimeStats *>(data);
|
||||||
|
|
||||||
// CollectRuntimeStats reserves enough space.
|
// CollectRuntimeStats reserves enough space.
|
||||||
MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
|
MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
|
||||||
|
@ -75,30 +75,21 @@ CompartmentStatsCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ExplicitNonHeapCompartmentCallback(JSContext *cx, void *data, JSCompartment *compartment)
|
StatsChunkCallback(JSContext *cx, void *data, gc::Chunk *chunk)
|
||||||
{
|
|
||||||
#ifdef JS_METHODJIT
|
|
||||||
size_t *n = static_cast<size_t *>(data);
|
|
||||||
*n += compartment->sizeOfMjitCode();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ChunkCallback(JSContext *cx, void *vdata, gc::Chunk *chunk)
|
|
||||||
{
|
{
|
||||||
// Nb: This function is only called for dirty chunks, which is why we
|
// Nb: This function is only called for dirty chunks, which is why we
|
||||||
// increment gcHeapChunkDirtyDecommitted.
|
// increment gcHeapChunkDirtyDecommitted.
|
||||||
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
|
RuntimeStats *rtStats = static_cast<RuntimeStats *>(data);
|
||||||
for (size_t i = 0; i < gc::ArenasPerChunk; i++)
|
for (size_t i = 0; i < gc::ArenasPerChunk; i++)
|
||||||
if (chunk->decommittedArenas.get(i))
|
if (chunk->decommittedArenas.get(i))
|
||||||
rtStats->gcHeapChunkDirtyDecommitted += gc::ArenaSize;
|
rtStats->gcHeapChunkDirtyDecommitted += gc::ArenaSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ArenaCallback(JSContext *cx, void *vdata, gc::Arena *arena,
|
StatsArenaCallback(JSContext *cx, void *data, gc::Arena *arena,
|
||||||
JSGCTraceKind traceKind, size_t thingSize)
|
JSGCTraceKind traceKind, size_t thingSize)
|
||||||
{
|
{
|
||||||
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
|
RuntimeStats *rtStats = static_cast<RuntimeStats *>(data);
|
||||||
|
|
||||||
rtStats->currCompartmentStats->gcHeapArenaHeaders += sizeof(gc::ArenaHeader);
|
rtStats->currCompartmentStats->gcHeapArenaHeaders += sizeof(gc::ArenaHeader);
|
||||||
size_t allocationSpace = arena->thingsSpan(thingSize);
|
size_t allocationSpace = arena->thingsSpan(thingSize);
|
||||||
|
@ -107,15 +98,15 @@ ArenaCallback(JSContext *cx, void *vdata, gc::Arena *arena,
|
||||||
// We don't call the callback on unused things. So we compute the
|
// We don't call the callback on unused things. So we compute the
|
||||||
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
|
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
|
||||||
// We do this by setting arenaUnused to maxArenaUnused here, and then
|
// We do this by setting arenaUnused to maxArenaUnused here, and then
|
||||||
// subtracting thingSize for every used cell, in CellCallback().
|
// subtracting thingSize for every used cell, in StatsCellCallback().
|
||||||
rtStats->currCompartmentStats->gcHeapArenaUnused += allocationSpace;
|
rtStats->currCompartmentStats->gcHeapArenaUnused += allocationSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
StatsCellCallback(JSContext *cx, void *data, void *thing, JSGCTraceKind traceKind,
|
||||||
size_t thingSize)
|
size_t thingSize)
|
||||||
{
|
{
|
||||||
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
|
RuntimeStats *rtStats = static_cast<RuntimeStats *>(data);
|
||||||
CompartmentStats *cStats = rtStats->currCompartmentStats;
|
CompartmentStats *cStats = rtStats->currCompartmentStats;
|
||||||
switch (traceKind) {
|
switch (traceKind) {
|
||||||
case JSTRACE_OBJECT:
|
case JSTRACE_OBJECT:
|
||||||
|
@ -185,7 +176,7 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Yes, this is a subtraction: see ArenaCallback() for details.
|
// Yes, this is a subtraction: see StatsArenaCallback() for details.
|
||||||
cStats->gcHeapArenaUnused -= thingSize;
|
cStats->gcHeapArenaUnused -= thingSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,9 +201,9 @@ CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
|
||||||
rtStats->gcHeapChunkTotal =
|
rtStats->gcHeapChunkTotal =
|
||||||
size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
|
size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
|
||||||
|
|
||||||
IterateCompartmentsArenasCells(cx, rtStats, CompartmentStatsCallback,
|
IterateCompartmentsArenasCells(cx, rtStats, StatsCompartmentCallback,
|
||||||
ArenaCallback, CellCallback);
|
StatsArenaCallback, StatsCellCallback);
|
||||||
IterateChunks(cx, rtStats, ChunkCallback);
|
IterateChunks(cx, rtStats, StatsChunkCallback);
|
||||||
|
|
||||||
rtStats->runtimeObject = rtStats->mallocSizeOf(rt);
|
rtStats->runtimeObject = rtStats->mallocSizeOf(rt);
|
||||||
|
|
||||||
|
@ -308,6 +299,15 @@ CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ExplicitNonHeapCompartmentCallback(JSContext *cx, void *data, JSCompartment *compartment)
|
||||||
|
{
|
||||||
|
#ifdef JS_METHODJIT
|
||||||
|
size_t *n = static_cast<size_t *>(data);
|
||||||
|
*n += compartment->sizeOfMjitCode();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
GetExplicitNonHeapForRuntime(JSRuntime *rt, int64_t *amount,
|
GetExplicitNonHeapForRuntime(JSRuntime *rt, int64_t *amount,
|
||||||
JSMallocSizeOfFun mallocSizeOf)
|
JSMallocSizeOfFun mallocSizeOf)
|
||||||
|
@ -325,7 +325,7 @@ GetExplicitNonHeapForRuntime(JSRuntime *rt, int64_t *amount,
|
||||||
|
|
||||||
// explicit/<compartment>/mjit-code
|
// explicit/<compartment>/mjit-code
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
IterateCompartments(cx, &n, ExplicitNonHeapCompartmentCallback);
|
JS_IterateCompartments(cx, &n, ExplicitNonHeapCompartmentCallback);
|
||||||
*amount += n;
|
*amount += n;
|
||||||
|
|
||||||
// explicit/runtime/regexp-code
|
// explicit/runtime/regexp-code
|
||||||
|
@ -346,6 +346,28 @@ GetExplicitNonHeapForRuntime(JSRuntime *rt, int64_t *amount,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(size_t)
|
||||||
|
SystemCompartmentCount(const JSRuntime *rt)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for (size_t i = 0; i < rt->compartments.length(); i++) {
|
||||||
|
if (rt->compartments[i]->isSystemCompartment)
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(size_t)
|
||||||
|
UserCompartmentCount(const JSRuntime *rt)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for (size_t i = 0; i < rt->compartments.length(); i++) {
|
||||||
|
if (!rt->compartments[i]->isSystemCompartment)
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace JS
|
} // namespace JS
|
||||||
|
|
||||||
#endif // JS_THREADSAFE
|
#endif // JS_THREADSAFE
|
||||||
|
|
|
@ -996,30 +996,6 @@ JS_SetRuntimePrivate(JSRuntime *rt, void *data)
|
||||||
rt->data = data;
|
rt->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(size_t)
|
|
||||||
JS::SystemCompartmentCount(const JSRuntime *rt)
|
|
||||||
{
|
|
||||||
size_t n = 0;
|
|
||||||
for (size_t i = 0; i < rt->compartments.length(); i++) {
|
|
||||||
if (rt->compartments[i]->isSystemCompartment) {
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(size_t)
|
|
||||||
JS::UserCompartmentCount(const JSRuntime *rt)
|
|
||||||
{
|
|
||||||
size_t n = 0;
|
|
||||||
for (size_t i = 0; i < rt->compartments.length(); i++) {
|
|
||||||
if (!rt->compartments[i]->isSystemCompartment) {
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
static void
|
static void
|
||||||
StartRequest(JSContext *cx)
|
StartRequest(JSContext *cx)
|
||||||
|
|
|
@ -2690,6 +2690,18 @@ class JS_PUBLIC_API(JSAutoEnterCompartment)
|
||||||
JS_BEGIN_EXTERN_C
|
JS_BEGIN_EXTERN_C
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void (*JSIterateCompartmentCallback)(JSContext *cx, void *data,
|
||||||
|
JSCompartment *compartment);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function calls |compartmentCallback| on every compartment. Beware that
|
||||||
|
* there is no guarantee that the compartment will survive after the callback
|
||||||
|
* returns.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(void)
|
||||||
|
JS_IterateCompartments(JSContext *cx, void *data,
|
||||||
|
JSIterateCompartmentCallback compartmentCallback);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSObject *)
|
extern JS_PUBLIC_API(JSObject *)
|
||||||
JS_GetGlobalObject(JSContext *cx);
|
JS_GetGlobalObject(JSContext *cx);
|
||||||
|
|
||||||
|
|
|
@ -3789,31 +3789,9 @@ struct IterateCellCallbackOp
|
||||||
void operator()(Cell *cell) { (*callback)(cx, data, cell, traceKind, thingSize); }
|
void operator()(Cell *cell) { (*callback)(cx, data, cell, traceKind, thingSize); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
|
||||||
IterateCompartments(JSContext *cx, void *data,
|
|
||||||
IterateCompartmentCallback compartmentCallback)
|
|
||||||
{
|
|
||||||
CHECK_REQUEST(cx);
|
|
||||||
|
|
||||||
JSRuntime *rt = cx->runtime;
|
|
||||||
JS_ASSERT(!rt->gcRunning);
|
|
||||||
|
|
||||||
AutoLockGC lock(rt);
|
|
||||||
AutoHeapSession session(cx);
|
|
||||||
#ifdef JS_THREADSAFE
|
|
||||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
|
||||||
#endif
|
|
||||||
AutoUnlockGC unlock(rt);
|
|
||||||
|
|
||||||
AutoCopyFreeListToArenas copy(rt);
|
|
||||||
for (CompartmentsIter c(rt); !c.done(); c.next()) {
|
|
||||||
(*compartmentCallback)(cx, data, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IterateCompartmentsArenasCells(JSContext *cx, void *data,
|
IterateCompartmentsArenasCells(JSContext *cx, void *data,
|
||||||
IterateCompartmentCallback compartmentCallback,
|
JSIterateCompartmentCallback compartmentCallback,
|
||||||
IterateArenaCallback arenaCallback,
|
IterateArenaCallback arenaCallback,
|
||||||
IterateCellCallback cellCallback)
|
IterateCellCallback cellCallback)
|
||||||
{
|
{
|
||||||
|
@ -4558,6 +4536,27 @@ PurgePCCounts(JSContext *cx)
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void)
|
||||||
|
JS_IterateCompartments(JSContext *cx, void *data,
|
||||||
|
JSIterateCompartmentCallback compartmentCallback)
|
||||||
|
{
|
||||||
|
CHECK_REQUEST(cx);
|
||||||
|
|
||||||
|
JSRuntime *rt = cx->runtime;
|
||||||
|
JS_ASSERT(!rt->gcRunning);
|
||||||
|
|
||||||
|
AutoLockGC lock(rt);
|
||||||
|
AutoHeapSession session(cx);
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||||
|
#endif
|
||||||
|
AutoUnlockGC unlock(rt);
|
||||||
|
|
||||||
|
AutoCopyFreeListToArenas copy(rt);
|
||||||
|
for (CompartmentsIter c(rt); !c.done(); c.next())
|
||||||
|
(*compartmentCallback)(cx, data, c);
|
||||||
|
}
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
extern size_t sE4XObjectsCreated;
|
extern size_t sE4XObjectsCreated;
|
||||||
|
|
||||||
|
|
|
@ -1896,19 +1896,12 @@ struct FullGCMarker : public GCMarker {
|
||||||
void
|
void
|
||||||
MarkStackRangeConservatively(JSTracer *trc, Value *begin, Value *end);
|
MarkStackRangeConservatively(JSTracer *trc, Value *begin, Value *end);
|
||||||
|
|
||||||
typedef void (*IterateCompartmentCallback)(JSContext *cx, void *data, JSCompartment *compartment);
|
|
||||||
typedef void (*IterateChunkCallback)(JSContext *cx, void *data, gc::Chunk *chunk);
|
typedef void (*IterateChunkCallback)(JSContext *cx, void *data, gc::Chunk *chunk);
|
||||||
typedef void (*IterateArenaCallback)(JSContext *cx, void *data, gc::Arena *arena,
|
typedef void (*IterateArenaCallback)(JSContext *cx, void *data, gc::Arena *arena,
|
||||||
JSGCTraceKind traceKind, size_t thingSize);
|
JSGCTraceKind traceKind, size_t thingSize);
|
||||||
typedef void (*IterateCellCallback)(JSContext *cx, void *data, void *thing,
|
typedef void (*IterateCellCallback)(JSContext *cx, void *data, void *thing,
|
||||||
JSGCTraceKind traceKind, size_t thingSize);
|
JSGCTraceKind traceKind, size_t thingSize);
|
||||||
|
|
||||||
/*
|
|
||||||
* This function calls |compartmentCallback| on every compartment.
|
|
||||||
*/
|
|
||||||
extern JS_FRIEND_API(void)
|
|
||||||
IterateCompartments(JSContext *cx, void *data,
|
|
||||||
IterateCompartmentCallback compartmentCallback);
|
|
||||||
/*
|
/*
|
||||||
* This function calls |compartmentCallback| on every compartment,
|
* This function calls |compartmentCallback| on every compartment,
|
||||||
* |arenaCallback| on every in-use arena, and |cellCallback| on every in-use
|
* |arenaCallback| on every in-use arena, and |cellCallback| on every in-use
|
||||||
|
@ -1916,7 +1909,7 @@ IterateCompartments(JSContext *cx, void *data,
|
||||||
*/
|
*/
|
||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(void)
|
||||||
IterateCompartmentsArenasCells(JSContext *cx, void *data,
|
IterateCompartmentsArenasCells(JSContext *cx, void *data,
|
||||||
IterateCompartmentCallback compartmentCallback,
|
JSIterateCompartmentCallback compartmentCallback,
|
||||||
IterateArenaCallback arenaCallback,
|
IterateArenaCallback arenaCallback,
|
||||||
IterateCellCallback cellCallback);
|
IterateCellCallback cellCallback);
|
||||||
|
|
||||||
|
|
|
@ -1211,7 +1211,7 @@ XPCJSRuntime::~XPCJSRuntime()
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
||||||
void*
|
void*
|
||||||
GetCompartmentName(JSContext *cx, JSCompartment *c)
|
GetCompartmentNameHelper(JSContext *cx, JSCompartment *c, bool getAddress)
|
||||||
{
|
{
|
||||||
nsCString* name = new nsCString();
|
nsCString* name = new nsCString();
|
||||||
if (js::IsAtomsCompartmentFor(cx, c)) {
|
if (js::IsAtomsCompartmentFor(cx, c)) {
|
||||||
|
@ -1220,10 +1220,10 @@ GetCompartmentName(JSContext *cx, JSCompartment *c)
|
||||||
if (principals->codebase) {
|
if (principals->codebase) {
|
||||||
name->Assign(principals->codebase);
|
name->Assign(principals->codebase);
|
||||||
|
|
||||||
// If it's the system compartment, append the address.
|
// If it's the system compartment and |getAddress| is true, append
|
||||||
// This means that multiple system compartments (and there
|
// the address. This means that multiple system compartments (and
|
||||||
// can be many) can be distinguished.
|
// there can be many) can be distinguished.
|
||||||
if (js::IsSystemCompartment(c)) {
|
if (getAddress && js::IsSystemCompartment(c)) {
|
||||||
xpc::CompartmentPrivate *compartmentPrivate =
|
xpc::CompartmentPrivate *compartmentPrivate =
|
||||||
static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(cx, c));
|
static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(cx, c));
|
||||||
if (compartmentPrivate &&
|
if (compartmentPrivate &&
|
||||||
|
@ -1251,6 +1251,18 @@ GetCompartmentName(JSContext *cx, JSCompartment *c)
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
GetCompartmentName(JSContext *cx, JSCompartment *c)
|
||||||
|
{
|
||||||
|
return GetCompartmentNameHelper(cx, c, /* get address = */false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
GetCompartmentNameAndAddress(JSContext *cx, JSCompartment *c)
|
||||||
|
{
|
||||||
|
return GetCompartmentNameHelper(cx, c, /* get address = */true);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DestroyCompartmentName(void *string)
|
DestroyCompartmentName(void *string)
|
||||||
{
|
{
|
||||||
|
@ -1372,7 +1384,7 @@ GetJSUserCompartmentCount()
|
||||||
|
|
||||||
// Nb: js-system-compartment-count + js-user-compartment-count could be
|
// Nb: js-system-compartment-count + js-user-compartment-count could be
|
||||||
// different to the number of compartments reported by
|
// different to the number of compartments reported by
|
||||||
// XPConnectJSCompartmentsMultiReporter if a garbage collection occurred
|
// JSMemoryMultiReporter if a garbage collection occurred
|
||||||
// between them being consulted. We could move these reporters into
|
// between them being consulted. We could move these reporters into
|
||||||
// XPConnectJSCompartmentCount to avoid that problem, but then we couldn't
|
// XPConnectJSCompartmentCount to avoid that problem, but then we couldn't
|
||||||
// easily report them via telemetry, so we live with the small risk of
|
// easily report them via telemetry, so we live with the small risk of
|
||||||
|
@ -1705,7 +1717,7 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACStri
|
||||||
|
|
||||||
// gcTotal is the sum of everything we've reported for the GC heap. It
|
// gcTotal is the sum of everything we've reported for the GC heap. It
|
||||||
// should equal rtStats.gcHeapChunkTotal.
|
// should equal rtStats.gcHeapChunkTotal.
|
||||||
JS_ASSERT(gcTotal == rtStats.gcHeapChunkTotal);
|
JS_ASSERT(size_t(gcTotal) == rtStats.gcHeapChunkTotal);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace memory
|
} // namespace memory
|
||||||
|
@ -1714,7 +1726,77 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACStri
|
||||||
|
|
||||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
|
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
|
||||||
|
|
||||||
class XPConnectJSCompartmentsMultiReporter : public nsIMemoryMultiReporter
|
class JSCompartmentsMultiReporter : public nsIMemoryMultiReporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
NS_IMETHOD GetName(nsACString &name)
|
||||||
|
{
|
||||||
|
name.AssignLiteral("compartments");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef js::Vector<nsCString, 0, js::SystemAllocPolicy> Paths;
|
||||||
|
|
||||||
|
static void CompartmentCallback(JSContext *cx, void* data, JSCompartment *c)
|
||||||
|
{
|
||||||
|
Paths *paths = static_cast<Paths *>(data);
|
||||||
|
nsCString *name =
|
||||||
|
static_cast<nsCString *>(xpc::GetCompartmentName(cx, c));
|
||||||
|
nsCString path;
|
||||||
|
if (js::IsSystemCompartment(c))
|
||||||
|
path = NS_LITERAL_CSTRING("compartments/system/") + *name;
|
||||||
|
else
|
||||||
|
path = NS_LITERAL_CSTRING("compartments/user/") + *name;
|
||||||
|
if (!paths->append(path))
|
||||||
|
return; // silent failure, but it's very unlikely
|
||||||
|
|
||||||
|
xpc::DestroyCompartmentName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback,
|
||||||
|
nsISupports *closure)
|
||||||
|
{
|
||||||
|
// First we collect the compartment paths. Then we report them. Doing
|
||||||
|
// the two steps interleaved is a bad idea, because calling |callback|
|
||||||
|
// from within CompartmentCallback() leads to all manner of assertions.
|
||||||
|
|
||||||
|
// Collect.
|
||||||
|
XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance();
|
||||||
|
JSContext *cx = JS_NewContext(xpcrt->GetJSRuntime(), 0);
|
||||||
|
if (!cx)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
Paths paths;
|
||||||
|
JS_IterateCompartments(cx, &paths, CompartmentCallback);
|
||||||
|
JS_DestroyContextNoGC(cx);
|
||||||
|
|
||||||
|
// Report.
|
||||||
|
for (size_t i = 0; i < paths.length(); i++)
|
||||||
|
// These ones don't need a description, hence the "".
|
||||||
|
ReportMemory(paths[i],
|
||||||
|
nsIMemoryReporter::KIND_OTHER,
|
||||||
|
nsIMemoryReporter::UNITS_COUNT,
|
||||||
|
1, "", callback, closure);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
GetExplicitNonHeap(PRInt64 *n)
|
||||||
|
{
|
||||||
|
// This reporter does neither "explicit" nor NONHEAP measurements.
|
||||||
|
*n = 0;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_THREADSAFE_ISUPPORTS1(JSCompartmentsMultiReporter
|
||||||
|
, nsIMemoryMultiReporter
|
||||||
|
)
|
||||||
|
|
||||||
|
class JSMemoryMultiReporter : public nsIMemoryMultiReporter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
@ -1735,7 +1817,7 @@ public:
|
||||||
// the callback. Separating these steps is important because the
|
// the callback. Separating these steps is important because the
|
||||||
// callback may be a JS function, and executing JS while getting these
|
// callback may be a JS function, and executing JS while getting these
|
||||||
// stats seems like a bad idea.
|
// stats seems like a bad idea.
|
||||||
JS::RuntimeStats rtStats(JsMallocSizeOf, xpc::GetCompartmentName,
|
JS::RuntimeStats rtStats(JsMallocSizeOf, xpc::GetCompartmentNameAndAddress,
|
||||||
xpc::DestroyCompartmentName);
|
xpc::DestroyCompartmentName);
|
||||||
if (!JS::CollectRuntimeStats(xpcrt->GetJSRuntime(), &rtStats))
|
if (!JS::CollectRuntimeStats(xpcrt->GetJSRuntime(), &rtStats))
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -1861,7 +1943,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_THREADSAFE_ISUPPORTS1(XPConnectJSCompartmentsMultiReporter
|
NS_IMPL_THREADSAFE_ISUPPORTS1(JSMemoryMultiReporter
|
||||||
, nsIMemoryMultiReporter
|
, nsIMemoryMultiReporter
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2001,7 +2083,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
||||||
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
|
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
|
||||||
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount));
|
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount));
|
||||||
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));
|
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));
|
||||||
NS_RegisterMemoryMultiReporter(new XPConnectJSCompartmentsMultiReporter);
|
NS_RegisterMemoryMultiReporter(new JSMemoryMultiReporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,
|
if (!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче