Merge TM -> JM

This commit is contained in:
Brian Hackett 2011-07-08 17:52:15 -07:00
commit efef17855f
22 changed files with 283 additions and 75 deletions

View File

@ -105,8 +105,7 @@ AtomDecls::lookupMulti(JSAtom *atom)
DefnOrHeader &doh = p.value();
if (doh.isHeader())
return MultiDeclRange(doh.header());
else
return MultiDeclRange(doh.defn());
return MultiDeclRange(doh.defn());
}
inline bool

View File

@ -286,6 +286,18 @@ ArenaNew(JSArenaPool &pool, const A &a, const B &b, const C &c, const D &d, cons
return v ? new (v) T(a, b, c, d, e) : NULL;
}
inline uintN
ArenaAllocatedSize(const JSArenaPool &pool)
{
uintN res = 0;
const JSArena *a = &pool.first;
while (a) {
res += (a->limit - (jsuword)a);
a = a->next;
}
return res;
}
} /* namespace js */
#endif /* __cplusplus */

View File

@ -85,6 +85,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
propertyTree(thisForCtor()),
emptyArgumentsShape(NULL),
emptyBlockShape(NULL),
emptyCallShape(NULL),
emptyDeclEnvShape(NULL),
emptyEnumeratorShape(NULL),
emptyWithShape(NULL),
@ -515,6 +516,8 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
emptyArgumentsShape = NULL;
if (emptyBlockShape && IsAboutToBeFinalized(cx, emptyBlockShape))
emptyBlockShape = NULL;
if (emptyCallShape && IsAboutToBeFinalized(cx, emptyCallShape))
emptyCallShape = NULL;
if (emptyDeclEnvShape && IsAboutToBeFinalized(cx, emptyDeclEnvShape))
emptyDeclEnvShape = NULL;
if (emptyEnumeratorShape && IsAboutToBeFinalized(cx, emptyEnumeratorShape))

View File

@ -394,6 +394,18 @@ struct JS_FRIEND_API(JSCompartment) {
bool condenseTypes(JSContext *cx);
/* Data for tracking analysis/inference memory usage. */
struct TypeInferenceMemoryStats
{
int64 scriptMain;
int64 scriptSets;
int64 objectMain;
int64 objectSets;
int64 poolMain;
};
void getTypeInferenceMemoryStats(TypeInferenceMemoryStats *stats);
#ifdef JS_TRACER
private:
/*
@ -452,10 +464,11 @@ struct JS_FRIEND_API(JSCompartment) {
/*
* Runtime-shared empty scopes for well-known built-in objects that lack
* class prototypes (the usual locus of an emptyShape). Mnemonic: ABDEW
* class prototypes (the usual locus of an emptyShape). Mnemonic: ABCDEW
*/
js::EmptyShape *emptyArgumentsShape;
js::EmptyShape *emptyBlockShape;
js::EmptyShape *emptyCallShape;
js::EmptyShape *emptyDeclEnvShape;
js::EmptyShape *emptyEnumeratorShape;
js::EmptyShape *emptyWithShape;

View File

@ -121,6 +121,7 @@ JSCodeGenerator::JSCodeGenerator(Parser *parser,
constMap(parser->context),
constList(parser->context),
upvarIndices(parser->context),
upvarMap(parser->context),
globalUses(parser->context),
globalMap(parser->context),
closedArgs(parser->context),
@ -134,7 +135,6 @@ JSCodeGenerator::JSCodeGenerator(Parser *parser,
current = &main;
firstLine = prolog.currentLine = main.currentLine = lineno;
prolog.noteMask = main.noteMask = SRCNOTE_CHUNK - 1;
memset(&upvarMap, 0, sizeof upvarMap);
}
bool
@ -154,9 +154,6 @@ JSCodeGenerator::~JSCodeGenerator()
/* NB: non-null only after OOM. */
if (spanDeps)
cx->free_(spanDeps);
if (upvarMap.vector)
cx->free_(upvarMap.vector);
}
static ptrdiff_t
@ -2339,17 +2336,13 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (!cg->upvarIndices->add(p, atom, index))
return JS_FALSE;
UpvarCookie *vector = cg->upvarMap.vector;
uint32 length = cg->roLexdeps->count();
if (!vector || cg->upvarMap.length != length) {
vector = (UpvarCookie *) cx->realloc_(vector, length * sizeof *vector);
if (!vector) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;
}
cg->upvarMap.vector = vector;
cg->upvarMap.length = length;
}
UpvarCookies &upvarMap = cg->upvarMap;
/* upvarMap should have the same number of UpvarCookies as there are lexdeps. */
size_t lexdepCount = cg->roLexdeps->count();
JS_ASSERT_IF(!upvarMap.empty(), lexdepCount == upvarMap.length());
if (upvarMap.empty() && !upvarMap.appendN(UpvarCookie(), lexdepCount))
return JS_FALSE;
uintN slot = cookie.slot();
if (slot != UpvarCookie::CALLEE_SLOT && dn_kind != JSDefinition::ARG) {
@ -2361,8 +2354,8 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
slot += tc->fun()->nargs;
}
JS_ASSERT(index < cg->upvarMap.length);
vector[index].set(skip, slot);
JS_ASSERT(index < upvarMap.length());
upvarMap[index].set(skip, slot);
}
pn->pn_op = JSOP_GETFCSLOT;

