Bug 692277 - Part a: Introduce an unstable public API for JS memory measurements to be used in XPCJSRuntime; r=njn sr=dmandelin

This commit is contained in:
Ms2ger 2011-12-24 09:27:39 +01:00
Родитель 7299311a32
Коммит d153c9927f
17 изменённых файлов: 237 добавлений и 104 удалений

104
js/public/MemoryMetrics.h Normal file
Просмотреть файл

@ -0,0 +1,104 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is about:memory glue.
*
* The Initial Developer of the Original Code is
* Ms2ger <ms2ger@gmail.com>.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef js_MemoryMetrics_h
#define js_MemoryMetrics_h
/*
* These declarations are not within jsapi.h because they are highly likely
* to change in the future. Depend on them at your own risk.
*/
#include "jspubtd.h"
#include "js/Utility.h"
namespace JS {
/* Data for tracking analysis/inference memory usage. */
struct TypeInferenceMemoryStats
{
int64_t scripts;
int64_t objects;
int64_t tables;
int64_t temporary;
};
extern JS_PUBLIC_API(void)
SizeOfCompartmentTypeInferenceData(JSContext *cx, JSCompartment *compartment,
TypeInferenceMemoryStats *stats,
JSMallocSizeOfFun mallocSizeOf);
extern JS_PUBLIC_API(void)
SizeOfObjectTypeInferenceData(/*TypeObject*/ void *object,
TypeInferenceMemoryStats *stats,
JSMallocSizeOfFun mallocSizeOf);
extern JS_PUBLIC_API(size_t)
SizeOfObjectDynamicSlots(JSObject *obj, JSMallocSizeOfFun mallocSizeOf);
extern JS_PUBLIC_API(size_t)
SizeOfCompartmentShapeTable(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf);
extern JS_PUBLIC_API(size_t)
SizeOfCompartmentMjitCode(const JSCompartment *c);
extern JS_PUBLIC_API(bool)
IsShapeInDictionary(const void *shape);
extern JS_PUBLIC_API(size_t)
SizeOfShapePropertyTable(const void *shape, JSMallocSizeOfFun mallocSizeOf);
extern JS_PUBLIC_API(size_t)
SizeOfShapeKids(const void *shape, JSMallocSizeOfFun mallocSizeOf);
extern JS_PUBLIC_API(size_t)
SizeOfScriptData(JSScript *script, JSMallocSizeOfFun mallocSizeOf);
#ifdef JS_METHODJIT
extern JS_PUBLIC_API(size_t)
SizeOfScriptJitData(JSScript *script, JSMallocSizeOfFun mallocSizeOf);
#endif
extern JS_PUBLIC_API(size_t)
SystemCompartmentCount(const JSRuntime *rt);
extern JS_PUBLIC_API(size_t)
UserCompartmentCount(const JSRuntime *rt);
} // namespace JS
#endif // js_MemoryMetrics_h

Просмотреть файл

@ -269,6 +269,7 @@ EXPORTS_NAMESPACES += js
EXPORTS_js = \
HashTable.h \
LegacyIntTypes.h \
MemoryMetrics.h \
TemplateLib.h \
Utility.h \
Vector.h \

Просмотреть файл

@ -18,6 +18,7 @@
#include "jsxdrapi.h"
#include "js/HashTable.h"
#include "js/MemoryMetrics.h"
#include "js/TemplateLib.h"
#include "js/Utility.h"
#include "js/Vector.h"

Просмотреть файл

@ -86,6 +86,7 @@
#include "builtin/RegExp.h"
#include "frontend/BytecodeCompiler.h"
#include "frontend/BytecodeEmitter.h"
#include "js/MemoryMetrics.h"
#include "jsatominlines.h"
#include "jsinferinlines.h"
@ -923,6 +924,30 @@ JS_SetRuntimePrivate(JSRuntime *rt, void *data)
rt->data = data;
}
JS_PUBLIC_API(size_t)
JS::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)
JS::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;
}
#ifdef JS_THREADSAFE
static void
StartRequest(JSContext *cx)

