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();
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)
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)
return false;
right->setOp(JSOP_STRING);
right->pn_pos = pn->pn_pos;
right->pn_atom = pn->pn_atom;
} else {
JS_ASSERT(pn->isArity(PN_BINARY));
left = pn->pn_left;
@ -6016,8 +6012,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break;
case PNK_REGEXP:
JS_ASSERT(pn->isOp(JSOP_REGEXP));
ok = EmitRegExp(cx, bce->regexpList.add(pn->pn_objbox), bce);
ok = EmitRegExp(cx, bce->regexpList.add(pn->as<RegExpLiteral>().objbox()), bce);
break;
case PNK_TRUE:

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

@ -130,6 +130,18 @@ class FullParseHandler
ParseNode *newNullLiteral(const TokenPos &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) {
return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
}

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

@ -370,12 +370,12 @@ enum ParseNodeKind
* PN_NAME node for x on left and right of PNK_COLON
* node in PNK_OBJECT's list, has PNX_DESTRUCT flag
* PNK_NAME, name pn_atom: name, string, or object atom
* PNK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or
* JSOP_REGEXP
* PNK_REGEXP If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
* PNK_STRING pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT
* If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
* with pn_cookie telling (staticLevel, slot) (see
* jsscript.h's UPVAR macros) and pn_dflags telling
* 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
* of the expr member it overlays
* PNK_NUMBER dval pn_dval: double value of numeric literal
@ -820,9 +820,16 @@ struct NullaryNode : public ParseNode
{
NullaryNode(ParseNodeKind kind, const TokenPos &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) {
return (NullaryNode *) ParseNode::create(kind, PN_NULLARY, handler);
// This constructor is for a few mad uses in the emitter. It populates
// 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) {
@ -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
{
public:

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

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

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

@ -500,7 +500,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
Node pushLexicalScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt);
Node pushLetScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt);
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);
bool checkDestructuring(BindData<ParseHandler> *data, Node left, bool toplevel = true);
bool bindDestructuringVar(BindData<ParseHandler> *data, Node pn);

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

@ -69,6 +69,10 @@ class SyntaxParseHandler
Node newBooleanLiteral(bool cond, const TokenPos &pos) { return NodeGeneric; }
Node newThisLiteral(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 newElision() { return NodeGeneric; }

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

@ -2648,7 +2648,7 @@ ASTSerializer::literal(ParseNode *pn, MutableHandleValue dst)
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>());
RootedObject proto(cx);