Bug 750606 - Remove TreeContext::parser, thus avoiding cycles between TreeContext and Parser objects. r=bhackett.

This commit is contained in:
Nicholas Nethercote 2012-04-30 22:20:06 -07:00
parent c3b189cb76
commit a1c382cf15
14 changed files with 439 additions and 424 deletions

View File

@ -227,10 +227,10 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
if (inDirectivePrologue && !parser.recognizeDirectivePrologue(pn, &inDirectivePrologue))
goto out;
if (!FoldConstants(cx, pn, &bce))
if (!FoldConstants(cx, pn, bce.parser))
goto out;
if (!AnalyzeFunctions(&bce))
if (!AnalyzeFunctions(bce.parser))
goto out;
bce.functionList = NULL;
@ -241,7 +241,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
if (!pn->isKind(PNK_SEMI) || !pn->pn_kid || !pn->pn_kid->isXMLItem())
onlyXML = false;
#endif
bce.freeTree(pn);
bce.parser->freeTree(pn);
}
#if JS_HAS_XML_SUPPORT
@ -308,7 +308,7 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
return false;
/* FIXME: make Function format the source for a function definition. */
ParseNode *fn = FunctionNode::create(PNK_NAME, &funbce);
ParseNode *fn = FunctionNode::create(PNK_NAME, funbce.parser);
if (fn) {
fn->pn_body = NULL;
fn->pn_cookie.makeFree();
@ -324,7 +324,7 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
fn = NULL;
} else {
for (unsigned i = 0; i < nargs; i++) {
if (!DefineArg(fn, names[i].maybeAtom, i, &funbce)) {
if (!DefineArg(fn, names[i].maybeAtom, i, funbce.parser)) {
fn = NULL;
break;
}
@ -343,10 +343,10 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
if (!tokenStream.matchToken(TOK_EOF)) {
parser.reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_SYNTAX_ERROR);
pn = NULL;
} else if (!FoldConstants(cx, pn, &funbce)) {
} else if (!FoldConstants(cx, pn, funbce.parser)) {
/* FoldConstants reported the error already. */
pn = NULL;
} else if (!AnalyzeFunctions(&funbce)) {
} else if (!AnalyzeFunctions(funbce.parser)) {
pn = NULL;
} else {
if (fn->pn_body) {

View File

@ -100,6 +100,7 @@ SetSrcNoteOffset(JSContext *cx, BytecodeEmitter *bce, unsigned index, unsigned w
BytecodeEmitter::BytecodeEmitter(Parser *parser, unsigned lineno)
: TreeContext(parser),
parser(parser),
atomIndices(parser->context),
stackDepth(0), maxStackDepth(0),
ntrynotes(0), lastTryNode(NULL),
@ -1932,14 +1933,14 @@ EmitElemOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
*/
left = pn->maybeExpr();
if (!left) {
left = NullaryNode::create(PNK_STRING, bce);
left = NullaryNode::create(PNK_STRING, bce->parser);
if (!left)
return false;
left->setOp(JSOP_BINDNAME);
left->pn_pos = pn->pn_pos;
left->pn_atom = pn->pn_atom;
}
right = NullaryNode::create(PNK_STRING, bce);
right = NullaryNode::create(PNK_STRING, bce->parser);
if (!right)
return false;
right->setOp(IsIdentifier(pn->pn_atom) ? JSOP_QNAMEPART : JSOP_STRING);

View File

@ -116,6 +116,8 @@ struct BytecodeEmitter : public TreeContext
unsigned currentLine; /* line number for tree-based srcnote gen */
} prolog, main, *current;
Parser *parser; /* the parser */
OwnedAtomIndexMapPtr atomIndices; /* literals indexed for mapping */
AtomDefnMapPtr roLexdeps;
unsigned firstLine; /* first line, for JSScript::NewScriptFromEmitter */
@ -151,10 +153,6 @@ struct BytecodeEmitter : public TreeContext
BytecodeEmitter(Parser *parser, unsigned lineno);
bool init(JSContext *cx, TreeContext::InitBehavior ib = USED_AS_CODE_GENERATOR);
JSContext *context() {
return parser->context;
}
// This is a down-cast. It's necessary and safe -- although
// TreeContext::parent is a |TreeContext *|, a BytecodeEmitter's parent is
// always itself a BytecodeEmitter.

View File

@ -147,7 +147,7 @@ FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
*/
static JSBool
FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
ParseNode *pn, TreeContext *tc)
ParseNode *pn, Parser *parser)
{
double d, d2;
int32_t i, j;
@ -214,9 +214,9 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
/* Take care to allow pn1 or pn2 to alias pn. */
if (pn1 != pn)
tc->freeTree(pn1);
parser->freeTree(pn1);
if (pn2 != pn)
tc->freeTree(pn2);
parser->freeTree(pn2);
pn->setKind(PNK_NUMBER);
pn->setOp(JSOP_DOUBLE);
pn->setArity(PN_NULLARY);
@ -227,7 +227,7 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
#if JS_HAS_XML_SUPPORT
static JSBool
FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
{
JS_ASSERT(pn->isArity(PN_LIST));
ParseNodeKind kind = pn->getKind();
@ -303,7 +303,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
#endif
} else if (accum && pn1 != pn2) {
while (pn1->pn_next != pn2) {
pn1 = tc->freeTree(pn1);
pn1 = parser->freeTree(pn1);
--pn->pn_count;
}
pn1->setKind(PNK_XMLTEXT);
@ -355,7 +355,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
JS_ASSERT(*pnp == pn1);
while (pn1->pn_next) {
pn1 = tc->freeTree(pn1);
pn1 = parser->freeTree(pn1);
--pn->pn_count;
}
pn1->setKind(PNK_XMLTEXT);
@ -434,7 +434,7 @@ Boolish(ParseNode *pn)
}
bool
js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
js::FoldConstants(JSContext *cx, ParseNode *pn, Parser *parser, bool inCond)
{
ParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL;
@ -443,12 +443,13 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
switch (pn->getArity()) {
case PN_FUNC:
{
TreeContext *tc = parser->tc;
uint32_t oldflags = tc->flags;
FunctionBox *oldlist = tc->functionList;
tc->flags = pn->pn_funbox->tcflags;
tc->functionList = pn->pn_funbox->kids;
if (!FoldConstants(cx, pn->pn_body, tc))
if (!FoldConstants(cx, pn->pn_body, parser))
return false;
pn->pn_funbox->kids = tc->functionList;
tc->flags = oldflags;
@ -468,7 +469,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
/* Save the list head in pn1 for later use. */
for (; pn2; pn2 = pn2->pn_next) {
if (!FoldConstants(cx, pn2, tc, cond))
if (!FoldConstants(cx, pn2, parser, cond))
return false;
}
break;
@ -479,17 +480,17 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn1 = pn->pn_kid1;
pn2 = pn->pn_kid2;
pn3 = pn->pn_kid3;
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(PNK_IF)))
if (pn1 && !FoldConstants(cx, pn1, parser, pn->isKind(PNK_IF)))
return false;
if (pn2) {
if (!FoldConstants(cx, pn2, tc, pn->isKind(PNK_FORHEAD)))
if (!FoldConstants(cx, pn2, parser, pn->isKind(PNK_FORHEAD)))
return false;
if (pn->isKind(PNK_FORHEAD) && pn2->isOp(JSOP_TRUE)) {
tc->freeTree(pn2);
parser->freeTree(pn2);
pn->pn_kid2 = NULL;
}
}
if (pn3 && !FoldConstants(cx, pn3, tc))
if (pn3 && !FoldConstants(cx, pn3, parser))
return false;
break;
@ -499,17 +500,17 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
/* Propagate inCond through logical connectives. */
if (pn->isKind(PNK_OR) || pn->isKind(PNK_AND)) {
if (!FoldConstants(cx, pn1, tc, inCond))
if (!FoldConstants(cx, pn1, parser, inCond))
return false;
if (!FoldConstants(cx, pn2, tc, inCond))
if (!FoldConstants(cx, pn2, parser, inCond))
return false;
break;
}
/* First kid may be null (for default case in switch). */
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(PNK_WHILE)))
if (pn1 && !FoldConstants(cx, pn1, parser, pn->isKind(PNK_WHILE)))
return false;
if (!FoldConstants(cx, pn2, tc, pn->isKind(PNK_DOWHILE)))
if (!FoldConstants(cx, pn2, parser, pn->isKind(PNK_DOWHILE)))
return false;
break;
@ -528,7 +529,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
if (pn->isOp(JSOP_TYPEOF) && !pn1->isKind(PNK_NAME))
pn->setOp(JSOP_TYPEOFEXPR);
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isOp(JSOP_NOT)))
if (pn1 && !FoldConstants(cx, pn1, parser, pn->isOp(JSOP_NOT)))
return false;
break;
@ -543,14 +544,14 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn1 = pn->pn_expr;
while (pn1 && pn1->isArity(PN_NAME) && !pn1->isUsed())
pn1 = pn1->pn_expr;
if (pn1 && !FoldConstants(cx, pn1, tc))
if (pn1 && !FoldConstants(cx, pn1, parser))
return false;
}
break;
case PN_NAMESET:
pn1 = pn->pn_tree;
if (!FoldConstants(cx, pn1, tc))
if (!FoldConstants(cx, pn1, parser))
return false;
break;
@ -588,7 +589,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
#if JS_HAS_GENERATOR_EXPRS
/* Don't fold a trailing |if (0)| in a generator expression. */
if (!pn2 && (tc->flags & TCF_GENEXP_LAMBDA))
if (!pn2 && (parser->tc->flags & TCF_GENEXP_LAMBDA))
break;
#endif
@ -606,9 +607,9 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn->setArity(PN_LIST);
pn->makeEmpty();
}
tc->freeTree(pn2);
parser->freeTree(pn2);
if (pn3 && pn3 != pn2)
tc->freeTree(pn3);
parser->freeTree(pn3);
break;
case PNK_OR:
@ -626,7 +627,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
if ((t == Truthy) == pn->isKind(PNK_OR)) {
for (pn2 = pn1->pn_next; pn2; pn2 = pn3) {
pn3 = pn2->pn_next;
tc->freeTree(pn2);
parser->freeTree(pn2);
--pn->pn_count;
}
pn1->pn_next = NULL;
@ -636,7 +637,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
if (pn->pn_count == 1)
break;
*pnp = pn1->pn_next;
tc->freeTree(pn1);
parser->freeTree(pn1);
--pn->pn_count;
} while ((pn1 = *pnp) != NULL);
@ -651,17 +652,17 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn->pn_right = pn2;
} else if (pn->pn_count == 1) {
pn->become(pn1);
tc->freeTree(pn1);
parser->freeTree(pn1);
}
} else {
Truthiness t = Boolish(pn1);
if (t != Unknown) {
if ((t == Truthy) == pn->isKind(PNK_OR)) {
tc->freeTree(pn2);
parser->freeTree(pn2);
pn->become(pn1);
} else {
JS_ASSERT((t == Truthy) == pn->isKind(PNK_AND));
tc->freeTree(pn1);
parser->freeTree(pn1);
pn->become(pn2);
}
}
@ -727,7 +728,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
}
/* Fill the buffer, advancing chars and recycling kids as we go. */
for (pn2 = pn1; pn2; pn2 = tc->freeTree(pn2)) {
for (pn2 = pn1; pn2; pn2 = parser->freeTree(pn2)) {
JSAtom *atom = pn2->pn_atom;
size_t length2 = atom->length();
js_strncpy(chars, atom->chars(), length2);
@ -763,8 +764,8 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn->setKind(PNK_STRING);
pn->setOp(JSOP_STRING);
pn->setArity(PN_NULLARY);
tc->freeTree(pn1);
tc->freeTree(pn2);
parser->freeTree(pn1);
parser->freeTree(pn2);
break;
}
@ -795,11 +796,11 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn2 = pn1->pn_next;
pn3 = pn2->pn_next;
if (!FoldBinaryNumeric(cx, op, pn1, pn2, pn, tc))
if (!FoldBinaryNumeric(cx, op, pn1, pn2, pn, parser))
return false;
while ((pn2 = pn3) != NULL) {
pn3 = pn2->pn_next;
if (!FoldBinaryNumeric(cx, op, pn, pn2, pn, tc))
if (!FoldBinaryNumeric(cx, op, pn, pn2, pn, parser))
return false;
}
}
@ -810,7 +811,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
return false;
}
if (pn1->isKind(PNK_NUMBER) && pn2->isKind(PNK_NUMBER)) {
if (!FoldBinaryNumeric(cx, pn->getOp(), pn1, pn2, pn, tc))
if (!FoldBinaryNumeric(cx, pn->getOp(), pn1, pn2, pn, parser))
return false;
}
}
@ -858,7 +859,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn->setOp(JSOP_DOUBLE);
pn->setArity(PN_NULLARY);
pn->pn_dval = d;
tc->freeTree(pn1);
parser->freeTree(pn1);
} else if (pn1->isKind(PNK_TRUE) || pn1->isKind(PNK_FALSE)) {
if (pn->isOp(JSOP_NOT)) {
pn->become(pn1);
@ -869,7 +870,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn->setKind(PNK_TRUE);
pn->setOp(JSOP_TRUE);
}
tc->freeTree(pn1);
parser->freeTree(pn1);
}
}
break;
@ -883,7 +884,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
case PNK_XMLNAME:
if (pn->isArity(PN_LIST)) {
JS_ASSERT(pn->isKind(PNK_XMLLIST) || pn->pn_count != 0);
if (!FoldXMLConstants(cx, pn, tc))
if (!FoldXMLConstants(cx, pn, parser))
return false;
}
break;
@ -895,7 +896,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
return false;
JS_ASSERT(v.isObject());
ObjectBox *xmlbox = tc->parser->newObjectBox(&v.toObject());
ObjectBox *xmlbox = parser->newObjectBox(&v.toObject());
if (!xmlbox)
return false;
@ -903,7 +904,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
pn->setOp(JSOP_OBJECT);
pn->setArity(PN_NULLARY);
pn->pn_objbox = xmlbox;
tc->freeTree(pn1);
parser->freeTree(pn1);
}
break;
#endif /* JS_HAS_XML_SUPPORT */
@ -920,7 +921,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
* a method list corrupts the method list. However, methods are M's in
* statements of the form 'this.foo = M;', which we never fold, so we're okay.
*/
tc->parser->allocator.prepareNodeForMutation(pn);
parser->allocator.prepareNodeForMutation(pn);
if (t == Truthy) {
pn->setKind(PNK_TRUE);
pn->setOp(JSOP_TRUE);

View File

@ -46,7 +46,7 @@
namespace js {
bool
FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond = false);
FoldConstants(JSContext *cx, ParseNode *pn, Parser *parser, bool inCond = false);
} /* namespace js */