Просмотреть файл

@ -48,12 +48,14 @@
#include "jsscope.h"
#include "jswatchpoint.h"
#include "jswrapper.h"
#include "assembler/wtf/Platform.h"
#include "yarr/BumpPointerAllocator.h"
#include "js/MemoryMetrics.h"
#include "methodjit/MethodJIT.h"
#include "methodjit/PolyIC.h"
#include "methodjit/MonoIC.h"
#include "vm/Debugger.h"
#include "yarr/BumpPointerAllocator.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
@ -142,17 +144,24 @@ JSCompartment::ensureJaegerCompartmentExists(JSContext *cx)
return true;
}
void
JSCompartment::sizeOfCode(size_t *method, size_t *regexp, size_t *unused) const
size_t
JSCompartment::sizeOfMjitCode() const
{
if (jaegerCompartment_) {
jaegerCompartment_->execAlloc()->sizeOfCode(method, regexp, unused);
} else {
*method = 0;
*regexp = 0;
*unused = 0;
}
if (!jaegerCompartment_)
return 0;
size_t method, regexp, unused;
jaegerCompartment_->execAlloc()->sizeOfCode(&method, &regexp, &unused);
JS_ASSERT(regexp == 0);
return method + unused;
}
JS_PUBLIC_API(size_t)
JS::SizeOfCompartmentMjitCode(const JSCompartment *c)
{
return c->sizeOfMjitCode();
}
#endif
bool
@ -740,3 +749,12 @@ JSCompartment::createBarrierTracer()
JS_ASSERT(!gcIncrementalTracer);
return NULL;
}
JS_PUBLIC_API(size_t)
JS::SizeOfCompartmentShapeTable(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf)
{
return c->baseShapes.sizeOfExcludingThis(mallocSizeOf)
+ c->initialShapes.sizeOfExcludingThis(mallocSizeOf)
+ c->newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
+ c->lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
}

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -235,7 +235,7 @@ struct JS_FRIEND_API(JSCompartment) {
bool ensureJaegerCompartmentExists(JSContext *cx);
void sizeOfCode(size_t *method, size_t *regexp, size_t *unused) const;
size_t sizeOfMjitCode() const;
#endif
/*

Просмотреть файл

@ -184,21 +184,6 @@ AutoSwitchCompartment::~AutoSwitchCompartment()
cx->compartment = oldCompartment;
}
JS_FRIEND_API(size_t)
js::GetObjectDynamicSlotSize(JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
{
return obj->dynamicSlotSize(mallocSizeOf);
}
JS_FRIEND_API(size_t)
js::GetCompartmentShapeTableSize(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf)
{
return c->baseShapes.sizeOfExcludingThis(mallocSizeOf)
+ c->initialShapes.sizeOfExcludingThis(mallocSizeOf)
+ c->newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
+ c->lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
}
JS_FRIEND_API(bool)
js::IsScopeObject(const JSObject *obj)
{

Просмотреть файл

@ -114,25 +114,6 @@ typedef void
extern JS_FRIEND_API(void)
JS_SetGCFinishedCallback(JSRuntime *rt, JSGCFinishedCallback callback);
/* Data for tracking analysis/inference memory usage. */
typedef struct TypeInferenceMemoryStats
{
int64_t scripts;
int64_t objects;
int64_t tables;
int64_t temporary;
} TypeInferenceMemoryStats;
extern JS_FRIEND_API(void)
JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
TypeInferenceMemoryStats *stats,
JSMallocSizeOfFun mallocSizeOf);
extern JS_FRIEND_API(void)
JS_GetTypeInferenceObjectStats(/*TypeObject*/ void *object,
TypeInferenceMemoryStats *stats,
JSMallocSizeOfFun mallocSizeOf);
extern JS_FRIEND_API(JSPrincipals *)
JS_GetCompartmentPrincipals(JSCompartment *compartment);
@ -209,12 +190,6 @@ JS_FRIEND_API(JSBool) obj_defineGetter(JSContext *cx, uintN argc, js::Value *vp)
JS_FRIEND_API(JSBool) obj_defineSetter(JSContext *cx, uintN argc, js::Value *vp);
#endif
extern JS_FRIEND_API(size_t)
GetObjectDynamicSlotSize(JSObject *obj, JSMallocSizeOfFun mallocSizeOf);
extern JS_FRIEND_API(size_t)
GetCompartmentShapeTableSize(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf);
/*
* Check whether it is OK to assign an undeclared property with name
* propname of the global object in the current script on cx. Reports

Просмотреть файл

@ -56,6 +56,7 @@
#include "jsiter.h"
#include "frontend/TokenStream.h"
#include "js/MemoryMetrics.h"
#include "methodjit/MethodJIT.h"
#include "methodjit/Retcon.h"
@ -6294,7 +6295,7 @@ GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSMalloc
/*
* This counts memory that is in the temp pool but gets attributed
* elsewhere. See JS_GetTypeInferenceMemoryStats for more details.
* elsewhere. See JS::SizeOfCompartmentTypeInferenceData for more details.
*/
TypeSet *typeArray = typeScript->typeArray();
for (unsigned i = 0; i < count; i++) {
@ -6304,10 +6305,10 @@ GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSMalloc
}
}
JS_FRIEND_API(void)
JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
TypeInferenceMemoryStats *stats,
JSMallocSizeOfFun mallocSizeOf)
JS_PUBLIC_API(void)
JS::SizeOfCompartmentTypeInferenceData(JSContext *cx, JSCompartment *compartment,
TypeInferenceMemoryStats *stats,
JSMallocSizeOfFun mallocSizeOf)
{
/*
* Note: not all data in the pool is temporary, and some will survive GCs
@ -6350,8 +6351,8 @@ JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
}
}
JS_FRIEND_API(void)
JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats, JSMallocSizeOfFun mallocSizeOf)
JS_PUBLIC_API(void)
JS::SizeOfObjectTypeInferenceData(void *object_, TypeInferenceMemoryStats *stats, JSMallocSizeOfFun mallocSizeOf)
{
TypeObject *object = (TypeObject *) object_;

Просмотреть файл

@ -82,6 +82,7 @@
#include "frontend/BytecodeCompiler.h"
#include "frontend/BytecodeEmitter.h"
#include "frontend/Parser.h"
#include "js/MemoryMetrics.h"
#include "jsarrayinlines.h"
#include "jsinterpinlines.h"
@ -7130,6 +7131,12 @@ js::HandleNonGenericMethodClassMismatch(JSContext *cx, CallArgs args, Native nat
return false;
}
JS_PUBLIC_API(size_t)
JS::SizeOfObjectDynamicSlots(JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
{
return obj->dynamicSlotSize(mallocSizeOf);
}
#ifdef DEBUG
/*

Просмотреть файл

@ -59,6 +59,8 @@
#include "jsscope.h"
#include "jsstr.h"
#include "js/MemoryMetrics.h"
#include "jsatominlines.h"
#include "jsobjinlines.h"
#include "jsscopeinlines.h"
@ -1449,3 +1451,21 @@ JSCompartment::sweepInitialShapeTable(JSContext *cx)
}
}
}
JS_PUBLIC_API(bool)
JS::IsShapeInDictionary(const void *shape)
{
return static_cast<const Shape*>(shape)->inDictionary();
}
JS_PUBLIC_API(size_t)
JS::SizeOfShapePropertyTable(const void *shape, JSMallocSizeOfFun mallocSizeOf)
{
return static_cast<const Shape*>(shape)->sizeOfPropertyTable(mallocSizeOf);
}
JS_PUBLIC_API(size_t)
JS::SizeOfShapeKids(const void *shape, JSMallocSizeOfFun mallocSizeOf)
{
return static_cast<const Shape*>(shape)->sizeOfKids(mallocSizeOf);
}

Просмотреть файл

@ -68,6 +68,7 @@
#include "frontend/BytecodeEmitter.h"
#include "frontend/Parser.h"
#include "js/MemoryMetrics.h"
#include "methodjit/MethodJIT.h"
#include "methodjit/Retcon.h"
#include "vm/Debugger.h"
@ -1311,6 +1312,12 @@ JSScript::dataSize(JSMallocSizeOfFun mallocSizeOf)
return mallocSizeOf(data, dataSize());
}
JS_PUBLIC_API(size_t)
JS::SizeOfScriptData(JSScript *script, JSMallocSizeOfFun mallocSizeOf)
{
return script->dataSize(mallocSizeOf);
}
/*
* Nb: srcnotes are variable-length. This function computes the number of
* srcnote *slots*, which may be greater than the number of srcnotes.

Просмотреть файл

@ -651,8 +651,8 @@ struct JSScript : public js::gc::Cell {
return JITScript_Valid;
}
/* Size of the JITScript and all sections. (This method is implemented in MethodJIT.h.) */
JS_FRIEND_API(size_t) jitDataSize(JSMallocSizeOfFun mallocSizeOf);
/* Size of the JITScript and all sections. (This method is implemented in MethodJIT.cpp.) */
size_t jitDataSize(JSMallocSizeOfFun mallocSizeOf);
#endif

Просмотреть файл

@ -40,6 +40,7 @@
#include "Logging.h"
#include "assembler/jit/ExecutableAllocator.h"
#include "assembler/assembler/RepatchBuffer.h"
#include "js/MemoryMetrics.h"
#include "jsgcmark.h"
#include "BaseAssembler.h"
#include "Compiler.h"
@ -1312,6 +1313,12 @@ JSScript::jitDataSize(JSMallocSizeOfFun mallocSizeOf)
return n;
}
JS_PUBLIC_API(size_t)
JS::SizeOfScriptJitData(JSScript *script, JSMallocSizeOfFun mallocSizeOf)
{
return script->jitDataSize(mallocSizeOf);
}
/* Please keep in sync with Compiler::finishThisUp! */
size_t
mjit::JITScript::scriptDataSize(JSMallocSizeOfFun mallocSizeOf)

