Bug 720219 (part 1) - Clean up JS object measurement. r=bhackett.

--HG--
extra : rebase_source : ff9aa7da84814e6868fef88b56bcb038389d5fb9
This commit is contained in:
Nicholas Nethercote 2012-01-23 15:35:37 -08:00
parent 37bf75c74d
commit bdcd8d9251
8 changed files with 50 additions and 29 deletions

View File

@ -101,6 +101,7 @@ struct CompartmentStats
int64_t gcHeapXML;
int64_t objectSlots;
int64_t objectElements;
int64_t stringChars;
int64_t shapesExtraTreeTables;
int64_t shapesExtraDictTables;

View File

@ -130,7 +130,10 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
} else {
curr->gcHeapObjectsNonFunction += thingSize;
}
curr->objectSlots += obj->dynamicSlotSize(data->mallocSizeOf);
size_t slotsSize, elementsSize;
obj->sizeOfExcludingThis(data->mallocSizeOf, &slotsSize, &elementsSize);
curr->objectSlots += slotsSize;
curr->objectElements += elementsSize;
break;
}
case JSTRACE_STRING:
@ -272,7 +275,8 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
data->gcHeapArenaUnused += stats.gcHeapArenaUnused;
data->totalObjects += stats.gcHeapObjectsNonFunction +
stats.gcHeapObjectsFunction +
stats.objectSlots;
stats.objectSlots +
stats.objectElements;
data->totalShapes += stats.gcHeapShapesTree +
stats.gcHeapShapesDict +
stats.gcHeapShapesBase +

View File

@ -979,7 +979,7 @@ JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
JS_PUBLIC_API(size_t)
JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
{
return obj->slotsAndStructSize();
return obj->computedSizeOfIncludingThis();
}
static size_t

View File