View File

@ -644,7 +644,8 @@ struct JSCodeGenerator : public JSTreeContext
cloned during execution */
js::OwnedAtomIndexMapPtr upvarIndices; /* map of atoms to upvar indexes */
JSUpvarArray upvarMap; /* indexed upvar pairs (JS_realloc'ed) */
js::UpvarCookies upvarMap; /* indexed upvar slot locations */
typedef js::Vector<js::GlobalSlotArray::Entry, 16> GlobalUseVector;

View File

@ -516,6 +516,8 @@ public:
}
TypeObject * persistentObject() { return object; }
size_t allocatedSize() { return sizeof(TypeConstraintBaseSubset); }
};
void
@ -556,6 +558,8 @@ public:
void newObjectState(JSContext *cx, TypeObject*, bool) { checkAnalysis(cx); }
bool condensed() { return true; }
size_t allocatedSize() { return sizeof(TypeConstraintCondensed); }
};
bool
@ -1880,8 +1884,10 @@ TypeCompartment::init(JSContext *cx)
#endif
typeEmpty.flags = OBJECT_FLAG_UNKNOWN_MASK;
#ifndef JS_CPU_ARM
if (cx && cx->getRunOptions() & JSOPTION_TYPE_INFERENCE)
inferenceEnabled = true;
#endif
}
TypeObject *
@ -4296,6 +4302,8 @@ class TypeIntermediateClearDefinite : public TypeIntermediate
{
return object->marked;
}
size_t allocatedSize() { return sizeof(TypeIntermediateClearDefinite); }
};
static bool
@ -4564,7 +4572,7 @@ types::CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSScript *scrip
Vector<TypeNewScript::Initializer> initializerList(cx);
AnalyzeNewScriptProperties(cx, type, script, &baseobj, &initializerList);
if (!baseobj || baseobj->slotSpan() == 0 && type->newScriptCleared)
if (!baseobj || (baseobj->slotSpan() == 0 && type->newScriptCleared))
return;
gc::FinalizeKind kind = gc::GetGCObjectKind(baseobj->slotSpan());
@ -4837,6 +4845,8 @@ class TypeIntermediatePushed : public TypeIntermediate
return false;
}
size_t allocatedSize() { return sizeof(TypeIntermediatePushed); }
};
void
@ -5464,6 +5474,9 @@ SweepTypeObjectList(JSContext *cx, TypeObject *&objects)
if (count >= 2)
cx->free_(object->propertySet);
if (object->newScript)
cx->free_(object->newScript);
cx->delete_(object);
}
}
@ -5639,3 +5652,76 @@ JSScript::sweepAnalysis(JSContext *cx)
analysis_ = NULL;
}
}
size_t
TypeSet::dynamicSize()
{
size_t res = 0;
if (objectCount >= 2)
res += HashSetCapacity(objectCount) * sizeof(TypeObject *);
/* Get the total size of any heap-allocated constraints on this set. */
TypeConstraint *constraint = constraintList;
while (constraint) {
res += constraint->allocatedSize();
constraint = constraint->next;
}
return res;
}
static void
GetObjectListMemoryStats(TypeObject *object, JSCompartment::TypeInferenceMemoryStats *stats)
{
while (object) {
stats->objectMain += sizeof(TypeObject);
if (object->propertyCount >= 2)
stats->objectMain += HashSetCapacity(object->propertyCount) * sizeof(Property *);
unsigned count = object->getPropertyCount();
for (unsigned i = 0; i < count; i++) {
Property *prop = object->getProperty(i);
if (prop) {
stats->objectMain += sizeof(Property);
stats->objectSets += prop->types.dynamicSize();
}
}
object = object->next;
}
}
static void
GetScriptMemoryStats(JSScript *script, JSCompartment::TypeInferenceMemoryStats *stats)
{
GetObjectListMemoryStats(script->types.typeObjects, stats);
if (!script->types.typeArray)
return;
unsigned count = script->types.numTypeSets();
stats->scriptMain += count * sizeof(TypeSet);
for (unsigned i = 0; i < count; i++)
stats->scriptSets += script->types.typeArray[i].dynamicSize();
TypeIntermediate *intermediate = script->types.intermediateList;
while (intermediate) {
stats->scriptMain += intermediate->allocatedSize();
intermediate = intermediate->next;
}
}
void
JSCompartment::getTypeInferenceMemoryStats(TypeInferenceMemoryStats *stats)
{
GetObjectListMemoryStats(types.objects, stats);
for (JSCList *cursor = scripts.next; cursor != &scripts; cursor = cursor->next) {
JSScript *script = reinterpret_cast<JSScript *>(cursor);
GetScriptMemoryStats(script, stats);
}
stats->poolMain += ArenaAllocatedSize(pool);
}

