mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 722595 - Add memory reporters for misc things hanging off JS objects. r=bhackett.
--HG-- extra : rebase_source : 211b35134923f4cb99625bb240b96e81f0f28b4b
This commit is contained in:
parent
9f28cf3032
commit
a1ab9492f5
@ -102,6 +102,7 @@ struct CompartmentStats
|
||||
|
||||
size_t objectSlots;
|
||||
size_t objectElements;
|
||||
size_t objectMisc;
|
||||
size_t stringChars;
|
||||
size_t shapesExtraTreeTables;
|
||||
size_t shapesExtraDictTables;
|
||||
|
@ -126,10 +126,12 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||
} else {
|
||||
cStats->gcHeapObjectsNonFunction += thingSize;
|
||||
}
|
||||
size_t slotsSize, elementsSize;
|
||||
obj->sizeOfExcludingThis(rtStats->mallocSizeOf, &slotsSize, &elementsSize);
|
||||
size_t slotsSize, elementsSize, miscSize;
|
||||
obj->sizeOfExcludingThis(rtStats->mallocSizeOf, &slotsSize,
|
||||
&elementsSize, &miscSize);
|
||||
cStats->objectSlots += slotsSize;
|
||||
cStats->objectElements += elementsSize;
|
||||
cStats->objectMisc += miscSize;
|
||||
break;
|
||||
}
|
||||
case JSTRACE_STRING:
|
||||
@ -262,7 +264,8 @@ CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
|
||||
rtStats->totalObjects += cStats.gcHeapObjectsNonFunction +
|
||||
cStats.gcHeapObjectsFunction +
|
||||
cStats.objectSlots +
|
||||
cStats.objectElements;
|
||||
cStats.objectElements +
|
||||
cStats.objectMisc;
|
||||
rtStats->totalShapes += cStats.gcHeapShapesTree +
|
||||
cStats.gcHeapShapesDict +
|
||||
cStats.gcHeapShapesBase +
|
||||
|
@ -978,7 +978,7 @@ JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
|
||||
JS_PUBLIC_API(size_t)
|
||||
JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return obj->computedSizeOfIncludingThis();
|
||||
return obj->computedSizeOfThisSlotsElements();
|
||||
}
|
||||
|
||||
static size_t
|
||||
|
@ -1469,6 +1469,14 @@ fun_finalize(JSContext *cx, JSObject *obj)
|
||||
obj->toFunction()->finalizeUpvars();
|
||||
}
|
||||
|
||||
size_t
|
||||
JSFunction::sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const
|
||||
{
|
||||
return (isFlatClosure() && hasFlatClosureUpvars()) ?
|
||||
mallocSizeOf(getFlatClosureUpvars()) :
|
||||
0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reserve two slots in all function objects for XPConnect. Note that this
|
||||
* does not bloat every instance, only those on which reserved slots are set,
|
||||
|
@ -290,6 +290,12 @@ struct JSFunction : public JSObject
|
||||
inline JSAtom *methodAtom() const;
|
||||
inline void setMethodAtom(JSAtom *atom);
|
||||
|
||||
/*
|
||||
* Measures things hanging off this JSFunction that are counted by the
|
||||
* |miscSize| argument in JSObject::sizeOfExcludingThis().
|
||||
*/
|
||||
size_t sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const;
|
||||
|
||||
private:
|
||||
/*
|
||||
* These member functions are inherited from JSObject, but should never be applied to
|
||||
|
@ -4119,7 +4119,7 @@ JSObject::growSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
|
||||
*/
|
||||
JS_ASSERT(newCount < NELEMENTS_LIMIT);
|
||||
|
||||
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfIncludingThis() : 0;
|
||||
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfThisSlotsElements() : 0;
|
||||
size_t newSize = oldSize + (newCount - oldCount) * sizeof(Value);
|
||||
|
||||
/*
|
||||
@ -4188,7 +4188,7 @@ JSObject::shrinkSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
|
||||
if (isCall())
|
||||
return;
|
||||
|
||||
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfIncludingThis() : 0;
|
||||
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfThisSlotsElements() : 0;
|
||||
size_t newSize = oldSize - (oldCount - newCount) * sizeof(Value);
|
||||
|
||||
if (newCount == 0) {
|
||||
@ -4234,7 +4234,7 @@ JSObject::growElements(JSContext *cx, uintN newcap)
|
||||
uint32_t oldcap = getDenseArrayCapacity();
|
||||
JS_ASSERT(oldcap <= newcap);
|
||||
|
||||
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfIncludingThis() : 0;
|
||||
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfThisSlotsElements() : 0;
|
||||
|
||||
uint32_t nextsize = (oldcap <= CAPACITY_DOUBLING_MAX)
|
||||
? oldcap * 2
|
||||
@ -4277,7 +4277,7 @@ JSObject::growElements(JSContext *cx, uintN newcap)
|
||||
Debug_SetValueRangeToCrashOnTouch(elements + initlen, actualCapacity - initlen);
|
||||
|
||||
if (Probes::objectResizeActive())
|
||||
Probes::resizeObject(cx, this, oldSize, computedSizeOfIncludingThis());
|
||||
Probes::resizeObject(cx, this, oldSize, computedSizeOfThisSlotsElements());
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -4290,7 +4290,7 @@ JSObject::shrinkElements(JSContext *cx, uintN newcap)
|
||||
uint32_t oldcap = getDenseArrayCapacity();
|
||||
JS_ASSERT(newcap <= oldcap);
|
||||
|
||||
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfIncludingThis() : 0;
|
||||
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfThisSlotsElements() : 0;
|
||||
|
||||
/* Don't shrink elements below the minimum capacity. */
|
||||
if (oldcap <= SLOT_CAPACITY_MIN || !hasDynamicElements())
|
||||
@ -4309,7 +4309,7 @@ JSObject::shrinkElements(JSContext *cx, uintN newcap)
|
||||
elements = newheader->elements();
|
||||
|
||||
if (Probes::objectResizeActive())
|
||||
Probes::resizeObject(cx, this, oldSize, computedSizeOfIncludingThis());
|
||||
Probes::resizeObject(cx, this, oldSize, computedSizeOfThisSlotsElements());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -363,6 +363,7 @@ extern Class NormalArgumentsObjectClass;
|
||||
extern Class ObjectClass;
|
||||
extern Class ProxyClass;
|
||||
extern Class RegExpClass;
|
||||
extern Class RegExpStaticsClass;
|
||||
extern Class SlowArrayClass;
|
||||
extern Class StopIterationClass;
|
||||
extern Class StringClass;
|
||||
@ -672,11 +673,11 @@ struct JSObject : js::gc::Cell
|
||||
inline bool hasPropertyTable() const;
|
||||
|
||||
inline size_t sizeOfThis() const;
|
||||
inline size_t computedSizeOfIncludingThis() const;
|
||||
inline size_t computedSizeOfThisSlotsElements() const;
|
||||
|
||||
/* mallocSizeOf can be NULL, in which case we compute the sizes analytically */
|
||||
inline void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
|
||||
size_t *slotsSize, size_t *elementsSize) const;
|
||||
size_t *slotsSize, size_t *elementsSize,
|
||||
size_t *miscSize) const;
|
||||
|
||||
inline size_t numFixedSlots() const;
|
||||
|
||||
@ -1416,6 +1417,7 @@ struct JSObject : js::gc::Cell
|
||||
inline bool isPrimitive() const;
|
||||
inline bool isProxy() const;
|
||||
inline bool isRegExp() const;
|
||||
inline bool isRegExpStatics() const;
|
||||
inline bool isScope() const;
|
||||
inline bool isScript() const;
|
||||
inline bool isSlowArray() const;
|
||||
@ -1448,6 +1450,7 @@ struct JSObject : js::gc::Cell
|
||||
inline bool isCrossCompartmentWrapper() const;
|
||||
|
||||
inline js::ArgumentsObject &asArguments();
|
||||
inline const js::ArgumentsObject &asArguments() const;
|
||||
inline js::BlockObject &asBlock();
|
||||
inline js::BooleanObject &asBoolean();
|
||||
inline js::CallObject &asCall();
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/TemplateLib.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/RegExpStatics.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jsfuninlines.h"
|
||||
@ -76,6 +77,7 @@
|
||||
|
||||
#include "gc/Barrier-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
#include "vm/RegExpStatics-inl.h"
|
||||
|
||||
inline bool
|
||||
JSObject::hasPrivate() const
|
||||
@ -936,6 +938,7 @@ inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
|
||||
inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
|
||||
inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
|
||||
inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
|
||||
inline bool JSObject::isRegExpStatics() const { return hasClass(&js::RegExpStaticsClass); }
|
||||
inline bool JSObject::isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
|
||||
inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
|
||||
inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
|
||||
@ -1208,31 +1211,43 @@ JSObject::sizeOfThis() const
|
||||
}
|
||||
|
||||
inline size_t
|
||||
JSObject::computedSizeOfIncludingThis() const
|
||||
JSObject::computedSizeOfThisSlotsElements() const
|
||||
{
|
||||
size_t slotsSize, elementsSize;
|
||||
sizeOfExcludingThis(NULL, &slotsSize, &elementsSize);
|
||||
return sizeOfThis() + slotsSize + elementsSize;
|
||||
size_t n = sizeOfThis();
|
||||
|
||||
if (hasDynamicSlots())
|
||||
n += numDynamicSlots() * sizeof(js::Value);
|
||||
|
||||
if (hasDynamicElements())
|
||||
n += (js::ObjectElements::VALUES_PER_HEADER + getElementsHeader()->capacity) *
|
||||
sizeof(js::Value);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
|
||||
size_t *slotsSize, size_t *elementsSize) const
|
||||
size_t *slotsSize, size_t *elementsSize,
|
||||
size_t *miscSize) const
|
||||
{
|
||||
*slotsSize = 0;
|
||||
if (hasDynamicSlots()) {
|
||||
size_t computedSize = numDynamicSlots() * sizeof(js::Value);
|
||||
*slotsSize = mallocSizeOf ? mallocSizeOf(slots) : computedSize;
|
||||
} else {
|
||||
*slotsSize = 0;
|
||||
*slotsSize += mallocSizeOf(slots);
|
||||
}
|
||||
|
||||
*elementsSize = 0;
|
||||
if (hasDynamicElements()) {
|
||||
size_t computedSize =
|
||||
(js::ObjectElements::VALUES_PER_HEADER +
|
||||
getElementsHeader()->capacity) * sizeof(js::Value);
|
||||
*elementsSize =
|
||||
mallocSizeOf ? mallocSizeOf(getElementsHeader()) : computedSize;
|
||||
} else {
|
||||
*elementsSize = 0;
|
||||
*elementsSize += mallocSizeOf(getElementsHeader());
|
||||
}
|
||||
|
||||
/* Other things may be measured in the future if DMD indicates it is worthwhile. */
|
||||
*miscSize = 0;
|
||||
if (isFunction()) {
|
||||
*miscSize += toFunction()->sizeOfMisc(mallocSizeOf);
|
||||
} else if (isArguments()) {
|
||||
*miscSize += asArguments().sizeOfMisc(mallocSizeOf);
|
||||
} else if (isRegExpStatics()) {
|
||||
*miscSize += js::SizeOfRegExpStaticsData(this, mallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,12 @@ ArgumentsObject::setStackFrame(StackFrame *frame)
|
||||
setFixedSlot(STACK_FRAME_SLOT, PrivateValue(frame));
|
||||
}
|
||||
|
||||
inline size_t
|
||||
ArgumentsObject::sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const
|
||||
{
|
||||
return mallocSizeOf(data());
|
||||
}
|
||||
|
||||
inline const js::Value &
|
||||
NormalArgumentsObject::callee() const
|
||||
{
|
||||
|
@ -213,6 +213,12 @@ class ArgumentsObject : public JSObject
|
||||
/* The stack frame for this ArgumentsObject, if the frame is still active. */
|
||||
inline js::StackFrame *maybeStackFrame() const;
|
||||
inline void setStackFrame(js::StackFrame *frame);
|
||||
|
||||
/*
|
||||
* Measures things hanging off this ArgumentsObject that are counted by the
|
||||
* |miscSize| argument in JSObject::sizeOfExcludingThis().
|
||||
*/
|
||||
inline size_t sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const;
|
||||
};
|
||||
|
||||
class NormalArgumentsObject : public ArgumentsObject
|
||||
@ -246,21 +252,28 @@ js::NormalArgumentsObject &
|
||||
JSObject::asNormalArguments()
|
||||
{
|
||||
JS_ASSERT(isNormalArguments());
|
||||
return *reinterpret_cast<js::NormalArgumentsObject *>(this);
|
||||
return *static_cast<js::NormalArgumentsObject *>(this);
|
||||
}
|
||||
|
||||
js::StrictArgumentsObject &
|
||||
JSObject::asStrictArguments()
|
||||
{
|
||||
JS_ASSERT(isStrictArguments());
|
||||
return *reinterpret_cast<js::StrictArgumentsObject *>(this);
|
||||
return *static_cast<js::StrictArgumentsObject *>(this);
|
||||
}
|
||||
|
||||
js::ArgumentsObject &
|
||||
JSObject::asArguments()
|
||||
{
|
||||
JS_ASSERT(isArguments());
|
||||
return *reinterpret_cast<js::ArgumentsObject *>(this);
|
||||
return *static_cast<js::ArgumentsObject *>(this);
|
||||
}
|
||||
|
||||
const js::ArgumentsObject &
|
||||
JSObject::asArguments() const
|
||||
{
|
||||
JS_ASSERT(isArguments());
|
||||
return *static_cast<const js::ArgumentsObject *>(this);
|
||||
}
|
||||
|
||||
#endif /* ArgumentsObject_h___ */
|
||||
|
@ -54,6 +54,12 @@ js::GlobalObject::getRegExpStatics() const
|
||||
return static_cast<RegExpStatics *>(resObj.getPrivate());
|
||||
}
|
||||
|
||||
inline size_t
|
||||
SizeOfRegExpStaticsData(const JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
|
||||
{
|
||||
return mallocSizeOf(obj->getPrivate());
|
||||
}
|
||||
|
||||
inline
|
||||
RegExpStatics::RegExpStatics()
|
||||
: bufferLink(NULL),
|
||||
|
@ -69,7 +69,7 @@ resc_trace(JSTracer *trc, JSObject *obj)
|
||||
res->mark(trc);
|
||||
}
|
||||
|
||||
static Class regexp_statics_class = {
|
||||
Class js::RegExpStaticsClass = {
|
||||
"RegExpStatics",
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
@ -92,7 +92,7 @@ static Class regexp_statics_class = {
|
||||
JSObject *
|
||||
RegExpStatics::create(JSContext *cx, GlobalObject *parent)
|
||||
{
|
||||
JSObject *obj = NewObjectWithGivenProto(cx, ®exp_statics_class, NULL, parent);
|
||||
JSObject *obj = NewObjectWithGivenProto(cx, &RegExpStaticsClass, NULL, parent);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
RegExpStatics *res = cx->new_<RegExpStatics>();
|
||||
|
@ -261,6 +261,8 @@ class PreserveRegExpStatics
|
||||
inline ~PreserveRegExpStatics();
|
||||
};
|
||||
|
||||
size_t SizeOfRegExpStaticsData(const JSObject *obj, JSMallocSizeOfFun mallocSizeOf);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif
|
||||
|
@ -1491,7 +1491,7 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"object-slots"),
|
||||
"objects/slots"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.objectSlots,
|
||||
"Memory allocated for the compartment's non-fixed object slot arrays, "
|
||||
"which are used to represent object properties. Some objects also "
|
||||
@ -1501,12 +1501,19 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"object-elements"),
|
||||
"objects/elements"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.objectElements,
|
||||
"Memory allocated for the compartment's object element arrays, "
|
||||
"which are used to represent indexed object properties.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"objects/misc"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.objectMisc,
|
||||
"Memory allocated for various small, miscellaneous "
|
||||
"structures that hang off certain kinds of objects.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"string-chars"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.stringChars,
|
||||
|
Loading…
Reference in New Issue
Block a user