From 998a480f3e5798aa4ebb94022fa31572fbe0663d Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Tue, 19 Feb 2013 23:06:14 +0100 Subject: [PATCH] Bug 568953 - Refactor FunctionNode; r=jorendorff --- js/src/frontend/BytecodeCompiler.cpp | 2 +- js/src/frontend/BytecodeEmitter.cpp | 2 +- js/src/frontend/FoldConstants.cpp | 12 ++++++--- js/src/frontend/NameFunctions.cpp | 4 +-- js/src/frontend/ParseNode-inl.h | 7 +++++ js/src/frontend/ParseNode.cpp | 21 +++++++++------ js/src/frontend/ParseNode.h | 40 +++++++++++++++------------- js/src/frontend/Parser.cpp | 12 ++++----- 8 files changed, 61 insertions(+), 39 deletions(-) diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 4cdd08b8701..888e7089cfd 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -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; diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 4abee457d22..85631460f6b 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -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 diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index 7fae522a70c..3e36dd0dc55 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -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: diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index 3ff960e6a7a..9255cd6e97a 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -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; diff --git a/js/src/frontend/ParseNode-inl.h b/js/src/frontend/ParseNode-inl.h index 8eb64513d48..e20f9876eea 100644 --- a/js/src/frontend/ParseNode-inl.h +++ b/js/src/frontend/ParseNode-inl.h @@ -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() { diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 83307dfad7f..97cf9a36871 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -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: diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 13c22402e60..1820cf30d66 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -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; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index cc5e471f9b8..625491ea7ea 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -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);