mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 568953 - Refactor FunctionNode; r=jorendorff
This commit is contained in:
parent
e603f6fb3e
commit
998a480f3e
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user