@ -3419,7 +3419,7 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
* swaps can be performed infallibly.
*/
if (a->structSize() == b->structSize())
if (a->sizeOfThis() == b->sizeOfThis())
return true;
/*
@ -3512,7 +3512,7 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
JS_ASSERT(a->isFunction() == b->isFunction());
/* Don't try to swap a JSFunction for a plain function JSObject. */
JS_ASSERT_IF(a->isFunction(), a->structSize() == b->structSize());
JS_ASSERT_IF(a->isFunction(), a->sizeOfThis() == b->sizeOfThis());
/*
* Regexp guts are more complicated -- we would need to migrate the
@ -3542,8 +3542,8 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
#endif
/* Trade the guts of the objects. */
const size_t size = a->structSize();
if (size == b->structSize()) {
const size_t size = a->sizeOfThis();
if (size == b->sizeOfThis()) {
/*
* If the objects are the same size, then we make no assumptions about
* whether they have dynamically allocated slots and instead just copy
@ -4098,7 +4098,7 @@ JSObject::growSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
*/
JS_ASSERT(newCount < NELEMENTS_LIMIT);
size_t oldSize = Probes::objectResizeActive() ? slotsAndStructSize() : 0;
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfIncludingThis() : 0;
size_t newSize = oldSize + (newCount - oldCount) * sizeof(Value);
/*
@ -4167,7 +4167,7 @@ JSObject::shrinkSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
if (isCall())
return;
size_t oldSize = Probes::objectResizeActive() ? slotsAndStructSize() : 0;
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfIncludingThis() : 0;
size_t newSize = oldSize - (oldCount - newCount) * sizeof(Value);
if (newCount == 0) {
@ -4213,7 +4213,7 @@ JSObject::growElements(JSContext *cx, uintN newcap)
uint32_t oldcap = getDenseArrayCapacity();
JS_ASSERT(oldcap <= newcap);
size_t oldSize = Probes::objectResizeActive() ? slotsAndStructSize() : 0;
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfIncludingThis() : 0;
uint32_t nextsize = (oldcap <= CAPACITY_DOUBLING_MAX)
? oldcap * 2
@ -4256,7 +4256,7 @@ JSObject::growElements(JSContext *cx, uintN newcap)
Debug_SetValueRangeToCrashOnTouch(elements + initlen, actualCapacity - initlen);
if (Probes::objectResizeActive())
Probes::resizeObject(cx, this, oldSize, slotsAndStructSize());
Probes::resizeObject(cx, this, oldSize, computedSizeOfIncludingThis());
return true;
}
@ -4269,7 +4269,7 @@ JSObject::shrinkElements(JSContext *cx, uintN newcap)
uint32_t oldcap = getDenseArrayCapacity();
JS_ASSERT(newcap <= oldcap);
size_t oldSize = Probes::objectResizeActive() ? slotsAndStructSize() : 0;
size_t oldSize = Probes::objectResizeActive() ? computedSizeOfIncludingThis() : 0;
/* Don't shrink elements below the minimum capacity. */
if (oldcap <= SLOT_CAPACITY_MIN || !hasDynamicElements())
@ -4288,7 +4288,7 @@ JSObject::shrinkElements(JSContext *cx, uintN newcap)
elements = newheader->elements();
if (Probes::objectResizeActive())
Probes::resizeObject(cx, this, oldSize, slotsAndStructSize());
Probes::resizeObject(cx, this, oldSize, computedSizeOfIncludingThis());
}
#ifdef DEBUG

View File

@ -669,9 +669,12 @@ struct JSObject : js::gc::Cell
inline bool hasPropertyTable() const;
inline size_t structSize() const;
inline size_t slotsAndStructSize() const;
inline size_t dynamicSlotSize(JSMallocSizeOfFun mallocSizeOf) const;
inline size_t sizeOfThis() const;
inline size_t computedSizeOfIncludingThis() 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;
inline size_t numFixedSlots() const;

View File

@ -1199,32 +1199,38 @@ JSObject::hasPropertyTable() const
}
inline size_t
JSObject::structSize() const
JSObject::sizeOfThis() const
{
return arenaHeader()->getThingSize();
}
inline size_t
JSObject::slotsAndStructSize() const
JSObject::computedSizeOfIncludingThis() const
{
return structSize() + dynamicSlotSize(NULL);
size_t slotsSize, elementsSize;
sizeOfExcludingThis(NULL, &slotsSize, &elementsSize);
return sizeOfThis() + slotsSize + elementsSize;
}
inline size_t
JSObject::dynamicSlotSize(JSMallocSizeOfFun mallocSizeOf) const
inline void
JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
size_t *slotsSize, size_t *elementsSize) const
{
size_t size = 0;
if (hasDynamicSlots()) {
size_t bytes = numDynamicSlots() * sizeof(js::Value);
size += mallocSizeOf ? mallocSizeOf(slots, bytes) : bytes;
size_t computedSize = numDynamicSlots() * sizeof(js::Value);
*slotsSize = mallocSizeOf ? mallocSizeOf(slots, computedSize) : computedSize;
} else {
*slotsSize = 0;
}
if (hasDynamicElements()) {
size_t bytes =
size_t computedSize =
(js::ObjectElements::VALUES_PER_HEADER +
getElementsHeader()->capacity) * sizeof(js::Value);
size += mallocSizeOf ? mallocSizeOf(getElementsHeader(), bytes) : bytes;
*elementsSize =
mallocSizeOf ? mallocSizeOf(getElementsHeader(), computedSize) : computedSize;
} else {
*elementsSize = 0;
}
return size;
}
inline JSBool
@ -1564,7 +1570,7 @@ NewObjectCache::fill(EntryIndex entry_, Class *clasp, gc::Cell *key, gc::AllocKi
entry->key = key;
entry->kind = kind;
entry->nbytes = obj->structSize();
entry->nbytes = obj->sizeOfThis();
js_memcpy(&entry->templateObject, obj, entry->nbytes);
}

View File

@ -444,7 +444,7 @@ Probes::ETWCreateObject(JSContext *cx, JSObject *obj)
return EventWriteEvtObjectCreate(script_filename, lineno,
ObjectClassname(obj), reinterpret_cast<uint64_t_t>(obj),
obj ? obj->slotsAndStructSize() : 0) == ERROR_SUCCESS;
obj ? obj->computedSizeOfIncludingThis() : 0) == ERROR_SUCCESS;
}
bool

View File

@ -1513,6 +1513,13 @@ ReportCompartmentStats(const JS::CompartmentStats &stats,
"'gc-heap/objects' instead." SLOP_BYTES_STRING,
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
"object-elements"),
nsIMemoryReporter::KIND_HEAP, stats.objectElements,
"Memory allocated for the compartment's object element arrays, "
"which are used to represent indexed object properties." SLOP_BYTES_STRING,
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
"string-chars"),
nsIMemoryReporter::KIND_HEAP, stats.stringChars,