From 615e5730397da380f595840ca3a224285bdb8284 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Nov 2012 17:05:39 -0800 Subject: [PATCH] Bug 814229 (part 1) - Add "objects-extra/ctypes-data" memory report. r=jorendorff. --HG-- extra : rebase_source : 8b65b74b5c22ebf7525eeff51601e36274d56736 --- js/public/MemoryMetrics.h | 4 ++++ js/src/ctypes/CTypes.cpp | 22 ++++++++++++++++++++++ js/src/jsfriendapi.h | 3 +++ js/src/jsmemorymetrics.cpp | 5 +++-- js/src/jsobj.h | 3 ++- js/src/jsobjinlines.h | 7 ++++++- js/xpconnect/src/XPCJSRuntime.cpp | 7 +++++-- 7 files changed, 45 insertions(+), 6 deletions(-) diff --git a/js/public/MemoryMetrics.h b/js/public/MemoryMetrics.h index 2f7b78505f8..0dee0a793f0 100644 --- a/js/public/MemoryMetrics.h +++ b/js/public/MemoryMetrics.h @@ -166,6 +166,7 @@ struct CompartmentStats , objectsExtraArgumentsData(0) , objectsExtraRegExpStatics(0) , objectsExtraPropertyIteratorData(0) + , objectsExtraCtypesData(0) , objectsExtraPrivate(0) , stringCharsNonHuge(0) , shapesExtraTreeTables(0) @@ -208,6 +209,7 @@ struct CompartmentStats , objectsExtraArgumentsData(other.objectsExtraArgumentsData) , objectsExtraRegExpStatics(other.objectsExtraRegExpStatics) , objectsExtraPropertyIteratorData(other.objectsExtraPropertyIteratorData) + , objectsExtraCtypesData(other.objectsExtraCtypesData) , objectsExtraPrivate(other.objectsExtraPrivate) , stringCharsNonHuge(other.stringCharsNonHuge) , shapesExtraTreeTables(other.shapesExtraTreeTables) @@ -258,6 +260,7 @@ struct CompartmentStats size_t objectsExtraArgumentsData; size_t objectsExtraRegExpStatics; size_t objectsExtraPropertyIteratorData; + size_t objectsExtraCtypesData; size_t objectsExtraPrivate; size_t stringCharsNonHuge; size_t shapesExtraTreeTables; @@ -306,6 +309,7 @@ struct CompartmentStats ADD(objectsExtraArgumentsData); ADD(objectsExtraRegExpStatics); ADD(objectsExtraPropertyIteratorData); + ADD(objectsExtraCtypesData); ADD(objectsExtraPrivate); ADD(stringCharsNonHuge); ADD(shapesExtraTreeTables); diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index fadd146d661..26254a74d81 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -1330,6 +1330,28 @@ JS_SetCTypesCallbacks(JSRawObject ctypesObj, JSCTypesCallbacks* callbacks) } namespace js { + +JS_FRIEND_API(size_t) +SizeOfDataIfCDataObject(JSMallocSizeOfFun mallocSizeOf, JSObject *obj) +{ + if (!CData::IsCData(obj)) + return 0; + + size_t n = 0; + jsval slot = JS_GetReservedSlot(obj, ctypes::SLOT_OWNS); + if (!JSVAL_IS_VOID(slot)) { + JSBool owns = JSVAL_TO_BOOLEAN(slot); + slot = JS_GetReservedSlot(obj, ctypes::SLOT_DATA); + if (!JSVAL_IS_VOID(slot)) { + char** buffer = static_cast(JSVAL_TO_PRIVATE(slot)); + n += mallocSizeOf(buffer); + if (owns) + n += mallocSizeOf(*buffer); + } + } + return n; +} + namespace ctypes { /******************************************************************************* diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 88c0bc0f0a3..7520a06cc79 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -298,6 +298,9 @@ GCThingTraceKind(void *thing); extern JS_FRIEND_API(void) IterateGrayObjects(JSCompartment *compartment, GCThingCallback cellCallback, void *data); +extern JS_FRIEND_API(size_t) +SizeOfDataIfCDataObject(JSMallocSizeOfFun mallocSizeOf, JSObject *obj); + /* * Shadow declarations of JS internal structures, for access by inline access * functions below. Do not use these structures in any other way. When adding diff --git a/js/src/jsmemorymetrics.cpp b/js/src/jsmemorymetrics.cpp index a1878a5d325..faeab350466 100644 --- a/js/src/jsmemorymetrics.cpp +++ b/js/src/jsmemorymetrics.cpp @@ -152,15 +152,16 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin cStats->gcHeapObjectsOrdinary += thingSize; } size_t slotsSize, elementsSize, argumentsDataSize, regExpStaticsSize, - propertyIteratorDataSize; + propertyIteratorDataSize, ctypesDataSize; obj->sizeOfExcludingThis(rtStats->mallocSizeOf, &slotsSize, &elementsSize, &argumentsDataSize, ®ExpStaticsSize, - &propertyIteratorDataSize); + &propertyIteratorDataSize, &ctypesDataSize); cStats->objectsExtraSlots += slotsSize; cStats->objectsExtraElements += elementsSize; cStats->objectsExtraArgumentsData += argumentsDataSize; cStats->objectsExtraRegExpStatics += regExpStaticsSize; cStats->objectsExtraPropertyIteratorData += propertyIteratorDataSize; + cStats->objectsExtraCtypesData += ctypesDataSize; if (ObjectPrivateVisitor *opv = closure->opv) { js::Class *clazz = js::GetObjectClass(obj); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index a45387159f9..e4daa05accd 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -371,7 +371,8 @@ struct JSObject : public js::ObjectImpl inline void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *slotsSize, size_t *elementsSize, size_t *argumentsDataSize, size_t *regExpStaticsSize, - size_t *propertyIteratorDataSize) const; + size_t *propertyIteratorDataSize, + size_t *ctypesDataSize) const; bool hasIdempotentProtoChain() const; diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 401d042967f..9e209241cf7 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -1001,7 +1001,8 @@ JSObject::computedSizeOfThisSlotsElements() const inline void JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *slotsSize, size_t *elementsSize, size_t *argumentsDataSize, - size_t *regExpStaticsSize, size_t *propertyIteratorDataSize) const + size_t *regExpStaticsSize, size_t *propertyIteratorDataSize, + size_t *ctypesDataSize) const { *slotsSize = 0; if (hasDynamicSlots()) { @@ -1017,12 +1018,16 @@ JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *slotsSize, *argumentsDataSize = 0; *regExpStaticsSize = 0; *propertyIteratorDataSize = 0; + *ctypesDataSize = 0; if (isArguments()) { *argumentsDataSize += asArguments().sizeOfMisc(mallocSizeOf); } else if (isRegExpStatics()) { *regExpStaticsSize += js::SizeOfRegExpStaticsData(this, mallocSizeOf); } else if (isPropertyIterator()) { *propertyIteratorDataSize += asPropertyIterator().sizeOfMisc(mallocSizeOf); + } else { + // This must be the last case. + *ctypesDataSize += js::SizeOfDataIfCDataObject(mallocSizeOf, const_cast(this)); } } diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 2cd7e4603e8..1bd738205af 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1620,9 +1620,12 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats, CREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/property-iterator-data"), cStats.objectsExtraPropertyIteratorData, - "Memory allocated for data belonging to property iterator " - "objects."); + "Memory allocated for data belonging to property iterator objects."); + CREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/ctypes-data"), + cStats.objectsExtraCtypesData, + "Memory allocated for data belonging to ctypes objects."); + // Note that we use cDOMPathPrefix here. This is because we measure orphan // DOM nodes in the JS multi-reporter, but we want to report them in a // "dom" sub-tree rather than a "js" sub-tree.