mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Merge TM -> JM
This commit is contained in:
commit
efef17855f
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
9
js/src/tests/ecma_5/RegExp/regress-613820-1.js
Normal file
9
js/src/tests/ecma_5/RegExp/regress-613820-1.js
Normal 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);
|
9
js/src/tests/ecma_5/RegExp/regress-613820-2.js
Normal file
9
js/src/tests/ecma_5/RegExp/regress-613820-2.js
Normal 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);
|
9
js/src/tests/ecma_5/RegExp/regress-613820-3.js
Normal file
9
js/src/tests/ecma_5/RegExp/regress-613820-3.js
Normal 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);
|
@ -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
|
||||
|
12
js/src/tests/js1_8_5/extensions/regress-668438.js
Normal file
12
js/src/tests/js1_8_5/extensions/regress-668438.js
Normal 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);
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user