View File

@ -209,6 +209,8 @@ public:
* of any script.
*/
virtual TypeObject * persistentObject() { return NULL; }
virtual size_t allocatedSize() { return 0; }
};
/* Coarse flags for the contents of a type set. */
@ -313,6 +315,7 @@ class TypeSet
void print(JSContext *cx);
inline void destroy(JSContext *cx);
size_t dynamicSize();
/* Whether this set contains a specific type. */
inline bool hasType(jstype type);
@ -487,6 +490,8 @@ class TypeIntermediate
/* Whether this subsumes a dynamic type pushed by the bytecode at offset. */
virtual bool hasDynamicResult(uint32 offset, jstype type) { return false; }
virtual size_t allocatedSize() = 0;
};
/*

View File

@ -1551,21 +1551,14 @@ Parser::functionBody()
return pn;
}
/*
* Creates a placeholder JSDefinition node for |atom| and adds it to the
* current lexdeps.
*/
/* Create a placeholder JSDefinition node for |atom|. */
static JSDefinition *
MakePlaceholder(AtomDefnAddPtr &p, JSParseNode *pn, JSTreeContext *tc)
MakePlaceholder(JSParseNode *pn, JSTreeContext *tc)
{
JSAtom *atom = pn->pn_atom;
JSDefinition *dn = (JSDefinition *) NameNode::create(atom, tc);
JSDefinition *dn = (JSDefinition *) NameNode::create(pn->pn_atom, tc);
if (!dn)
return NULL;
if (!tc->lexdeps->add(p, atom, dn))
return NULL;
dn->pn_type = TOK_NAME;
dn->pn_op = JSOP_NOP;
dn->pn_defn = true;
@ -1896,23 +1889,20 @@ struct BindData {
};
static bool
BindLocalVariable(JSContext *cx, JSTreeContext *tc, JSAtom *atom, BindingKind kind, bool isArg)
BindLocalVariable(JSContext *cx, JSTreeContext *tc, JSParseNode *pn, BindingKind kind)
{
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
/*
* Don't bind a variable with the hidden name 'arguments', per ECMA-262.
* Instead 'var arguments' always restates the predefined property of the
* activation objects whose name is 'arguments'. Assignment to such a
* variable must be handled specially.
*
* Special case: an argument named 'arguments' *does* shadow the predefined
* arguments property.
*/
if (atom == cx->runtime->atomState.argumentsAtom && !isArg)
return true;
/* 'arguments' can be bound as a local only via a destructuring formal parameter. */
JS_ASSERT_IF(pn->pn_atom == cx->runtime->atomState.argumentsAtom, kind == VARIABLE);
return tc->bindings.add(cx, atom, kind);
uintN index = tc->bindings.countVars();
if (!tc->bindings.add(cx, pn->pn_atom, kind))
return false;
pn->pn_cookie.set(tc->staticLevel, index);
pn->pn_dflags |= PND_BOUND;
return true;
}
#if JS_HAS_DESTRUCTURING
@ -2785,8 +2775,8 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, JSAtom *funAtom = NULL,
* inherited lexdeps into uses of a new outer definition
* allows us to handle both these cases in a natural way.
*/
outer_dn = MakePlaceholder(p, dn, tc);
if (!outer_dn)
outer_dn = MakePlaceholder(dn, tc);
if (!outer_dn || !tc->lexdeps->add(p, atom, outer_dn))
return false;
}
}
@ -3184,10 +3174,8 @@ Parser::functionDef(JSAtom *funAtom, FunctionType type, FunctionSyntaxKind kind)
if (apn->pn_op != JSOP_SETLOCAL)
continue;
uint16 index = funtc.bindings.countVars();
if (!BindLocalVariable(context, &funtc, apn->pn_atom, VARIABLE, true))
if (!BindLocalVariable(context, &funtc, apn, VARIABLE))
return NULL;
apn->pn_cookie.set(funtc.staticLevel, index);
}
}
#endif
@ -3773,7 +3761,7 @@ DefineGlobal(JSParseNode *pn, JSCodeGenerator *cg, JSAtom *atom)
}
static bool
BindTopLevelVar(JSContext *cx, BindData *data, JSParseNode *pn, JSAtom *varname, JSTreeContext *tc)
BindTopLevelVar(JSContext *cx, BindData *data, JSParseNode *pn, JSTreeContext *tc)
{
JS_ASSERT(pn->pn_op == JSOP_NAME);
JS_ASSERT(!tc->inFunction());
@ -3826,11 +3814,19 @@ BindTopLevelVar(JSContext *cx, BindData *data, JSParseNode *pn, JSAtom *varname,
}
static bool
BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, JSParseNode *pn,
JSAtom *name, JSTreeContext *tc)
BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, JSTreeContext *tc)
{
JS_ASSERT(tc->inFunction());
JSParseNode *pn = data->pn;
JSAtom *name = pn->pn_atom;
/*
* Don't create a local variable with the name 'arguments', per ECMA-262.
* Instead, 'var arguments' always restates that predefined binding of the
* lexical environment for function activations. Assignments to arguments
* must be handled specially -- see NoteLValue.
*/
if (name == cx->runtime->atomState.argumentsAtom) {
pn->pn_op = JSOP_ARGUMENTS;
pn->pn_dflags |= PND_BOUND;
@ -3848,12 +3844,9 @@ BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, JSParseNod
*/
kind = (data->op == JSOP_DEFCONST) ? CONSTANT : VARIABLE;
uintN index = tc->bindings.countVars();
if (!BindLocalVariable(cx, tc, name, kind, false))
if (!BindLocalVariable(cx, tc, pn, kind))
return false;
pn->pn_op = JSOP_GETLOCAL;
pn->pn_cookie.set(tc->staticLevel, index);
pn->pn_dflags |= PND_BOUND;
return true;
}
@ -4012,9 +4005,9 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
pn->pn_dflags |= PND_CONST;
if (tc->inFunction())
return BindFunctionLocal(cx, data, mdl, pn, atom, tc);
return BindFunctionLocal(cx, data, mdl, tc);
return BindTopLevelVar(cx, data, pn, atom, tc);
return BindTopLevelVar(cx, data, pn, tc);
}
static bool
@ -6917,8 +6910,7 @@ CompExprTransplanter::transplant(JSParseNode *pn)
* generator) a use of a new placeholder in the generator's
* lexdeps.
*/
AtomDefnAddPtr p = tc->lexdeps->lookupForAdd(atom);
JSDefinition *dn2 = MakePlaceholder(p, pn, tc);
JSDefinition *dn2 = MakePlaceholder(pn, tc);
if (!dn2)
return false;
dn2->pn_pos = root->pn_pos;
@ -6937,6 +6929,8 @@ CompExprTransplanter::transplant(JSParseNode *pn)
dn2->dn_uses = dn->dn_uses;
dn->dn_uses = *pnup;
*pnup = NULL;
if (!tc->lexdeps->put(atom, dn2))
return false;
} else if (dn->isPlaceholder()) {
/*
* The variable first occurs free in the 'yield' expression;
@ -7101,8 +7095,9 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp,
if (isGenexp) {
if (!guard.checkValidBody(pn2))
return NULL;
} else if (!guard.maybeNoteGenerator()) {
return NULL;
} else {
if (!guard.maybeNoteGenerator())
return NULL;
}
switch (tt) {
@ -8761,8 +8756,8 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
* - Be left as a free variable definition if we never
* see the real definition.
*/
dn = MakePlaceholder(p, pn, tc);
if (!dn)
dn = MakePlaceholder(pn, tc);
if (!dn || !tc->lexdeps->add(p, dn->pn_atom, dn))
return NULL;
/*

View File

@ -155,6 +155,7 @@ class TokenStream;
struct Token;
struct TokenPos;
struct TokenPtr;
class UpvarCookie;
class TempAllocPolicy;
@ -192,9 +193,10 @@ class Bindings;
class MultiDeclRange;
class ParseMapPool;
class DefnOrHeader;
typedef js::InlineMap<JSAtom *, JSDefinition *, 24> AtomDefnMap;
typedef js::InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
typedef js::InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
typedef InlineMap<JSAtom *, JSDefinition *, 24> AtomDefnMap;
typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
typedef InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
typedef Vector<UpvarCookie> UpvarCookies;
} /* namespace js */

View File

@ -636,6 +636,7 @@ struct EmptyShape : public js::Shape
static inline EmptyShape *getEmptyArgumentsShape(JSContext *cx);
static inline EmptyShape *getEmptyBlockShape(JSContext *cx);
static inline EmptyShape *getEmptyCallShape(JSContext *cx);
static inline EmptyShape *getEmptyDeclEnvShape(JSContext *cx);
static inline EmptyShape *getEmptyEnumeratorShape(JSContext *cx);
static inline EmptyShape *getEmptyWithShape(JSContext *cx);

View File

@ -364,6 +364,12 @@ EmptyShape::getEmptyBlockShape(JSContext *cx)
return ensure(cx, &js_BlockClass, &cx->compartment->emptyBlockShape);
}
/* static */ inline EmptyShape *
EmptyShape::getEmptyCallShape(JSContext *cx)
{
return ensure(cx, &js_CallClass, &cx->compartment->emptyCallShape);
}
/* static */ inline EmptyShape *
EmptyShape::getEmptyDeclEnvShape(JSContext *cx)
{

View File

@ -1312,12 +1312,11 @@ JSScript::NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
script->hasSingletons = true;
if (cg->hasUpvarIndices()) {
JS_ASSERT(cg->upvarIndices->count() <= cg->upvarMap.length);
memcpy(script->upvars()->vector, cg->upvarMap.vector,
cg->upvarIndices->count() * sizeof(uint32));
JS_ASSERT(cg->upvarIndices->count() <= cg->upvarMap.length());
memcpy(script->upvars()->vector, cg->upvarMap.begin(),
cg->upvarIndices->count() * sizeof(cg->upvarMap[0]));
cg->upvarIndices->clear();
cx->free_(cg->upvarMap.vector);
cg->upvarMap.vector = NULL;
cg->upvarMap.clear();
}
/* Set global for compileAndGo scripts. */

View File

@ -50,6 +50,8 @@
#include "jsscope.h"
#include "vm/GlobalObject.h"
#include "jsscopeinlines.h"
namespace js {
inline
@ -102,7 +104,7 @@ bool
Bindings::ensureShape(JSContext *cx)
{
if (!lastBinding) {
lastBinding = EmptyShape::create(cx, &js_CallClass);
lastBinding = EmptyShape::getEmptyCallShape(cx);
if (!lastBinding)
return false;
}

View File

@ -646,7 +646,18 @@ class SetPropCompiler : public PICStubCompiler
shape->setterOp() != SetCallVar) {
return disable("setter");
}
JS_ASSERT(obj->isCall());
if (pic.typeMonitored) {
/*
* Update the types of the locals/args in the script according
* to the possible RHS types of the assignment. Note that the
* shape guards we have performed do not by themselves
* guarantee that future call objects hit will be for the same
* script. We also depend on the fact that the scope chains hit
* at the same bytecode are all isomorphic: the same scripts,
* in the same order (though the properties on their call
* objects may differ due to eval(), DEFFUN, etc.).
*/
RecompilationMonitor monitor(cx);
JSScript *script = obj->getCallObjCalleeFunction()->script();
uint16 slot = uint16(shape->shortid);

View File

@ -6,5 +6,8 @@ script empty-lookahead.js
script exec.js
script exec-lastIndex-ToInteger.js
script regress-576828.js
script regress-613820-1.js
script regress-613820-2.js
script regress-613820-3.js
silentfail skip-if(!xulRuntime.shell&&(Android||xulRuntime.OS=="WINNT")) script regress-617935.js
script instance-property-storage-introspection.js

View File

@ -0,0 +1,9 @@
/* Back reference is actually a forwards reference. */
var re = /(\2(a)){2}/;
var str = 'aaa';
var actual = re.exec(str);
var expected = makeExpectedMatch(['aa', 'a', 'a'], 0, str);
checkRegExpMatch(actual, expected);
if (typeof reportCompare === 'function')
reportCompare(true, true);

View File

@ -0,0 +1,9 @@
/* Resetting of inner capture groups across quantified capturing parens. */
var re = /(?:(f)(o)(o)|(b)(a)(r))*/;
var str = 'foobar';
var actual = re.exec(str);
var expected = makeExpectedMatch(['foobar', undefined, undefined, undefined, 'b', 'a', 'r'], 0, str);
checkRegExpMatch(actual, expected);
if (typeof reportCompare === 'function')
reportCompare(true, true);

View File

@ -0,0 +1,9 @@
/* Capture group reset to undefined during second iteration, so backreference doesn't see prior result. */
var re = /(?:^(a)|\1(a)|(ab)){2}/;
var str = 'aab';
var actual = re.exec(str);
var expected = makeExpectedMatch(['aa', undefined, 'a', undefined], 0, str);
checkRegExpMatch(actual, expected);
if (typeof reportCompare === 'function')
reportCompare(true, true);

View File

@ -44,5 +44,6 @@ skip-if(!xulRuntime.shell) script regress-636818.js
script regress-636697.js
script is-generator.js
script weakmap.js
script regress-650753.js
script regress-645160.js
script regress-650753.js
script regress-668438.js

View File

@ -0,0 +1,12 @@
// -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
// Don't assert trying to parse this.
let(x = (x(( function() {
return { e: function() { e in x } };
}))
for (x in [])))
true;
reportCompare(true, true);

View File

@ -1348,6 +1348,7 @@ private:
PRInt64 tjitDataAllocatorsMain;
PRInt64 tjitDataAllocatorsReserve;
#endif
JSCompartment::TypeInferenceMemoryStats typeInferenceMemory;
};
struct IterateData
@ -1428,6 +1429,13 @@ private:
: 0;
}
static void
GetCompartmentTypeInferenceMemorySize(JSCompartment *c,
JSCompartment::TypeInferenceMemoryStats *stats)
{
c->getTypeInferenceMemoryStats(stats);
}
#endif // JS_TRACER
static void
@ -1451,6 +1459,7 @@ private:
curr->tjitDataAllocatorsMain = GetCompartmentTjitDataAllocatorsMainSize(compartment);
curr->tjitDataAllocatorsReserve = GetCompartmentTjitDataAllocatorsReserveSize(compartment);
#endif
GetCompartmentTypeInferenceMemorySize(compartment, &curr->typeInferenceMemory);
}
static void
@ -1638,6 +1647,34 @@ public:
"Memory used by the trace JIT and held in reserve for VMAllocators "
"in case of OOM.");
#endif
DO(mkPath(name, "type-inference/script-main"),
nsIMemoryReporter::KIND_HEAP, stats->typeInferenceMemory.scriptMain,
"Memory used during type inference to store type sets of variables "
"and dynamically observed types.");
DO(mkPath(name, "type-inference/script-typesets"),
nsIMemoryReporter::KIND_HEAP, stats->typeInferenceMemory.scriptSets,
"Memory used during type inference to hold the contents of type "
"sets associated with scripts.");
DO(mkPath(name, "type-inference/object-main"),
nsIMemoryReporter::KIND_HEAP, stats->typeInferenceMemory.objectMain,
"Memory used during type inference to store types and possible "
"property types of JS objects.");
DO(mkPath(name, "type-inference/object-typesets"),
nsIMemoryReporter::KIND_HEAP, stats->typeInferenceMemory.objectSets,
"Memory used during type inference to hold the contents of type "
"sets associated with objects.");
/*
* This is in a different category from the rest of type inference
* data as this can be large but is volatile and cleared on GC.
*/
DO(mkPath(name, "type-inference-pools"),
nsIMemoryReporter::KIND_HEAP, stats->typeInferenceMemory.poolMain,
"Memory used during type inference to hold transient analysis information.");
}
JS_ASSERT(gcHeapChunkTotal % js::GC_CHUNK_SIZE == 0);