Bug 568953 - Refactor FunctionNode; r=jorendorff

This commit is contained in:
Eddy Bruel 2013-02-19 23:06:14 +01:00
parent e603f6fb3e
commit 998a480f3e
8 changed files with 61 additions and 39 deletions

View File

@ -253,7 +253,7 @@ frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun, CompileOptions
fun->setArgCount(formals.length());
/* FIXME: make Function format the source for a function definition. */
ParseNode *fn = FunctionNode::create(PNK_FUNCTION, &parser);
ParseNode *fn = CodeNode::create(PNK_FUNCTION, &parser);
if (!fn)
return false;

View File

@ -1477,7 +1477,7 @@ CheckSideEffects(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool *answe
return true;
switch (pn->getArity()) {
case PN_FUNC:
case PN_CODE:
/*
* A named function, contrary to ES3, is no longer useful, because we
* bind its name lexically (using JSOP_CALLEE) instead of creating an

View File

@ -254,9 +254,15 @@ frontend::FoldConstants(JSContext *cx, ParseNode **pnp, Parser *parser, bool inG
JS_CHECK_RECURSION(cx, return false);
switch (pn->getArity()) {
case PN_FUNC:
if (!FoldConstants(cx, &pn->pn_body, parser, pn->pn_funbox->inGenexpLambda))
return false;
case PN_CODE:
if (pn->getKind() == PNK_MODULE) {
if (!FoldConstants(cx, &pn->pn_body, parser))
return false;
} else {
JS_ASSERT(pn->getKind() == PNK_FUNCTION);
if (!FoldConstants(cx, &pn->pn_body, parser, pn->pn_funbox->inGenexpLambda))
return false;
}
break;
case PN_LIST:

View File

@ -273,7 +273,7 @@ class NameResolver
if (cur == NULL)
return;
if (cur->isKind(PNK_FUNCTION) && cur->isArity(PN_FUNC)) {
if (cur->isKind(PNK_FUNCTION) && cur->isArity(PN_CODE)) {
RootedAtom prefix2(cx, resolveFun(cur, prefix));
/*
* If a function looks like (function(){})() where the parent node
@ -314,7 +314,7 @@ class NameResolver
resolve(cur->pn_kid2, prefix);
resolve(cur->pn_kid3, prefix);
break;
case PN_FUNC:
case PN_CODE:
JS_ASSERT(cur->isKind(PNK_FUNCTION));
resolve(cur->pn_body, prefix);
break;

View File

@ -36,6 +36,13 @@ ParseNode::name() const
return atom->asPropertyName();
}
inline JSAtom *
ParseNode::atom() const
{
JS_ASSERT(isKind(PNK_MODULE) || isKind(PNK_STRING));
return isKind(PNK_MODULE) ? pn_modulebox->module()->atom() : pn_atom;
}
inline bool
ParseNode::isConstant()
{

View File

@ -118,7 +118,7 @@ static bool
PushNodeChildren(ParseNode *pn, NodeStack *stack)
{
switch (pn->getArity()) {
case PN_FUNC:
case PN_CODE:
/*
* Function nodes are linked into the function box tree, and may appear
* on method lists. Both of those lists are singly-linked, so trying to
@ -385,13 +385,18 @@ CloneParseTree(ParseNode *opn, Parser *parser)
switch (pn->getArity()) {
#define NULLCHECK(e) JS_BEGIN_MACRO if (!(e)) return NULL; JS_END_MACRO
case PN_FUNC:
NULLCHECK(pn->pn_funbox =
parser->newFunctionBox(opn->pn_funbox->function(), pc, opn->pn_funbox->strict));
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;
case PN_CODE:
if (pn->getKind() == PNK_MODULE) {
NULLCHECK(pn->pn_modulebox = parser->newModuleBox(opn->pn_modulebox->module(), pc));
NULLCHECK(pn->pn_body = CloneParseTree(opn->pn_body, parser));
} else {
NULLCHECK(pn->pn_funbox =
parser->newFunctionBox(opn->pn_funbox->function(), pc, opn->pn_funbox->strict));
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;
}
break;
case PN_LIST:

View File

@ -131,6 +131,7 @@ class UpvarCookie
F(FORHEAD) \
F(ARGSBODY) \
F(SPREAD) \
F(MODULE) \
\
/* Equality operators. */ \
F(STRICTEQ) \
@ -394,7 +395,7 @@ enum ParseNodeArity {
PN_UNARY, /* one kid, plus a couple of scalars */
PN_BINARY, /* two kids, plus a couple of scalars */
PN_TERNARY, /* three kids */
PN_FUNC, /* function definition node */
PN_CODE, /* module or function definition node */
PN_LIST, /* generic singly linked list */
PN_NAME /* name use or definition node */
};
@ -406,6 +407,7 @@ class BreakStatement;
class ContinueStatement;
class ConditionalExpression;
class PropertyAccess;
class ModuleBox;
struct ParseNode {
private:
@ -502,14 +504,16 @@ struct ParseNode {
} unary;
struct { /* name, labeled statement, etc. */
union {
JSAtom *atom; /* lexical name or label atom */
ObjectBox *objbox; /* block or regexp object */
FunctionBox *funbox; /* function object */
JSAtom *atom; /* lexical name or label atom */
ObjectBox *objbox; /* block or regexp object */
ModuleBox *modulebox; /* module object */
FunctionBox *funbox; /* function object */
};
union {
ParseNode *expr; /* function body, var initializer, argument default,
or base object of PNK_DOT */
Definition *lexdef; /* lexical definition for this use */
ParseNode *expr; /* module or function body, var
initializer, argument default, or
base object of PNK_DOT */
Definition *lexdef; /* lexical definition for this use */
};
UpvarCookie cookie; /* upvar cookie with absolute frame
level (not relative skip), possibly
@ -528,6 +532,7 @@ struct ParseNode {
} loopControl;
} pn_u;
#define pn_modulebox pn_u.name.modulebox
#define pn_funbox pn_u.name.funbox
#define pn_body pn_u.name.expr
#define pn_cookie pn_u.name.cookie
@ -585,6 +590,7 @@ struct ParseNode {
Parser *parser);
inline PropertyName *name() const;
inline JSAtom *atom() const;
/*
* The pn_expr and lexdef members are arms of an unsafe union. Unless you
@ -594,7 +600,7 @@ struct ParseNode {
*/
ParseNode *expr() const {
JS_ASSERT(!pn_used);
JS_ASSERT(pn_arity == PN_NAME || pn_arity == PN_FUNC);
JS_ASSERT(pn_arity == PN_NAME || pn_arity == PN_CODE);
return pn_expr;
}
@ -609,7 +615,7 @@ struct ParseNode {
Definition *resolve();
/* PN_FUNC and PN_NAME pn_dflags bits. */
/* PN_CODE and PN_NAME pn_dflags bits. */
#define PND_LET 0x01 /* let (block-scoped) binding */
#define PND_CONST 0x02 /* const binding (orthogonal to let) */
#define PND_ASSIGNED 0x04 /* set if ever LHS of assignment */
@ -650,17 +656,17 @@ struct ParseNode {
#define PNX_NONCONST 0x400 /* initialiser has non-constants */
unsigned frameLevel() const {
JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
JS_ASSERT(pn_arity == PN_CODE || pn_arity == PN_NAME);
return pn_cookie.level();
}
unsigned frameSlot() const {
JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
JS_ASSERT(pn_arity == PN_CODE || pn_arity == PN_NAME);
return pn_cookie.slot();
}
bool functionIsHoisted() const {
JS_ASSERT(pn_arity == PN_FUNC);
JS_ASSERT(pn_arity == PN_CODE && getKind() == PNK_FUNCTION);
JS_ASSERT(isOp(JSOP_LAMBDA) || // lambda, genexpr
isOp(JSOP_DEFFUN) || // non-body-level function statement
isOp(JSOP_NOP) || // body-level function stmt in global code
@ -933,13 +939,13 @@ struct ListNode : public ParseNode
#endif
};
struct FunctionNode : public ParseNode {
static inline FunctionNode *create(ParseNodeKind kind, Parser *parser) {
return (FunctionNode *) ParseNode::create(kind, PN_FUNC, parser);
struct CodeNode : public ParseNode {
static inline CodeNode *create(ParseNodeKind kind, Parser *parser) {
return (CodeNode *) ParseNode::create(kind, PN_CODE, parser);
}
static bool test(const ParseNode &node) {
return node.isArity(PN_FUNC);
return node.isArity(PN_CODE);
}
#ifdef DEBUG
@ -1307,8 +1313,6 @@ LinkUseToDef(ParseNode *pn, Definition *dn)
pn->pn_lexdef = dn;
}
class ModuleBox;
class ObjectBox {
public:
JSObject *object;

View File

@ -1265,7 +1265,7 @@ LeaveFunction(ParseNode *fn, Parser *parser, HandlePropertyName funName,
* when leaving the inner function.
*
* The dn == outer_dn case arises with generator expressions
* (see CompExprTransplanter::transplant, the PN_FUNC/PN_NAME
* (see CompExprTransplanter::transplant, the PN_CODE/PN_NAME
* case), and nowhere else, currently.
*/
if (dn != outer_dn) {
@ -1541,7 +1541,7 @@ Parser::functionDef(HandlePropertyName funName, const TokenStream::Position &sta
JS_ASSERT_IF(kind == Statement, funName);
/* Make a TOK_FUNCTION node. */
ParseNode *pn = FunctionNode::create(PNK_FUNCTION, this);
ParseNode *pn = CodeNode::create(PNK_FUNCTION, this);
if (!pn)
return NULL;
pn->pn_body = NULL;
@ -1592,7 +1592,7 @@ Parser::functionDef(HandlePropertyName funName, const TokenStream::Position &sta
if (Definition *fn = pc->lexdeps.lookupDefn(funName)) {
JS_ASSERT(fn->isDefn());
fn->setKind(PNK_FUNCTION);
fn->setArity(PN_FUNC);
fn->setArity(PN_CODE);
fn->pn_pos.begin = pn->pn_pos.begin;
fn->pn_pos.end = pn->pn_pos.end;
@ -4830,7 +4830,7 @@ BumpStaticLevel(ParseNode *pn, ParseContext *pc)
static bool
AdjustBlockId(ParseNode *pn, unsigned adjust, ParseContext *pc)
{
JS_ASSERT(pn->isArity(PN_LIST) || pn->isArity(PN_FUNC) || pn->isArity(PN_NAME));
JS_ASSERT(pn->isArity(PN_LIST) || pn->isArity(PN_CODE) || pn->isArity(PN_NAME));
if (JS_BIT(20) - pn->pn_blockid <= adjust + 1) {
JS_ReportErrorNumber(pc->sc->context, js_GetErrorMessage, NULL, JSMSG_NEED_DIET, "program");
return false;
@ -4884,7 +4884,7 @@ CompExprTransplanter::transplant(ParseNode *pn)
return false;
break;
case PN_FUNC:
case PN_CODE:
case PN_NAME:
if (!transplant(pn->maybeExpr()))
return false;
@ -5267,7 +5267,7 @@ Parser::generatorExpr(ParseNode *kid)
pn->pn_hidden = true;
/* Make a new node for the desugared generator function. */
ParseNode *genfn = FunctionNode::create(PNK_FUNCTION, this);
ParseNode *genfn = CodeNode::create(PNK_FUNCTION, this);
if (!genfn)
return NULL;
genfn->setOp(JSOP_LAMBDA);