Bug 854763 - Add a memory reporter for asm.js array buffers. r=luke.
This commit is contained in:
@@ -40,7 +40,9 @@ namespace JS {
|
|||||||
struct ObjectsExtraSizes
|
struct ObjectsExtraSizes
|
||||||
{
|
{
|
||||||
size_t slots;
|
size_t slots;
|
||||||
size_t elements;
|
size_t elementsNonAsmJS;
|
||||||
|
size_t elementsAsmJSHeap;
|
||||||
|
size_t elementsAsmJSNonHeap;
|
||||||
size_t argumentsData;
|
size_t argumentsData;
|
||||||
size_t regExpStatics;
|
size_t regExpStatics;
|
||||||
size_t propertyIteratorData;
|
size_t propertyIteratorData;
|
||||||
@@ -52,7 +54,9 @@ struct ObjectsExtraSizes
|
|||||||
|
|
||||||
void add(ObjectsExtraSizes &sizes) {
|
void add(ObjectsExtraSizes &sizes) {
|
||||||
this->slots += sizes.slots;
|
this->slots += sizes.slots;
|
||||||
this->elements += sizes.elements;
|
this->elementsNonAsmJS += sizes.elementsNonAsmJS;
|
||||||
|
this->elementsAsmJSHeap += sizes.elementsAsmJSHeap;
|
||||||
|
this->elementsAsmJSNonHeap += sizes.elementsAsmJSNonHeap;
|
||||||
this->argumentsData += sizes.argumentsData;
|
this->argumentsData += sizes.argumentsData;
|
||||||
this->regExpStatics += sizes.regExpStatics;
|
this->regExpStatics += sizes.regExpStatics;
|
||||||
this->propertyIteratorData += sizes.propertyIteratorData;
|
this->propertyIteratorData += sizes.propertyIteratorData;
|
||||||
|
|||||||
@@ -5040,3 +5040,40 @@ js_DumpBacktrace(JSContext *cx)
|
|||||||
fprintf(stdout, "%s", sprinter.string());
|
fprintf(stdout, "%s", sprinter.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, JS::ObjectsExtraSizes *sizes)
|
||||||
|
{
|
||||||
|
if (hasDynamicSlots())
|
||||||
|
sizes->slots = mallocSizeOf(slots);
|
||||||
|
|
||||||
|
if (hasDynamicElements()) {
|
||||||
|
js::ObjectElements *elements = getElementsHeader();
|
||||||
|
if (JS_UNLIKELY(elements->isAsmJSArrayBuffer())) {
|
||||||
|
#if defined (JS_CPU_X64)
|
||||||
|
// On x64, ArrayBufferObject::prepareForAsmJS switches the
|
||||||
|
// ArrayBufferObject to use mmap'd storage.
|
||||||
|
sizes->elementsAsmJSNonHeap = asArrayBuffer().byteLength();
|
||||||
|
#else
|
||||||
|
sizes->elementsAsmJSHeap = mallocSizeOf(elements);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
sizes->elementsNonAsmJS = mallocSizeOf(elements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other things may be measured in the future if DMD indicates it is worthwhile.
|
||||||
|
// Note that sizes->private_ is measured elsewhere.
|
||||||
|
if (isArguments()) {
|
||||||
|
sizes->argumentsData = asArguments().sizeOfMisc(mallocSizeOf);
|
||||||
|
} else if (isRegExpStatics()) {
|
||||||
|
sizes->regExpStatics = js::SizeOfRegExpStaticsData(this, mallocSizeOf);
|
||||||
|
} else if (isPropertyIterator()) {
|
||||||
|
sizes->propertyIteratorData = asPropertyIterator().sizeOfMisc(mallocSizeOf);
|
||||||
|
#ifdef JS_HAS_CTYPES
|
||||||
|
} else {
|
||||||
|
// This must be the last case.
|
||||||
|
sizes->ctypesData = js::SizeOfDataIfCDataObject(mallocSizeOf, const_cast<JSObject *>(this));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ class JSObject : public js::ObjectImpl
|
|||||||
|
|
||||||
inline bool hasShapeTable() const;
|
inline bool hasShapeTable() const;
|
||||||
|
|
||||||
inline void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, JS::ObjectsExtraSizes *sizes);
|
void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, JS::ObjectsExtraSizes *sizes);
|
||||||
|
|
||||||
bool hasIdempotentProtoChain() const;
|
bool hasIdempotentProtoChain() const;
|
||||||
|
|
||||||
|
|||||||
@@ -1077,42 +1077,6 @@ JSObject::hasShapeTable() const
|
|||||||
return lastProperty()->hasTable();
|
return lastProperty()->hasTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, JS::ObjectsExtraSizes *sizes)
|
|
||||||
{
|
|
||||||
if (hasDynamicSlots())
|
|
||||||
sizes->slots = mallocSizeOf(slots);
|
|
||||||
|
|
||||||
if (hasDynamicElements()) {
|
|
||||||
js::ObjectElements *elements = getElementsHeader();
|
|
||||||
#if defined (JS_CPU_X64)
|
|
||||||
// On x64, ArrayBufferObject::prepareForAsmJS switches the
|
|
||||||
// ArrayBufferObject to use mmap'd storage. This is not included in the
|
|
||||||
// total 'explicit' figure and thus we must not include it here.
|
|
||||||
// TODO: include it somewhere else.
|
|
||||||
if (JS_LIKELY(!elements->isAsmJSArrayBuffer()))
|
|
||||||
sizes->elements = mallocSizeOf(elements);
|
|
||||||
#else
|
|
||||||
sizes->elements = mallocSizeOf(elements);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other things may be measured in the future if DMD indicates it is worthwhile.
|
|
||||||
// Note that sizes->private_ is measured elsewhere.
|
|
||||||
if (isArguments()) {
|
|
||||||
sizes->argumentsData = asArguments().sizeOfMisc(mallocSizeOf);
|
|
||||||
} else if (isRegExpStatics()) {
|
|
||||||
sizes->regExpStatics = js::SizeOfRegExpStaticsData(this, mallocSizeOf);
|
|
||||||
} else if (isPropertyIterator()) {
|
|
||||||
sizes->propertyIteratorData = asPropertyIterator().sizeOfMisc(mallocSizeOf);
|
|
||||||
#ifdef JS_HAS_CTYPES
|
|
||||||
} else {
|
|
||||||
// This must be the last case.
|
|
||||||
sizes->ctypesData = js::SizeOfDataIfCDataObject(mallocSizeOf, const_cast<JSObject *>(this));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ inline JSBool
|
/* static */ inline JSBool
|
||||||
JSObject::lookupGeneric(JSContext *cx, js::HandleObject obj, js::HandleId id,
|
JSObject::lookupGeneric(JSContext *cx, js::HandleObject obj, js::HandleId id,
|
||||||
js::MutableHandleObject objp, js::MutableHandleShape propp)
|
js::MutableHandleObject objp, js::MutableHandleShape propp)
|
||||||
|
|||||||
@@ -1763,11 +1763,29 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
|||||||
"stored on the JavaScript heap; those slots "
|
"stored on the JavaScript heap; those slots "
|
||||||
"are not counted here, but in 'gc-heap/objects' instead.");
|
"are not counted here, but in 'gc-heap/objects' instead.");
|
||||||
|
|
||||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/elements"),
|
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/elements/non-asm.js"),
|
||||||
cStats.objectsExtra.elements,
|
cStats.objectsExtra.elementsNonAsmJS,
|
||||||
"Memory allocated for object element "
|
"Memory allocated for non-asm.js object element arrays, "
|
||||||
"arrays, which are used to represent indexed object "
|
"which are used to represent indexed object properties.");
|
||||||
"properties.");
|
|
||||||
|
// asm.js arrays are heap-allocated on some platforms and
|
||||||
|
// non-heap-allocated on others. We never put them under sundries,
|
||||||
|
// because (a) in practice they're almost always larger than the sundries
|
||||||
|
// threshold, and (b) we'd need a third category of non-heap, non-GC
|
||||||
|
// sundries, which would be a pain.
|
||||||
|
#define ASM_JS_DESC "Memory allocated for object element " \
|
||||||
|
"arrays used as asm.js array buffers."
|
||||||
|
size_t asmJSHeap = cStats.objectsExtra.elementsAsmJSHeap;
|
||||||
|
size_t asmJSNonHeap = cStats.objectsExtra.elementsAsmJSNonHeap;
|
||||||
|
JS_ASSERT(asmJSHeap == 0 || asmJSNonHeap == 0);
|
||||||
|
if (asmJSHeap > 0) {
|
||||||
|
REPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/elements/asm.js"),
|
||||||
|
nsIMemoryReporter::KIND_HEAP, asmJSHeap, ASM_JS_DESC);
|
||||||
|
}
|
||||||
|
if (asmJSNonHeap > 0) {
|
||||||
|
REPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/elements/asm.js"),
|
||||||
|
nsIMemoryReporter::KIND_NONHEAP, asmJSNonHeap, ASM_JS_DESC);
|
||||||
|
}
|
||||||
|
|
||||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/arguments-data"),
|
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/arguments-data"),
|
||||||
cStats.objectsExtra.argumentsData,
|
cStats.objectsExtra.argumentsData,
|
||||||
|
|||||||
Reference in New Issue
Block a user