View File

@ -361,9 +361,8 @@ ParseNodeAllocator::allocNode()
/* used only by static create methods of subclasses */
ParseNode *
ParseNode::create(ParseNodeKind kind, ParseNodeArity arity, TreeContext *tc)
ParseNode::create(ParseNodeKind kind, ParseNodeArity arity, Parser *parser)
{
Parser *parser = tc->parser;
const Token &tok = parser->tokenStream.currentToken();
return parser->new_<ParseNode>(kind, JSOP_NOP, arity, tok.pos);
}
@ -407,7 +406,7 @@ ParseNode::append(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right
ParseNode *
ParseNode::newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right,
TreeContext *tc)
Parser *parser)
{
if (!left || !right)
return NULL;
@ -429,21 +428,24 @@ ParseNode::newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, Parse
if (kind == PNK_ADD &&
left->isKind(PNK_NUMBER) &&
right->isKind(PNK_NUMBER) &&
tc->parser->foldConstants)
parser->foldConstants)
{
left->pn_dval += right->pn_dval;
left->pn_pos.end = right->pn_pos.end;
tc->freeTree(right);
parser->freeTree(right);
return left;
}
return tc->parser->new_<BinaryNode>(kind, op, left, right);
return parser->new_<BinaryNode>(kind, op, left, right);
}
// Nb: unlike most functions that are passed a Parser, this one gets a
// TreeContext passed in separately, because in this case |tc| may not equal
// |parser->tc|.
NameNode *
NameNode::create(ParseNodeKind kind, JSAtom *atom, TreeContext *tc)
NameNode::create(ParseNodeKind kind, JSAtom *atom, Parser *parser, TreeContext *tc)
{
ParseNode *pn = ParseNode::create(kind, PN_NAME, tc);
ParseNode *pn = ParseNode::create(kind, PN_NAME, parser);
if (pn) {
pn->pn_atom = atom;
((NameNode *)pn)->initCommon(tc);
@ -474,12 +476,14 @@ Definition::kindString(Kind kind)
* binding context as the original tree.
*/
static ParseNode *
CloneParseTree(ParseNode *opn, TreeContext *tc)
CloneParseTree(ParseNode *opn, Parser *parser)
{
JS_CHECK_RECURSION(tc->parser->context, return NULL);
TreeContext *tc = parser->tc;
ParseNode *pn = tc->parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
JS_CHECK_RECURSION(tc->context, return NULL);
ParseNode *pn = parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
if (!pn)
return NULL;
pn->setInParens(opn->isInParens());
@ -491,8 +495,8 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
case PN_FUNC:
NULLCHECK(pn->pn_funbox =
tc->parser->newFunctionBox(opn->pn_funbox->object, pn, tc));
NULLCHECK(pn->pn_body = CloneParseTree(opn->pn_body, tc));
parser->newFunctionBox(opn->pn_funbox->object, pn, tc));
NULLCHECK(pn->pn_body = CloneParseTree(opn->pn_body, parser));
pn->pn_cookie = opn->pn_cookie;
pn->pn_dflags = opn->pn_dflags;
pn->pn_blockid = opn->pn_blockid;
@ -502,22 +506,22 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
pn->makeEmpty();
for (ParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) {
ParseNode *pn2;
NULLCHECK(pn2 = CloneParseTree(opn2, tc));
NULLCHECK(pn2 = CloneParseTree(opn2, parser));
pn->append(pn2);
}
pn->pn_xflags = opn->pn_xflags;
break;
case PN_TERNARY:
NULLCHECK(pn->pn_kid1 = CloneParseTree(opn->pn_kid1, tc));
NULLCHECK(pn->pn_kid2 = CloneParseTree(opn->pn_kid2, tc));
NULLCHECK(pn->pn_kid3 = CloneParseTree(opn->pn_kid3, tc));
NULLCHECK(pn->pn_kid1 = CloneParseTree(opn->pn_kid1, parser));
NULLCHECK(pn->pn_kid2 = CloneParseTree(opn->pn_kid2, parser));
NULLCHECK(pn->pn_kid3 = CloneParseTree(opn->pn_kid3, parser));
break;
case PN_BINARY:
NULLCHECK(pn->pn_left = CloneParseTree(opn->pn_left, tc));
NULLCHECK(pn->pn_left = CloneParseTree(opn->pn_left, parser));
if (opn->pn_right != opn->pn_left)
NULLCHECK(pn->pn_right = CloneParseTree(opn->pn_right, tc));
NULLCHECK(pn->pn_right = CloneParseTree(opn->pn_right, parser));
else
pn->pn_right = pn->pn_left;
pn->pn_pval = opn->pn_pval;
@ -525,7 +529,7 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
break;
case PN_UNARY:
NULLCHECK(pn->pn_kid = CloneParseTree(opn->pn_kid, tc));
NULLCHECK(pn->pn_kid = CloneParseTree(opn->pn_kid, parser));
pn->pn_hidden = opn->pn_hidden;
break;
@ -542,7 +546,7 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
pn->pn_link = dn->dn_uses;
dn->dn_uses = pn;
} else if (opn->pn_expr) {
NULLCHECK(pn->pn_expr = CloneParseTree(opn->pn_expr, tc));
NULLCHECK(pn->pn_expr = CloneParseTree(opn->pn_expr, parser));
/*
* If the old name is a definition, the new one has pn_defn set.
@ -550,14 +554,14 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
*/
if (opn->isDefn()) {
opn->setDefn(false);
LinkUseToDef(opn, (Definition *) pn, tc);
LinkUseToDef(opn, (Definition *) pn);
}
}
break;
case PN_NAMESET:
pn->pn_names = opn->pn_names;
NULLCHECK(pn->pn_tree = CloneParseTree(opn->pn_tree, tc));
NULLCHECK(pn->pn_tree = CloneParseTree(opn->pn_tree, parser));
break;
case PN_NULLARY:
@ -583,10 +587,10 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
* the original tree.
*/
ParseNode *
js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
js::CloneLeftHandSide(ParseNode *opn, Parser *parser)
{
ParseNode *pn = tc->parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
ParseNode *pn = parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
if (!pn)
return NULL;
pn->setInParens(opn->isInParens());
@ -603,19 +607,19 @@ js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
JS_ASSERT(opn2->isArity(PN_BINARY));
JS_ASSERT(opn2->isKind(PNK_COLON));
ParseNode *tag = CloneParseTree(opn2->pn_left, tc);
ParseNode *tag = CloneParseTree(opn2->pn_left, parser);
if (!tag)
return NULL;
ParseNode *target = CloneLeftHandSide(opn2->pn_right, tc);
ParseNode *target = CloneLeftHandSide(opn2->pn_right, parser);
if (!target)
return NULL;
pn2 = tc->parser->new_<BinaryNode>(PNK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target);
pn2 = parser->new_<BinaryNode>(PNK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target);
} else if (opn2->isArity(PN_NULLARY)) {
JS_ASSERT(opn2->isKind(PNK_COMMA));
pn2 = CloneParseTree(opn2, tc);
pn2 = CloneParseTree(opn2, parser);
} else {
pn2 = CloneLeftHandSide(opn2, tc);
pn2 = CloneLeftHandSide(opn2, parser);
}
if (!pn2)
@ -646,7 +650,7 @@ js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
pn->pn_dflags &= ~PND_BOUND;
pn->setDefn(false);
LinkUseToDef(pn, (Definition *) opn, tc);
LinkUseToDef(pn, (Definition *) opn);
}
}
return pn;