Просмотреть файл

@ -3825,11 +3825,9 @@ MJitCodeStats(JSContext *cx, uintN argc, jsval *vp)
#ifdef JS_METHODJIT
JSRuntime *rt = cx->runtime;
AutoLockGC lock(rt);
size_t n = 0, method, regexp, unused;
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
{
(*c)->sizeOfCode(&method, &regexp, &unused);
n += method + regexp + unused;
size_t n = 0;
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) {
n += (*c)->sizeOfMjitCode();
}
JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
#else

Просмотреть файл

@ -49,8 +49,6 @@
#include "dom_quickstubs.h"
#include "jscompartment.h"
#include "jsgcchunk.h"
#include "jsscope.h"
#include "nsIMemoryReporter.h"
#include "nsPrintfCString.h"
#include "mozilla/FunctionTimer.h"
@ -60,6 +58,8 @@
#include "nsContentUtils.h"
#include "js/MemoryMetrics.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
@ -1240,7 +1240,7 @@ namespace {
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
void
CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
CompartmentMemoryCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
{
// Append a new CompartmentStats to the vector.
IterateData *data = static_cast<IterateData *>(vdata);
@ -1251,15 +1251,13 @@ CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
// Get the compartment-level numbers.
#ifdef JS_METHODJIT
size_t method, regexp, unused;
compartment->sizeOfCode(&method, &regexp, &unused);
JS_ASSERT(regexp == 0); /* this execAlloc is only used for method code */
curr->mjitCode = method + unused;
curr->mjitCode = JS::SizeOfCompartmentMjitCode(compartment);
#endif
JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
JsMallocSizeOf);
JS::SizeOfCompartmentTypeInferenceData(cx, compartment,
&curr->typeInferenceMemory,
JsMallocSizeOf);
curr->shapesCompartmentTables =
js::GetCompartmentShapeTableSize(compartment, JsMallocSizeOf);
JS::SizeOfCompartmentShapeTable(compartment, JsMallocSizeOf);
}
void
@ -1306,7 +1304,7 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
} else {
curr->gcHeapObjectsNonFunction += thingSize;
}
curr->objectSlots += js::GetObjectDynamicSlotSize(obj, JsMallocSizeOf);
curr->objectSlots += JS::SizeOfObjectDynamicSlots(obj, JsMallocSizeOf);
break;
}
case JSTRACE_STRING:
@ -1318,17 +1316,16 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
}
case JSTRACE_SHAPE:
{
js::Shape *shape = static_cast<js::Shape *>(thing);
if (shape->inDictionary()) {
if (JS::IsShapeInDictionary(thing)) {
curr->gcHeapShapesDict += thingSize;
curr->shapesExtraDictTables +=
shape->sizeOfPropertyTable(JsMallocSizeOf);
JS::SizeOfShapePropertyTable(thing, JsMallocSizeOf);
} else {
curr->gcHeapShapesTree += thingSize;
curr->shapesExtraTreeTables +=
shape->sizeOfPropertyTable(JsMallocSizeOf);
JS::SizeOfShapePropertyTable(thing, JsMallocSizeOf);
curr->shapesExtraTreeShapeKids +=
shape->sizeOfKids(JsMallocSizeOf);
JS::SizeOfShapeKids(thing, JsMallocSizeOf);
}
break;
}
@ -1341,9 +1338,9 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
{
JSScript *script = static_cast<JSScript *>(thing);
curr->gcHeapScripts += thingSize;
curr->scriptData += script->dataSize(JsMallocSizeOf);
curr->scriptData += JS::SizeOfScriptData(script, JsMallocSizeOf);
#ifdef JS_METHODJIT
curr->mjitData += script->jitDataSize(JsMallocSizeOf);
curr->mjitData += JS::SizeOfScriptJitData(script, JsMallocSizeOf);
#endif
break;
}
@ -1351,8 +1348,8 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
{
js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
curr->gcHeapTypeObjects += thingSize;
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory,
JsMallocSizeOf);
JS::SizeOfObjectTypeInferenceData(obj, &curr->typeInferenceMemory,
JsMallocSizeOf);
break;
}
case JSTRACE_XML:
@ -1464,27 +1461,13 @@ NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSGCHeap,
static PRInt64
GetJSSystemCompartmentCount()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
size_t n = 0;
for (size_t i = 0; i < rt->compartments.length(); i++) {
if (rt->compartments[i]->isSystemCompartment) {
n++;
}
}
return n;
return JS::SystemCompartmentCount(nsXPConnect::GetRuntimeInstance()->GetJSRuntime());
}
static PRInt64
GetJSUserCompartmentCount()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
size_t n = 0;
for (size_t i = 0; i < rt->compartments.length(); i++) {
if (!rt->compartments[i]->isSystemCompartment) {
n++;
}
}
return n;
return JS::UserCompartmentCount(nsXPConnect::GetRuntimeInstance()->GetJSRuntime());
}
// Nb: js-system-compartment-count + js-user-compartment-count could be
@ -1581,7 +1564,7 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
PRInt64(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) *
js::gc::ChunkSize;
js::IterateCompartmentsArenasCells(cx, data, CompartmentCallback,
js::IterateCompartmentsArenasCells(cx, data, CompartmentMemoryCallback,
ArenaCallback, CellCallback);
js::IterateChunks(cx, data, ChunkCallback);

Просмотреть файл

@ -41,6 +41,7 @@
#define xpcpublic_h
#include "jsapi.h"
#include "js/MemoryMetrics.h"
#include "jsclass.h"
#include "jsfriendapi.h"
#include "jsgc.h"
@ -239,7 +240,7 @@ struct CompartmentStats
PRInt64 mjitCode;
PRInt64 mjitData;
#endif
TypeInferenceMemoryStats typeInferenceMemory;
JS::TypeInferenceMemoryStats typeInferenceMemory;
};
struct IterateData