зеркало из https://github.com/mozilla/gecko-dev.git
Bug 883226, part 1 - Clean up RegExp parsing. Remove NullaryNode::create in favor of constructors. r=Waldo.
This commit is contained in:
Родитель
e03649f9ee
Коммит
6a60d5b7a6
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче