Bug 883226, part 1 - Clean up RegExp parsing. Remove NullaryNode::create in favor of constructors. r=Waldo.

This commit is contained in:
Jason Orendorff 2013-06-19 14:43:38 -05:00
Родитель e03649f9ee
Коммит 6a60d5b7a6
7 изменённых файлов: 64 добавлений и 51 удалений

Просмотреть файл

@ -2035,19 +2035,15 @@ EmitElemOperands(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
*/ */
left = pn->maybeExpr(); left = pn->maybeExpr();
if (!left) { if (!left) {
left = NullaryNode::create(PNK_STRING, &bce->parser->handler); left = bce->parser->handler.new_<NullaryNode>(
PNK_STRING, JSOP_BINDNAME, pn->pn_pos, pn->pn_atom);
if (!left) if (!left)
return false; return false;
left->setOp(JSOP_BINDNAME);
left->pn_pos = pn->pn_pos;
left->pn_atom = pn->pn_atom;
} }
right = NullaryNode::create(PNK_STRING, &bce->parser->handler); right = bce->parser->handler.new_<NullaryNode>(
PNK_STRING, JSOP_STRING, pn->pn_pos, pn->pn_atom);
if (!right) if (!right)
return false; return false;
right->setOp(JSOP_STRING);
right->pn_pos = pn->pn_pos;
right->pn_atom = pn->pn_atom;
} else { } else {
JS_ASSERT(pn->isArity(PN_BINARY)); JS_ASSERT(pn->isArity(PN_BINARY));
left = pn->pn_left; left = pn->pn_left;
@ -6016,8 +6012,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break; break;
case PNK_REGEXP: case PNK_REGEXP:
JS_ASSERT(pn->isOp(JSOP_REGEXP)); ok = EmitRegExp(cx, bce->regexpList.add(pn->as<RegExpLiteral>().objbox()), bce);
ok = EmitRegExp(cx, bce->regexpList.add(pn->pn_objbox), bce);
break; break;
case PNK_TRUE: case PNK_TRUE:

Просмотреть файл

@ -130,6 +130,18 @@ class FullParseHandler
ParseNode *newNullLiteral(const TokenPos &pos) { ParseNode *newNullLiteral(const TokenPos &pos) {
return new_<NullLiteral>(pos); return new_<NullLiteral>(pos);
} }
// The Boxer object here is any object that can allocate ObjectBoxes.
// Specifically, a Boxer has a .newObjectBox(T) method that accepts a
// Rooted<RegExpObject*> argument and returns an ObjectBox*.
template <class Boxer>
ParseNode *newRegExp(HandleObject reobj, const TokenPos &pos, Boxer &boxer) {
ObjectBox *objbox = boxer.newObjectBox(reobj);
if (!objbox)
return null();
return new_<RegExpLiteral>(objbox, pos);
}
ParseNode *newConditional(ParseNode *cond, ParseNode *thenExpr, ParseNode *elseExpr) { ParseNode *newConditional(ParseNode *cond, ParseNode *thenExpr, ParseNode *elseExpr) {
return new_<ConditionalExpression>(cond, thenExpr, elseExpr); return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
} }

Просмотреть файл

@ -370,12 +370,12 @@ enum ParseNodeKind
* PN_NAME node for x on left and right of PNK_COLON * PN_NAME node for x on left and right of PNK_COLON
* node in PNK_OBJECT's list, has PNX_DESTRUCT flag * node in PNK_OBJECT's list, has PNX_DESTRUCT flag
* PNK_NAME, name pn_atom: name, string, or object atom * PNK_NAME, name pn_atom: name, string, or object atom
* PNK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or * PNK_STRING pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT
* JSOP_REGEXP * If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
* PNK_REGEXP If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
* with pn_cookie telling (staticLevel, slot) (see * with pn_cookie telling (staticLevel, slot) (see
* jsscript.h's UPVAR macros) and pn_dflags telling * jsscript.h's UPVAR macros) and pn_dflags telling
* const-ness and static analysis results * const-ness and static analysis results
* PNK_REGEXP nullary pn_objbox: RegExp model object
* PNK_NAME name If pn_used, PNK_NAME uses the lexdef member instead * PNK_NAME name If pn_used, PNK_NAME uses the lexdef member instead
* of the expr member it overlays * of the expr member it overlays
* PNK_NUMBER dval pn_dval: double value of numeric literal * PNK_NUMBER dval pn_dval: double value of numeric literal
@ -820,9 +820,16 @@ struct NullaryNode : public ParseNode
{ {
NullaryNode(ParseNodeKind kind, const TokenPos &pos) NullaryNode(ParseNodeKind kind, const TokenPos &pos)
: ParseNode(kind, JSOP_NOP, PN_NULLARY, pos) {} : ParseNode(kind, JSOP_NOP, PN_NULLARY, pos) {}
NullaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos)
: ParseNode(kind, op, PN_NULLARY, pos) {}
static inline NullaryNode *create(ParseNodeKind kind, FullParseHandler *handler) { // This constructor is for a few mad uses in the emitter. It populates
return (NullaryNode *) ParseNode::create(kind, PN_NULLARY, handler); // the pn_atom field even though that field belongs to a branch in pn_u
// that nullary nodes shouldn't use -- bogus.
NullaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, JSAtom *atom)
: ParseNode(kind, op, PN_NULLARY, pos)
{
pn_atom = atom;
} }
static bool test(const ParseNode &node) { static bool test(const ParseNode &node) {
@ -1112,6 +1119,25 @@ class BooleanLiteral : public ParseNode
{ } { }
}; };
class RegExpLiteral : public NullaryNode
{
public:
RegExpLiteral(ObjectBox *reobj, const TokenPos &pos)
: NullaryNode(PNK_REGEXP, JSOP_REGEXP, pos)
{
pn_objbox = reobj;
}
ObjectBox *objbox() const { return pn_objbox; }
static bool test(const ParseNode &node) {
bool match = node.isKind(PNK_REGEXP);
JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
JS_ASSERT_IF(match, node.isOp(JSOP_REGEXP));
return match;
}
};
class PropertyAccess : public ParseNode class PropertyAccess : public ParseNode
{ {
public: public:

Просмотреть файл

@ -6488,15 +6488,14 @@ Parser<ParseHandler>::atomNode(ParseNodeKind kind, JSOp op)
return pn; return pn;
} }
template <> template <typename ParseHandler>
ParseNode * typename ParseHandler::Node
Parser<FullParseHandler>::newRegExp(const jschar *buf, size_t length, RegExpFlag flags) Parser<ParseHandler>::newRegExp()
{ {
ParseNode *pn = NullaryNode::create(PNK_REGEXP, &handler); // Create the regexp even when doing a syntax parse, to check the regexp's syntax.
if (!pn) size_t length = tokenStream.getTokenbuf().length();
return NULL; const StableCharPtr chars(tokenStream.getTokenbuf().begin(), length);
RegExpFlag flags = tokenStream.currentToken().regExpFlags();
const StableCharPtr chars(buf, length);
Rooted<RegExpObject*> reobj(context); Rooted<RegExpObject*> reobj(context);
if (RegExpStatics *res = context->regExpStatics()) if (RegExpStatics *res = context->regExpStatics())
@ -6505,30 +6504,9 @@ Parser<FullParseHandler>::newRegExp(const jschar *buf, size_t length, RegExpFlag
reobj = RegExpObject::createNoStatics(context, chars.get(), length, flags, &tokenStream); reobj = RegExpObject::createNoStatics(context, chars.get(), length, flags, &tokenStream);
if (!reobj) if (!reobj)
return NULL; return null();
pn->pn_objbox = newObjectBox(reobj); return handler.newRegExp(reobj, pos(), *this);
if (!pn->pn_objbox)
return NULL;
pn->setOp(JSOP_REGEXP);
return pn;
}
template <>
SyntaxParseHandler::Node
Parser<SyntaxParseHandler>::newRegExp(const jschar *buf, size_t length, RegExpFlag flags)
{
// Create the regexp even when doing a syntax parse, to check the regexp's syntax.
const StableCharPtr chars(buf, length);
RegExpObject *reobj;
if (RegExpStatics *res = context->regExpStatics())
reobj = RegExpObject::create(context, res, chars.get(), length, flags, &tokenStream);
else
reobj = RegExpObject::createNoStatics(context, chars.get(), length, flags, &tokenStream);
return reobj ? SyntaxParseHandler::NodeGeneric : SyntaxParseHandler::NodeFailure;
} }
template <typename ParseHandler> template <typename ParseHandler>
@ -6932,9 +6910,7 @@ Parser<ParseHandler>::primaryExpr(TokenKind tt)
break; break;
case TOK_REGEXP: case TOK_REGEXP:
pn = newRegExp(tokenStream.getTokenbuf().begin(), pn = newRegExp();
tokenStream.getTokenbuf().length(),
tokenStream.currentToken().regExpFlags());
break; break;
case TOK_NUMBER: case TOK_NUMBER:

Просмотреть файл

@ -500,7 +500,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
Node pushLexicalScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt); Node pushLexicalScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt);
Node pushLetScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt); Node pushLetScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt);
bool noteNameUse(HandlePropertyName name, Node pn); bool noteNameUse(HandlePropertyName name, Node pn);
Node newRegExp(const jschar *chars, size_t length, RegExpFlag flags); Node newRegExp();
Node newBindingNode(PropertyName *name, bool functionScope, VarContext varContext = HoistVars); Node newBindingNode(PropertyName *name, bool functionScope, VarContext varContext = HoistVars);
bool checkDestructuring(BindData<ParseHandler> *data, Node left, bool toplevel = true); bool checkDestructuring(BindData<ParseHandler> *data, Node left, bool toplevel = true);
bool bindDestructuringVar(BindData<ParseHandler> *data, Node pn); bool bindDestructuringVar(BindData<ParseHandler> *data, Node pn);