View File

@ -713,7 +713,7 @@ struct ParseNode {
pn_next = pn_link = NULL;
}
static ParseNode *create(ParseNodeKind kind, ParseNodeArity arity, TreeContext *tc);
static ParseNode *create(ParseNodeKind kind, ParseNodeArity arity, Parser *parser);
public:
/*
@ -730,7 +730,7 @@ struct ParseNode {
*/
static ParseNode *
newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right,
TreeContext *tc);
Parser *parser);
inline PropertyName *atom() const;
@ -975,8 +975,8 @@ struct ParseNode {
};
struct NullaryNode : public ParseNode {
static inline NullaryNode *create(ParseNodeKind kind, TreeContext *tc) {
return (NullaryNode *)ParseNode::create(kind, PN_NULLARY, tc);
static inline NullaryNode *create(ParseNodeKind kind, Parser *parser) {
return (NullaryNode *)ParseNode::create(kind, PN_NULLARY, parser);
}
#ifdef DEBUG
@ -991,8 +991,8 @@ struct UnaryNode : public ParseNode {
pn_kid = kid;
}
static inline UnaryNode *create(ParseNodeKind kind, TreeContext *tc) {
return (UnaryNode *)ParseNode::create(kind, PN_UNARY, tc);
static inline UnaryNode *create(ParseNodeKind kind, Parser *parser) {
return (UnaryNode *)ParseNode::create(kind, PN_UNARY, parser);
}
#ifdef DEBUG
@ -1015,8 +1015,8 @@ struct BinaryNode : public ParseNode {
pn_right = right;
}
static inline BinaryNode *create(ParseNodeKind kind, TreeContext *tc) {
return (BinaryNode *)ParseNode::create(kind, PN_BINARY, tc);
static inline BinaryNode *create(ParseNodeKind kind, Parser *parser) {
return (BinaryNode *)ParseNode::create(kind, PN_BINARY, parser);
}
#ifdef DEBUG
@ -1035,8 +1035,8 @@ struct TernaryNode : public ParseNode {
pn_kid3 = kid3;
}
static inline TernaryNode *create(ParseNodeKind kind, TreeContext *tc) {
return (TernaryNode *)ParseNode::create(kind, PN_TERNARY, tc);
static inline TernaryNode *create(ParseNodeKind kind, Parser *parser) {
return (TernaryNode *)ParseNode::create(kind, PN_TERNARY, parser);
}
#ifdef DEBUG
@ -1045,8 +1045,8 @@ struct TernaryNode : public ParseNode {
};
struct ListNode : public ParseNode {
static inline ListNode *create(ParseNodeKind kind, TreeContext *tc) {
return (ListNode *)ParseNode::create(kind, PN_LIST, tc);
static inline ListNode *create(ParseNodeKind kind, Parser *parser) {
return (ListNode *)ParseNode::create(kind, PN_LIST, parser);
}
#ifdef DEBUG
@ -1055,8 +1055,8 @@ struct ListNode : public ParseNode {
};
struct FunctionNode : public ParseNode {
static inline FunctionNode *create(ParseNodeKind kind, TreeContext *tc) {
return (FunctionNode *)ParseNode::create(kind, PN_FUNC, tc);
static inline FunctionNode *create(ParseNodeKind kind, Parser *parser) {
return (FunctionNode *)ParseNode::create(kind, PN_FUNC, parser);
}
#ifdef DEBUG
@ -1065,7 +1065,7 @@ struct FunctionNode : public ParseNode {
};
struct NameNode : public ParseNode {
static NameNode *create(ParseNodeKind kind, JSAtom *atom, TreeContext *tc);
static NameNode *create(ParseNodeKind kind, JSAtom *atom, Parser *parser, TreeContext *tc);
inline void initCommon(TreeContext *tc);
@ -1075,14 +1075,14 @@ struct NameNode : public ParseNode {
};
struct NameSetNode : public ParseNode {
static inline NameSetNode *create(ParseNodeKind kind, TreeContext *tc) {
return (NameSetNode *)ParseNode::create(kind, PN_NAMESET, tc);
static inline NameSetNode *create(ParseNodeKind kind, Parser *parser) {
return (NameSetNode *)ParseNode::create(kind, PN_NAMESET, parser);
}
};
struct LexicalScopeNode : public ParseNode {
static inline LexicalScopeNode *create(ParseNodeKind kind, TreeContext *tc) {
return (LexicalScopeNode *)ParseNode::create(kind, PN_NAME, tc);
static inline LexicalScopeNode *create(ParseNodeKind kind, Parser *parser) {
return (LexicalScopeNode *)ParseNode::create(kind, PN_NAME, parser);
}
};
@ -1323,7 +1323,7 @@ class PropertyByValue : public ParseNode {
};
ParseNode *
CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
CloneLeftHandSide(ParseNode *opn, Parser *parser);
#ifdef DEBUG
void DumpParseTree(ParseNode *pn, int indent = 0);
@ -1511,7 +1511,7 @@ ParseNode::resolve()
}
inline void
LinkUseToDef(ParseNode *pn, Definition *dn, TreeContext *tc)
LinkUseToDef(ParseNode *pn, Definition *dn)
{
JS_ASSERT(!pn->isUsed());
JS_ASSERT(!pn->isDefn());

File diff suppressed because it is too large Load Diff

View File

@ -242,7 +242,7 @@ struct Parser : private AutoGCRooter
* Additional JS parsers.
*/
enum FunctionType { Getter, Setter, Normal };
bool functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **list);
bool functionArguments(ParseNode **list);
ParseNode *functionDef(HandlePropertyName name, FunctionType type, FunctionSyntaxKind kind);
@ -295,7 +295,7 @@ Parser::reportErrorNumber(ParseNode *pn, unsigned flags, unsigned errorNumber, .
}
bool
DefineArg(ParseNode *pn, JSAtom *atom, unsigned i, TreeContext *tc);
DefineArg(ParseNode *pn, JSAtom *atom, unsigned i, Parser *parser);
} /* namespace js */

View File

@ -189,13 +189,14 @@ MarkExtensibleScopeDescendants(JSContext *context, FunctionBox *funbox, bool has
}
bool
frontend::AnalyzeFunctions(TreeContext *tc)
frontend::AnalyzeFunctions(Parser *parser)
{
TreeContext *tc = parser->tc;
if (!tc->functionList)
return true;
if (!MarkExtensibleScopeDescendants(tc->parser->context, tc->functionList, false))
if (!MarkExtensibleScopeDescendants(tc->context, tc->functionList, false))
return false;
bool isDirectEval = !!tc->parser->callerFrame;
bool isDirectEval = !!parser->callerFrame;
SetFunctionKinds(tc->functionList, &tc->flags, isDirectEval);
return true;
}

View File

@ -42,7 +42,7 @@
namespace js {
struct TreeContext;
struct Parser;
namespace frontend {
@ -52,7 +52,7 @@ namespace frontend {
* accordingly.
*/
bool
AnalyzeFunctions(TreeContext *tc);
AnalyzeFunctions(Parser *parser);
} /* namespace frontend */
} /* namespace js */

View File

@ -48,12 +48,12 @@ namespace js {
inline
TreeContext::TreeContext(Parser *prs)
: flags(0), bodyid(0), blockidGen(0), parenDepth(0), yieldCount(0),
topStmt(NULL), topScopeStmt(NULL), blockChain(prs->context), blockNode(NULL),
decls(prs->context), parser(prs), yieldNode(NULL), argumentsNode(NULL),
fun_(prs->context), scopeChain_(prs->context),
lexdeps(prs->context), parent(prs->tc), staticLevel(0), funbox(NULL), functionList(NULL),
innermostWith(NULL), bindings(prs->context), bindingsRoot(prs->context, &bindings),
: context(prs->context), flags(0), bodyid(0), blockidGen(0), parenDepth(0), yieldCount(0),
topStmt(NULL), topScopeStmt(NULL), blockChain(context), blockNode(NULL),
decls(context), yieldNode(NULL), argumentsNode(NULL), parserTC(&prs->tc),
fun_(context), scopeChain_(context),
lexdeps(context), parent(prs->tc), staticLevel(0), funbox(NULL), functionList(NULL),
innermostWith(NULL), bindings(context), bindingsRoot(context, &bindings),
funcStmts(NULL)
{
prs->tc = this;
@ -73,32 +73,29 @@ TreeContext::atBodyLevel()
inline bool
TreeContext::needStrictChecks() {
return parser->context->hasStrictOption() || inStrictMode();
return context->hasStrictOption() || inStrictMode();
}
inline unsigned
TreeContext::argumentsLocalSlot() const {
PropertyName *arguments = parser->context->runtime->atomState.argumentsAtom;
PropertyName *arguments = context->runtime->atomState.argumentsAtom;
unsigned slot;
DebugOnly<BindingKind> kind = bindings.lookup(parser->context, arguments, &slot);
DebugOnly<BindingKind> kind = bindings.lookup(context, arguments, &slot);
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
return slot;
}
inline ParseNode *
TreeContext::freeTree(ParseNode *pn)
{
return parser->freeTree(pn);
}
// For functions the tree context is constructed and destructed a second
// time during code generation. To avoid a redundant stats update in such
// cases, we store UINT16_MAX in maxScopeDepth.
inline
TreeContext::~TreeContext()
{
parser->tc = this->parent;
parser->context->delete_(funcStmts);
// |*parserTC| pointed to this object. Now that this object is about to
// die, make |*parserTC| point to this object's parent.
JS_ASSERT(*parserTC == this);
*parserTC = this->parent;
context->delete_(funcStmts);
}
} // namespace js

View File

@ -39,7 +39,6 @@
* ***** END LICENSE BLOCK ***** */
#include "frontend/ParseNode.h"
#include "frontend/Parser.h"
#include "frontend/TreeContext.h"
#include "jsatominlines.h"
@ -65,7 +64,7 @@ frontend::SetStaticLevel(TreeContext *tc, unsigned staticLevel)
* practically speaking it leaves more than enough room for upvars.
*/
if (UpvarCookie::isLevelReserved(staticLevel)) {
JS_ReportErrorNumber(tc->parser->context, js_GetErrorMessage, NULL,
JS_ReportErrorNumber(tc->context, js_GetErrorMessage, NULL,
JSMSG_TOO_DEEP, js_function_str);
return false;
}
@ -77,7 +76,7 @@ bool
frontend::GenerateBlockId(TreeContext *tc, uint32_t &blockid)
{
if (tc->blockidGen == JS_BIT(20)) {
JS_ReportErrorNumber(tc->parser->context, js_GetErrorMessage, NULL,
JS_ReportErrorNumber(tc->context, js_GetErrorMessage, NULL,
JSMSG_NEED_DIET, "program");
return false;
}
@ -142,7 +141,7 @@ frontend::LexicalLookup(TreeContext *tc, JSAtom *atom, int *slotp, StmtInfo *stm
continue;
StaticBlockObject &blockObj = *stmt->blockObj;
const Shape *shape = blockObj.nativeLookup(tc->parser->context, AtomToId(atom));
const Shape *shape = blockObj.nativeLookup(tc->context, AtomToId(atom));
if (shape) {
JS_ASSERT(shape->hasShortID());

View File

@ -209,6 +209,8 @@ struct Parser;
struct StmtInfo;
struct TreeContext { /* tree context for semantic checks */
JSContext *context;
uint32_t flags; /* statement state flags, see above */
uint32_t bodyid; /* block number of program/function body */
uint32_t blockidGen; /* preincremented block number generator */
@ -225,7 +227,6 @@ struct TreeContext { /* tree context for semantic checks */
ParseNode *blockNode; /* parse node for a block with let declarations
(block with its own lexical scope) */
AtomDecls decls; /* function, const, and var declarations */
Parser *parser; /* ptr to common parsing and lexing data */
ParseNode *yieldNode; /* parse node for a yield expression that might
be an error if we turn out to be inside a
generator expression */
@ -234,6 +235,9 @@ struct TreeContext { /* tree context for semantic checks */
inside a generator expression */
private:
TreeContext **parserTC; /* this points to the Parser's active tc
and holds either |this| or one of
|this|'s descendents */
RootedVarFunction fun_; /* function to store argument and variable
names when flags & TCF_IN_FUNCTION */
RootedVarObject scopeChain_; /* scope chain object for the script */
@ -363,8 +367,6 @@ struct TreeContext { /* tree context for semantic checks */
bool hasExtensibleScope() const {
return flags & TCF_FUN_EXTENSIBLE_SCOPE;
}
ParseNode *freeTree(ParseNode *pn);
};
/*