Bug 695752 - Part 2 - Add Parser::new_ methods for creatinng parse nodes. r=luke.

--HG--
extra : rebase_source : 9978265f81e72929f55a78da55250a431c64c041
This commit is contained in:
Jason Orendorff 2011-10-19 16:44:18 -05:00
parent 30b9012a13
commit b90a714b55
6 changed files with 99 additions and 111 deletions

View File

@ -59,6 +59,8 @@ JS_STATIC_ASSERT(pn_offsetof(pn_link) == pn_offsetof(dn_uses));
#undef pn_offsetof
namespace js {
void
ParseNode::become(ParseNode *pn2)
{
@ -111,7 +113,6 @@ ParseNode::clear()
pn_parens = false;
}
bool
FunctionBox::joinable() const
{
@ -151,8 +152,6 @@ FunctionBox::shouldUnbrand(uintN methods, uintN slowMethods) const
return false;
}
namespace js {
/* Add |node| to |parser|'s free node list. */
void
AddNodeToFreeList(ParseNode *pn, Parser *parser)
@ -215,8 +214,6 @@ class NodeStack {
ParseNode *top;
};
} /* namespace js */
/*
* Push the children of |pn| on |stack|. Return true if |pn| itself could be
* safely recycled, or false if it must be cleaned later (pn_used and pn_defn
@ -299,8 +296,6 @@ PushNodeChildren(ParseNode *pn, NodeStack *stack)
return true;
}
namespace js {
/*
* Prepare |pn| to be mutated in place into a new kind of node. Recycle all
* |pn|'s recyclable children (but not |pn| itself!), and disconnect it from
@ -374,33 +369,24 @@ RecycleTree(ParseNode *pn, TreeContext *tc)
}
/*
* Allocate a ParseNode from tc's node freelist or, failing that, from
* Allocate a ParseNode from parser's node freelist or, failing that, from
* cx's temporary arena.
*/
ParseNode *
NewOrRecycledNode(TreeContext *tc)
void *
AllocNodeUninitialized(Parser *parser)
{
ParseNode *pn = tc->parser->nodeList;
if (!pn) {
JSContext *cx = tc->parser->context;
pn = (ParseNode *) cx->tempLifoAlloc().alloc(sizeof (ParseNode));
if (!pn)
js_ReportOutOfMemory(cx);
} else {
tc->parser->nodeList = pn->pn_next;
if (ParseNode *pn = parser->nodeList) {
parser->nodeList = pn->pn_next;
return pn;
}
if (pn) {
pn->setUsed(false);
pn->setDefn(false);
memset(&pn->pn_u, 0, sizeof pn->pn_u);
pn->pn_next = NULL;
}
return pn;
JSContext *cx = parser->context;
void *p = cx->tempLifoAlloc().alloc(sizeof (ParseNode));
if (!p)
js_ReportOutOfMemory(cx);
return p;
}
} /* namespace js */
/* used only by static create methods of subclasses */
ParseNode *
@ -414,12 +400,10 @@ ParseNode *
ParseNode::create(ParseNodeArity arity, TokenKind type, JSOp op, const TokenPos &pos,
TreeContext *tc)
{
ParseNode *pn = NewOrRecycledNode(tc);
if (!pn)
void *p = AllocNodeUninitialized(tc->parser);
if (!p)
return NULL;
pn->init(type, op, arity);
pn->pn_pos = pos;
return pn;
return new(p) ParseNode(type, op, arity, pos);
}
ParseNode *
@ -481,19 +465,9 @@ ParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, ParseNode *left, ParseNode *
return left;
}
ParseNode *pn = NewOrRecycledNode(tc);
if (!pn)
return NULL;
pn->init(tt, op, PN_BINARY);
pn->pn_pos.begin = left->pn_pos.begin;
pn->pn_pos.end = right->pn_pos.end;
pn->pn_left = left;
pn->pn_right = right;
return pn;
return tc->parser->new_<BinaryNode>(tt, op, left, right);
}
namespace js {
NameNode *
NameNode::create(JSAtom *atom, TreeContext *tc)
{
@ -511,6 +485,8 @@ const char js_argument_str[] = "argument";
const char js_variable_str[] = "variable";
const char js_unknown_str[] = "unknown";
namespace js {
const char *
Definition::kindString(Kind kind)
{
@ -534,16 +510,13 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
{
JS_CHECK_RECURSION(tc->parser->context, return NULL);
ParseNode *pn = NewOrRecycledNode(tc);
ParseNode *pn = tc->parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
if (!pn)
return NULL;
pn->setKind(opn->getKind());
pn->setOp(opn->getOp());
pn->setUsed(opn->isUsed());
pn->setDefn(opn->isDefn());
pn->setArity(opn->getArity());
pn->setInParens(opn->isInParens());
pn->pn_pos = opn->pn_pos;
pn->setDefn(opn->isDefn());
pn->setUsed(opn->isUsed());
switch (pn->getArity()) {
#define NULLCHECK(e) JS_BEGIN_MACRO if (!(e)) return NULL; JS_END_MACRO
@ -632,8 +605,6 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
#endif /* JS_HAS_DESTRUCTURING */
namespace js {
/*
* Used by Parser::forStatement and comprehensionTail to clone the TARGET in
* for (var/const/let TARGET in EXPR)
@ -647,16 +618,13 @@ namespace js {
ParseNode *
CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
{
ParseNode *pn = NewOrRecycledNode(tc);
ParseNode *pn = tc->parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
if (!pn)
return NULL;
pn->setKind(opn->getKind());
pn->setOp(opn->getOp());
pn->setUsed(opn->isUsed());
pn->setDefn(opn->isDefn());
pn->setArity(opn->getArity());
pn->setInParens(opn->isInParens());
pn->pn_pos = opn->pn_pos;
pn->setDefn(opn->isDefn());
pn->setUsed(opn->isUsed());
#if JS_HAS_DESTRUCTURING
if (opn->isArity(PN_LIST)) {
@ -674,7 +642,8 @@ CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
ParseNode *target = CloneLeftHandSide(opn2->pn_right, tc);
if (!target)
return NULL;
pn2 = BinaryNode::create(TOK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target, tc);
pn2 = tc->parser->new_<BinaryNode>(TOK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target);
} else if (opn2->isArity(PN_NULLARY)) {
JS_ASSERT(opn2->isKind(TOK_COMMA));
pn2 = CloneParseTree(opn2, tc);

View File

@ -346,10 +346,10 @@ struct ParseNode {
/* Boolean attributes. */
bool isInParens() const { return pn_parens; }
void setInParens(bool enabled) { pn_parens = enabled; }
bool isDefn() const { return pn_defn; }
void setDefn(bool enabled) { pn_defn = enabled; }
bool isUsed() const { return pn_used; }
void setUsed(bool enabled) { pn_used = enabled; }
bool isDefn() const { return pn_defn; }
void setDefn(bool enabled) { pn_defn = enabled; }
TokenPos pn_pos; /* two 16-bit pairs here, for 64 bits */
int32 pn_offset; /* first generated bytecode offset */
@ -698,21 +698,30 @@ struct NullaryNode : public ParseNode {
};
struct UnaryNode : public ParseNode {
UnaryNode(TokenKind type, JSOp op, const TokenPos &pos, ParseNode *kid)
: ParseNode(type, op, PN_UNARY, pos)
{
pn_kid = kid;
}
static inline UnaryNode *create(TreeContext *tc) {
return (UnaryNode *)ParseNode::create(PN_UNARY, tc);
}
};
struct BinaryNode : public ParseNode {
static inline BinaryNode *create(TokenKind type, JSOp op, const TokenPos &pos,
ParseNode *left, ParseNode *right,
TreeContext *tc) {
BinaryNode *pn = (BinaryNode *) ParseNode::create(PN_BINARY, type, op, pos, tc);
if (pn) {
pn->pn_left = left;
pn->pn_right = right;
}
return pn;
BinaryNode(TokenKind type, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right)
: ParseNode(type, op, PN_BINARY, pos)
{
pn_left = left;
pn_right = right;
}
BinaryNode(TokenKind type, JSOp op, ParseNode *left, ParseNode *right)
: ParseNode(type, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos))
{
pn_left = left;
pn_right = right;
}
static inline BinaryNode *create(TreeContext *tc) {
@ -721,19 +730,14 @@ struct BinaryNode : public ParseNode {
};
struct TernaryNode : public ParseNode {
static inline TernaryNode *create(TokenKind type, JSOp op,
ParseNode *kid1, ParseNode *kid2, ParseNode *kid3,
TreeContext *tc) {
TokenPos pos;
pos.begin = (kid1 ? kid1 : kid2)->pn_pos.begin;
pos.end = kid3->pn_pos.end;
TernaryNode *pn = (TernaryNode *) ParseNode::create(PN_TERNARY, type, op, pos, tc);
if (pn) {
pn->pn_kid1 = kid1;
pn->pn_kid2 = kid2;
pn->pn_kid3 = kid3;
}
return pn;
TernaryNode(TokenKind type, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3)
: ParseNode(type, op, PN_TERNARY,
TokenPos((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
(kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
{
pn_kid1 = kid1;
pn_kid2 = kid2;
pn_kid3 = kid3;
}
static inline TernaryNode *create(TreeContext *tc) {
@ -771,8 +775,8 @@ struct LexicalScopeNode : public ParseNode {
}
};
ParseNode *
NewOrRecycledNode(TreeContext *tc);
void *
AllocNodeUninitialized(Parser *parser);
void
AddNodeToFreeList(ParseNode *pn, Parser *parser);

View File

@ -788,10 +788,9 @@ ForgetUse(ParseNode *pn)
static ParseNode *
MakeAssignment(ParseNode *pn, ParseNode *rhs, TreeContext *tc)
{
ParseNode *lhs = NewOrRecycledNode(tc);
ParseNode *lhs = tc->parser->new_<ParseNode>(*pn);
if (!lhs)
return NULL;
*lhs = *pn;
if (pn->isUsed()) {
Definition *dn = pn->pn_lexdef;
@ -5977,7 +5976,7 @@ Parser::comprehensionTail(ParseNode *kid, uintN blockid, bool isGenexp,
if (!pn3)
return NULL;
pn2->pn_left = TernaryNode::create(TOK_IN, JSOP_NOP, vars, pn3, pn4, tc);
pn2->pn_left = new_<TernaryNode>(TOK_IN, JSOP_NOP, vars, pn3, pn4);
if (!pn2->pn_left)
return NULL;
*pnp = pn2;
@ -6218,16 +6217,9 @@ Parser::memberExpr(JSBool allowCallSyntax)
return NULL;
if (pn->isKind(TOK_ANYNAME) || pn->isKind(TOK_AT) || pn->isKind(TOK_DBLCOLON)) {
pn2 = NewOrRecycledNode(tc);
if (!pn2)
pn = new_<UnaryNode>(TOK_UNARYOP, JSOP_XMLNAME, pn->pn_pos, pn);
if (!pn)
return NULL;
pn2->setKind(TOK_UNARYOP);
pn2->pn_pos = pn->pn_pos;
pn2->setOp(JSOP_XMLNAME);
pn2->setArity(PN_UNARY);
pn2->setInParens(false);
pn2->pn_kid = pn;
pn = pn2;
}
}

View File

@ -180,6 +180,15 @@ struct Parser : private AutoGCRooter
*/
inline bool reportErrorNumber(ParseNode *pn, uintN flags, uintN errorNumber, ...);
private:
void *allocParseNode(size_t size) {
JS_ASSERT(size == sizeof(ParseNode));
return AllocNodeUninitialized(this);
}
public:
JS_DECLARE_NEW_METHODS(allocParseNode,);
private:
/*
* JS parsers, from lowest to highest precedence.

View File

@ -179,29 +179,29 @@ struct TokenPtr {
uint32 index; /* index of char in physical line */
uint32 lineno; /* physical line number */
bool operator==(const TokenPtr& bptr) {
bool operator==(const TokenPtr& bptr) const {
return index == bptr.index && lineno == bptr.lineno;
}
bool operator!=(const TokenPtr& bptr) {
bool operator!=(const TokenPtr& bptr) const {
return index != bptr.index || lineno != bptr.lineno;
}
bool operator <(const TokenPtr& bptr) {
bool operator <(const TokenPtr& bptr) const {
return lineno < bptr.lineno ||
(lineno == bptr.lineno && index < bptr.index);
}
bool operator <=(const TokenPtr& bptr) {
bool operator <=(const TokenPtr& bptr) const {
return lineno < bptr.lineno ||
(lineno == bptr.lineno && index <= bptr.index);
}
bool operator >(const TokenPtr& bptr) {
bool operator >(const TokenPtr& bptr) const {
return !(*this <= bptr);
}
bool operator >=(const TokenPtr& bptr) {
bool operator >=(const TokenPtr& bptr) const {
return !(*this < bptr);
}
};
@ -210,27 +210,41 @@ struct TokenPos {
TokenPtr begin; /* first character and line of token */
TokenPtr end; /* index 1 past last char, last line */
bool operator==(const TokenPos& bpos) {
TokenPos() {}
TokenPos(const TokenPtr &begin, const TokenPtr &end) : begin(begin), end(end) {
JS_ASSERT(begin <= end);
}
/* Return a TokenPos that covers left, right, and anything in between. */
static TokenPos box(const TokenPos &left, const TokenPos &right) {
JS_ASSERT(left.begin <= left.end);
JS_ASSERT(left.end <= right.begin);
JS_ASSERT(right.begin <= right.end);
return TokenPos(left.begin, right.end);
}
bool operator==(const TokenPos& bpos) const {
return begin == bpos.begin && end == bpos.end;
}
bool operator!=(const TokenPos& bpos) {
bool operator!=(const TokenPos& bpos) const {
return begin != bpos.begin || end != bpos.end;
}
bool operator <(const TokenPos& bpos) {
bool operator <(const TokenPos& bpos) const {
return begin < bpos.begin;
}
bool operator <=(const TokenPos& bpos) {
bool operator <=(const TokenPos& bpos) const {
return begin <= bpos.begin;
}
bool operator >(const TokenPos& bpos) {
bool operator >(const TokenPos& bpos) const {
return !(*this <= bpos);
}
bool operator >=(const TokenPos& bpos) {
bool operator >=(const TokenPos& bpos) const {
return !(*this < bpos);
}
};

View File

@ -2297,7 +2297,7 @@ ASTSerializer::leftAssociate(ParseNode *pn, Value *dst)
if (!expression(next, &right))
return false;
TokenPos subpos = { pn->pn_pos.begin, next->pn_pos.end };
TokenPos subpos(pn->pn_pos.begin, next->pn_pos.end);
if (logop) {
if (!builder.logicalExpression(lor, left, right, &subpos, &left))