Просмотреть файл

@ -69,6 +69,10 @@ class SyntaxParseHandler
Node newBooleanLiteral(bool cond, const TokenPos &pos) { return NodeGeneric; } Node newBooleanLiteral(bool cond, const TokenPos &pos) { return NodeGeneric; }
Node newThisLiteral(const TokenPos &pos) { return NodeGeneric; } Node newThisLiteral(const TokenPos &pos) { return NodeGeneric; }
Node newNullLiteral(const TokenPos &pos) { return NodeGeneric; } Node newNullLiteral(const TokenPos &pos) { return NodeGeneric; }
template <class Boxer>
Node newRegExp(JSObject *reobj, const TokenPos &pos, Boxer &boxer) { return NodeGeneric; }
Node newConditional(Node cond, Node thenExpr, Node elseExpr) { return NodeGeneric; } Node newConditional(Node cond, Node thenExpr, Node elseExpr) { return NodeGeneric; }
Node newElision() { return NodeGeneric; } Node newElision() { return NodeGeneric; }

Просмотреть файл

@ -2648,7 +2648,7 @@ ASTSerializer::literal(ParseNode *pn, MutableHandleValue dst)
case PNK_REGEXP: case PNK_REGEXP:
{ {
RootedObject re1(cx, pn->pn_objbox ? pn->pn_objbox->object : NULL); RootedObject re1(cx, pn->as<RegExpLiteral>().objbox()->object);
LOCAL_ASSERT(re1 && re1->is<RegExpObject>()); LOCAL_ASSERT(re1 && re1->is<RegExpObject>());
RootedObject proto(cx); RootedObject proto(cx);