mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
5ac27a163f
--HG-- rename : js/src/ETWProvider.man => js/src/devtools/ETWProvider.man rename : js/src/metrics/gc/README.txt => js/src/devtools/gc/README.txt rename : js/src/metrics/gc/gc-test.py => js/src/devtools/gc/gc-test.py rename : js/src/metrics/gc/tests/clock.js => js/src/devtools/gc/tests/clock.js rename : js/src/metrics/gc/tests/dslots.js => js/src/devtools/gc/tests/dslots.js rename : js/src/metrics/gc/tests/loops.js => js/src/devtools/gc/tests/loops.js rename : js/src/metrics/gc/tests/objGraph.js => js/src/devtools/gc/tests/objGraph.js rename : js/src/gnuplot/gcTimer.gnu => js/src/devtools/gnuplot/gcTimer.gnu rename : js/src/javascript-trace.d => js/src/devtools/javascript-trace.d rename : js/src/metrics/jint/sunspider/3d-cube.js => js/src/devtools/jint/sunspider/3d-cube.js rename : js/src/metrics/jint/sunspider/3d-morph.js => js/src/devtools/jint/sunspider/3d-morph.js rename : js/src/metrics/jint/sunspider/3d-raytrace.js => js/src/devtools/jint/sunspider/3d-raytrace.js rename : js/src/metrics/jint/sunspider/access-binary-trees.js => js/src/devtools/jint/sunspider/access-binary-trees.js rename : js/src/metrics/jint/sunspider/access-fannkuch.js => js/src/devtools/jint/sunspider/access-fannkuch.js rename : js/src/metrics/jint/sunspider/access-nbody.js => js/src/devtools/jint/sunspider/access-nbody.js rename : js/src/metrics/jint/sunspider/access-nsieve.js => js/src/devtools/jint/sunspider/access-nsieve.js rename : js/src/metrics/jint/sunspider/bitops-3bit-bits-in-byte.js => js/src/devtools/jint/sunspider/bitops-3bit-bits-in-byte.js rename : js/src/metrics/jint/sunspider/bitops-bits-in-byte.js => js/src/devtools/jint/sunspider/bitops-bits-in-byte.js rename : js/src/metrics/jint/sunspider/bitops-bitwise-and.js => js/src/devtools/jint/sunspider/bitops-bitwise-and.js rename : js/src/metrics/jint/sunspider/bitops-nsieve-bits.js => js/src/devtools/jint/sunspider/bitops-nsieve-bits.js rename : js/src/metrics/jint/sunspider/controlflow-recursive.js => js/src/devtools/jint/sunspider/controlflow-recursive.js rename : js/src/metrics/jint/sunspider/crypto-aes.js => js/src/devtools/jint/sunspider/crypto-aes.js rename : js/src/metrics/jint/sunspider/crypto-md5.js => js/src/devtools/jint/sunspider/crypto-md5.js rename : js/src/metrics/jint/sunspider/crypto-sha1.js => js/src/devtools/jint/sunspider/crypto-sha1.js rename : js/src/metrics/jint/sunspider/date-format-tofte.js => js/src/devtools/jint/sunspider/date-format-tofte.js rename : js/src/metrics/jint/sunspider/date-format-xparb.js => js/src/devtools/jint/sunspider/date-format-xparb.js rename : js/src/metrics/jint/sunspider/math-cordic.js => js/src/devtools/jint/sunspider/math-cordic.js rename : js/src/metrics/jint/sunspider/math-partial-sums.js => js/src/devtools/jint/sunspider/math-partial-sums.js rename : js/src/metrics/jint/sunspider/math-spectral-norm.js => js/src/devtools/jint/sunspider/math-spectral-norm.js rename : js/src/metrics/jint/sunspider/regexp-dna.js => js/src/devtools/jint/sunspider/regexp-dna.js rename : js/src/metrics/jint/sunspider/string-base64.js => js/src/devtools/jint/sunspider/string-base64.js rename : js/src/metrics/jint/sunspider/string-fasta.js => js/src/devtools/jint/sunspider/string-fasta.js rename : js/src/metrics/jint/sunspider/string-tagcloud.js => js/src/devtools/jint/sunspider/string-tagcloud.js rename : js/src/metrics/jint/sunspider/string-unpack-code.js => js/src/devtools/jint/sunspider/string-unpack-code.js rename : js/src/metrics/jint/sunspider/string-validate-input.js => js/src/devtools/jint/sunspider/string-validate-input.js rename : js/src/metrics/jint/treesearch.py => js/src/devtools/jint/treesearch.py rename : js/src/metrics/jint/v8/base.js => js/src/devtools/jint/v8/base.js rename : js/src/metrics/jint/v8/crypto.js => js/src/devtools/jint/v8/crypto.js rename : js/src/metrics/jint/v8/deltablue.js => js/src/devtools/jint/v8/deltablue.js rename : js/src/metrics/jint/v8/earley-boyer.js => js/src/devtools/jint/v8/earley-boyer.js rename : js/src/metrics/jint/v8/raytrace.js => js/src/devtools/jint/v8/raytrace.js rename : js/src/metrics/jint/v8/richards.js => js/src/devtools/jint/v8/richards.js rename : js/src/metrics/jint/v8/run-earley-boyer.js => js/src/devtools/jint/v8/run-earley-boyer.js rename : js/src/metrics/jint/v8/run-raytrace.js => js/src/devtools/jint/v8/run-raytrace.js rename : js/src/metrics/jint/v8/run-richards.js => js/src/devtools/jint/v8/run-richards.js rename : js/src/metrics/jint/v8/run.js => js/src/devtools/jint/v8/run.js rename : js/src/sharkctl.cpp => js/src/devtools/sharkctl.cpp rename : js/src/sharkctl.h => js/src/devtools/sharkctl.h rename : js/src/vprof/manifest.mk => js/src/devtools/vprof/manifest.mk rename : js/src/vprof/readme.txt => js/src/devtools/vprof/readme.txt rename : js/src/vprof/testVprofMT.c => js/src/devtools/vprof/testVprofMT.c rename : js/src/vprof/vprof.cpp => js/src/devtools/vprof/vprof.cpp rename : js/src/vprof/vprof.h => js/src/devtools/vprof/vprof.h rename : js/src/MemoryMetrics.cpp => js/src/jsmemorymetrics.cpp extra : rebase_source : b328f1463668e12052cb3d8af14d13c2b2f0f91d
302 lines
9.9 KiB
C++
302 lines
9.9 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "js/MemoryMetrics.h"
|
|
|
|
#include "mozilla/Assertions.h"
|
|
|
|
#include "jsapi.h"
|
|
#include "jscntxt.h"
|
|
#include "jscompartment.h"
|
|
#include "jsgc.h"
|
|
#include "jsobj.h"
|
|
#include "jsscope.h"
|
|
#include "jsscript.h"
|
|
|
|
#include "jsobjinlines.h"
|
|
|
|
#ifdef JS_THREADSAFE
|
|
|
|
namespace JS {
|
|
|
|
using namespace js;
|
|
|
|
typedef HashSet<ScriptSource *, DefaultHasher<ScriptSource *>, SystemAllocPolicy> SourceSet;
|
|
|
|
struct IteratorClosure
|
|
{
|
|
RuntimeStats *rtStats;
|
|
ObjectPrivateVisitor *opv;
|
|
SourceSet seenSources;
|
|
IteratorClosure(RuntimeStats *rt, ObjectPrivateVisitor *v) : rtStats(rt), opv(v) {}
|
|
bool init() {
|
|
return seenSources.init();
|
|
}
|
|
};
|
|
|
|
size_t
|
|
CompartmentStats::gcHeapThingsSize()
|
|
{
|
|
// These are just the GC-thing measurements.
|
|
size_t n = 0;
|
|
n += gcHeapObjectsNonFunction;
|
|
n += gcHeapObjectsFunction;
|
|
n += gcHeapStrings;
|
|
n += gcHeapShapesTree;
|
|
n += gcHeapShapesDict;
|
|
n += gcHeapShapesBase;
|
|
n += gcHeapScripts;
|
|
n += gcHeapTypeObjects;
|
|
#if JS_HAS_XML_SUPPORT
|
|
n += gcHeapXML;
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
size_t n2 = n;
|
|
n2 += gcHeapArenaAdmin;
|
|
n2 += gcHeapUnusedGcThings;
|
|
// These numbers should sum to a multiple of the arena size.
|
|
JS_ASSERT(n2 % gc::ArenaSize == 0);
|
|
#endif
|
|
|
|
return n;
|
|
}
|
|
|
|
static void
|
|
StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
|
|
{
|
|
// Append a new CompartmentStats to the vector.
|
|
RuntimeStats *rtStats = static_cast<IteratorClosure *>(data)->rtStats;
|
|
|
|
// CollectRuntimeStats reserves enough space.
|
|
MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
|
|
CompartmentStats &cStats = rtStats->compartmentStatsVector.back();
|
|
rtStats->initExtraCompartmentStats(compartment, &cStats);
|
|
rtStats->currCompartmentStats = &cStats;
|
|
|
|
// Get the compartment-level numbers.
|
|
compartment->sizeOfTypeInferenceData(&cStats.typeInferenceSizes, rtStats->mallocSizeOf);
|
|
cStats.shapesCompartmentTables = compartment->sizeOfShapeTable(rtStats->mallocSizeOf);
|
|
cStats.crossCompartmentWrappers =
|
|
compartment->crossCompartmentWrappers.sizeOfExcludingThis(rtStats->mallocSizeOf);
|
|
}
|
|
|
|
static void
|
|
StatsChunkCallback(JSRuntime *rt, void *data, gc::Chunk *chunk)
|
|
{
|
|
RuntimeStats *rtStats = static_cast<RuntimeStats *>(data);
|
|
for (size_t i = 0; i < gc::ArenasPerChunk; i++)
|
|
if (chunk->decommittedArenas.get(i))
|
|
rtStats->gcHeapDecommittedArenas += gc::ArenaSize;
|
|
}
|
|
|
|
static void
|
|
StatsArenaCallback(JSRuntime *rt, void *data, gc::Arena *arena,
|
|
JSGCTraceKind traceKind, size_t thingSize)
|
|
{
|
|
RuntimeStats *rtStats = static_cast<IteratorClosure *>(data)->rtStats;
|
|
|
|
// The admin space includes (a) the header and (b) the padding between the
|
|
// end of the header and the start of the first GC thing.
|
|
size_t allocationSpace = arena->thingsSpan(thingSize);
|
|
rtStats->currCompartmentStats->gcHeapArenaAdmin +=
|
|
gc::ArenaSize - allocationSpace;
|
|
|
|
// We don't call the callback on unused things. So we compute the
|
|
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
|
|
// We do this by setting arenaUnused to maxArenaUnused here, and then
|
|
// subtracting thingSize for every used cell, in StatsCellCallback().
|
|
rtStats->currCompartmentStats->gcHeapUnusedGcThings += allocationSpace;
|
|
}
|
|
|
|
static void
|
|
StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKind,
|
|
size_t thingSize)
|
|
{
|
|
IteratorClosure *closure = static_cast<IteratorClosure *>(data);
|
|
RuntimeStats *rtStats = closure->rtStats;
|
|
CompartmentStats *cStats = rtStats->currCompartmentStats;
|
|
switch (traceKind) {
|
|
case JSTRACE_OBJECT:
|
|
{
|
|
JSObject *obj = static_cast<JSObject *>(thing);
|
|
if (obj->isFunction()) {
|
|
cStats->gcHeapObjectsFunction += thingSize;
|
|
} else {
|
|
cStats->gcHeapObjectsNonFunction += thingSize;
|
|
}
|
|
size_t slotsSize, elementsSize, miscSize;
|
|
obj->sizeOfExcludingThis(rtStats->mallocSizeOf, &slotsSize,
|
|
&elementsSize, &miscSize);
|
|
cStats->objectSlots += slotsSize;
|
|
cStats->objectElements += elementsSize;
|
|
cStats->objectMisc += miscSize;
|
|
|
|
if (ObjectPrivateVisitor *opv = closure->opv) {
|
|
js::Class *clazz = js::GetObjectClass(obj);
|
|
if (clazz->flags & JSCLASS_HAS_PRIVATE &&
|
|
clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS)
|
|
{
|
|
cStats->objectPrivate += opv->sizeOfIncludingThis(GetObjectPrivate(obj));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case JSTRACE_STRING:
|
|
{
|
|
JSString *str = static_cast<JSString *>(thing);
|
|
cStats->gcHeapStrings += thingSize;
|
|
cStats->stringChars += str->sizeOfExcludingThis(rtStats->mallocSizeOf);
|
|
break;
|
|
}
|
|
case JSTRACE_SHAPE:
|
|
{
|
|
Shape *shape = static_cast<Shape*>(thing);
|
|
size_t propTableSize, kidsSize;
|
|
shape->sizeOfExcludingThis(rtStats->mallocSizeOf, &propTableSize, &kidsSize);
|
|
if (shape->inDictionary()) {
|
|
cStats->gcHeapShapesDict += thingSize;
|
|
cStats->shapesExtraDictTables += propTableSize;
|
|
JS_ASSERT(kidsSize == 0);
|
|
} else {
|
|
cStats->gcHeapShapesTree += thingSize;
|
|
cStats->shapesExtraTreeTables += propTableSize;
|
|
cStats->shapesExtraTreeShapeKids += kidsSize;
|
|
}
|
|
break;
|
|
}
|
|
case JSTRACE_BASE_SHAPE:
|
|
{
|
|
cStats->gcHeapShapesBase += thingSize;
|
|
break;
|
|
}
|
|
case JSTRACE_SCRIPT:
|
|
{
|
|
JSScript *script = static_cast<JSScript *>(thing);
|
|
cStats->gcHeapScripts += thingSize;
|
|
cStats->scriptData += script->sizeOfData(rtStats->mallocSizeOf);
|
|
#ifdef JS_METHODJIT
|
|
cStats->mjitData += script->sizeOfJitScripts(rtStats->mallocSizeOf);
|
|
#endif
|
|
ScriptSource *ss = script->scriptSource();
|
|
SourceSet::AddPtr entry = closure->seenSources.lookupForAdd(ss);
|
|
if (!entry) {
|
|
closure->seenSources.add(entry, ss); // Not much to be done on failure.
|
|
rtStats->runtime.scriptSources += ss->sizeOfIncludingThis(rtStats->mallocSizeOf);
|
|
}
|
|
break;
|
|
}
|
|
case JSTRACE_TYPE_OBJECT:
|
|
{
|
|
types::TypeObject *obj = static_cast<types::TypeObject *>(thing);
|
|
cStats->gcHeapTypeObjects += thingSize;
|
|
obj->sizeOfExcludingThis(&cStats->typeInferenceSizes, rtStats->mallocSizeOf);
|
|
break;
|
|
}
|
|
#if JS_HAS_XML_SUPPORT
|
|
case JSTRACE_XML:
|
|
{
|
|
cStats->gcHeapXML += thingSize;
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
// Yes, this is a subtraction: see StatsArenaCallback() for details.
|
|
cStats->gcHeapUnusedGcThings -= thingSize;
|
|
}
|
|
|
|
JS_PUBLIC_API(bool)
|
|
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor *opv)
|
|
{
|
|
if (!rtStats->compartmentStatsVector.reserve(rt->compartments.length()))
|
|
return false;
|
|
|
|
rtStats->gcHeapChunkTotal =
|
|
size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
|
|
|
|
rtStats->gcHeapUnusedChunks =
|
|
size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize;
|
|
|
|
// This just computes rtStats->gcHeapDecommittedArenas.
|
|
IterateChunks(rt, rtStats, StatsChunkCallback);
|
|
|
|
// Take the per-compartment measurements.
|
|
IteratorClosure closure(rtStats, opv);
|
|
if (!closure.init())
|
|
return false;
|
|
rtStats->runtime.scriptSources = 0;
|
|
IterateCompartmentsArenasCells(rt, &closure, StatsCompartmentCallback,
|
|
StatsArenaCallback, StatsCellCallback);
|
|
|
|
// Take the "explicit/js/runtime/" measurements.
|
|
rt->sizeOfIncludingThis(rtStats->mallocSizeOf, &rtStats->runtime);
|
|
|
|
rtStats->gcHeapGcThings = 0;
|
|
for (size_t i = 0; i < rtStats->compartmentStatsVector.length(); i++) {
|
|
CompartmentStats &cStats = rtStats->compartmentStatsVector[i];
|
|
|
|
rtStats->totals.add(cStats);
|
|
rtStats->gcHeapGcThings += cStats.gcHeapThingsSize();
|
|
}
|
|
|
|
size_t numDirtyChunks =
|
|
(rtStats->gcHeapChunkTotal - rtStats->gcHeapUnusedChunks) / gc::ChunkSize;
|
|
size_t perChunkAdmin =
|
|
sizeof(gc::Chunk) - (sizeof(gc::Arena) * gc::ArenasPerChunk);
|
|
rtStats->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin;
|
|
rtStats->gcHeapUnusedArenas -= rtStats->gcHeapChunkAdmin;
|
|
|
|
// |gcHeapUnusedArenas| is the only thing left. Compute it in terms of
|
|
// all the others. See the comment in RuntimeStats for explanation.
|
|
rtStats->gcHeapUnusedArenas = rtStats->gcHeapChunkTotal -
|
|
rtStats->gcHeapDecommittedArenas -
|
|
rtStats->gcHeapUnusedChunks -
|
|
rtStats->totals.gcHeapUnusedGcThings -
|
|
rtStats->gcHeapChunkAdmin -
|
|
rtStats->totals.gcHeapArenaAdmin -
|
|
rtStats->gcHeapGcThings;
|
|
return true;
|
|
}
|
|
|
|
JS_PUBLIC_API(int64_t)
|
|
GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf)
|
|
{
|
|
// explicit/<compartment>/gc-heap/*
|
|
size_t n = size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
|
|
|
|
// explicit/runtime/mjit-code
|
|
// explicit/runtime/regexp-code
|
|
// explicit/runtime/stack-committed
|
|
// explicit/runtime/unused-code-memory
|
|
n += rt->sizeOfExplicitNonHeap();
|
|
|
|
return int64_t(n);
|
|
}
|
|
|
|
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
|
|
|
|
#endif // JS_THREADSAFE
|