mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Bug 1227677 - Extract PNK_COMPREHENSIONFOR from PNK_FOR so that comprehension gunk doesn't taint for-loop emitting logic. r=shu
This commit is contained in:
parent
4560db90e5
commit
f5da2608e0
@ -2495,6 +2495,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
||||
}
|
||||
|
||||
case PNK_FOR:
|
||||
case PNK_COMPREHENSIONFOR:
|
||||
{
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
|
||||
@ -2759,12 +2760,12 @@ ASTSerializer::comprehension(ParseNode* pn, MutableHandleValue dst)
|
||||
// They have slightly different parse trees and scoping.
|
||||
bool isLegacy = pn->isKind(PNK_LEXICALSCOPE);
|
||||
ParseNode* next = isLegacy ? pn->pn_expr : pn;
|
||||
LOCAL_ASSERT(next->isKind(PNK_FOR));
|
||||
LOCAL_ASSERT(next->isKind(PNK_COMPREHENSIONFOR));
|
||||
|
||||
NodeVector blocks(cx);
|
||||
RootedValue filter(cx, MagicValue(JS_SERIALIZE_NO_NODE));
|
||||
while (true) {
|
||||
if (next->isKind(PNK_FOR)) {
|
||||
if (next->isKind(PNK_COMPREHENSIONFOR)) {
|
||||
RootedValue block(cx);
|
||||
if (!comprehensionBlock(next, &block) || !blocks.append(block))
|
||||
return false;
|
||||
@ -2802,12 +2803,12 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst)
|
||||
// expression.
|
||||
bool isLegacy = pn->isKind(PNK_LEXICALSCOPE);
|
||||
ParseNode* next = isLegacy ? pn->pn_expr : pn;
|
||||
LOCAL_ASSERT(next->isKind(PNK_FOR));
|
||||
LOCAL_ASSERT(next->isKind(PNK_COMPREHENSIONFOR));
|
||||
|
||||
NodeVector blocks(cx);
|
||||
RootedValue filter(cx, MagicValue(JS_SERIALIZE_NO_NODE));
|
||||
while (true) {
|
||||
if (next->isKind(PNK_FOR)) {
|
||||
if (next->isKind(PNK_COMPREHENSIONFOR)) {
|
||||
RootedValue block(cx);
|
||||
if (!comprehensionBlock(next, &block) || !blocks.append(block))
|
||||
return false;
|
||||
|
@ -2189,6 +2189,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||
case PNK_DOWHILE:
|
||||
case PNK_WHILE:
|
||||
case PNK_FOR:
|
||||
case PNK_COMPREHENSIONFOR:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
*answer = true;
|
||||
return true;
|
||||
@ -2347,9 +2348,9 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||
*answer = true;
|
||||
return true;
|
||||
|
||||
case PNK_FORIN: // by PNK_FOR
|
||||
case PNK_FOROF: // by PNK_FOR
|
||||
case PNK_FORHEAD: // by PNK_FOR
|
||||
case PNK_FORIN: // by PNK_FOR/PNK_COMPREHENSIONFOR
|
||||
case PNK_FOROF: // by PNK_FOR/PNK_COMPREHENSIONFOR
|
||||
case PNK_FORHEAD: // by PNK_FOR/PNK_COMPREHENSIONFOR
|
||||
case PNK_CLASSMETHOD: // by PNK_CLASS
|
||||
case PNK_CLASSNAMES: // by PNK_CLASS
|
||||
case PNK_CLASSMETHODLIST: // by PNK_CLASS
|
||||
@ -5425,8 +5426,14 @@ bool
|
||||
BytecodeEmitter::emitForOf(StmtType type, ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(type == StmtType::FOR_OF_LOOP || type == StmtType::SPREAD);
|
||||
MOZ_ASSERT_IF(type == StmtType::FOR_OF_LOOP, pn && pn->pn_left->isKind(PNK_FOROF));
|
||||
MOZ_ASSERT_IF(type == StmtType::SPREAD, !pn);
|
||||
#ifdef DEBUG
|
||||
if (type == StmtType::FOR_OF_LOOP) {
|
||||
MOZ_ASSERT(pn);
|
||||
MOZ_ASSERT(pn->pn_left->isKind(PNK_FOROF));
|
||||
} else {
|
||||
MOZ_ASSERT(!pn);
|
||||
}
|
||||
#endif
|
||||
|
||||
ptrdiff_t top = offset();
|
||||
ParseNode* forHead = pn ? pn->pn_left : nullptr;
|
||||
@ -7974,6 +7981,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
|
||||
break;
|
||||
|
||||
case PNK_FOR:
|
||||
case PNK_COMPREHENSIONFOR:
|
||||
if (!emitFor(pn))
|
||||
return false;
|
||||
break;
|
||||
|
@ -627,7 +627,8 @@ struct BytecodeEmitter
|
||||
bool emitSpread();
|
||||
|
||||
// If type is StmtType::FOR_OF_LOOP, emit bytecode for a for-of loop.
|
||||
// pn should be PNK_FOR, and pn->pn_left should be PNK_FOROF.
|
||||
// pn should be PNK_FOR or PNK_COMPREHENSIONFOR, and pn->pn_left should be
|
||||
// PNK_FOROF.
|
||||
//
|
||||
// If type is StmtType::SPREAD, emit bytecode for spread operator.
|
||||
// pn should be nullptr.
|
||||
|
@ -241,7 +241,8 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
||||
case PNK_CASE:
|
||||
return ContainsHoistedDeclaration(cx, node->as<CaseClause>().statementList(), result);
|
||||
|
||||
case PNK_FOR: {
|
||||
case PNK_FOR:
|
||||
case PNK_COMPREHENSIONFOR: {
|
||||
MOZ_ASSERT(node->isArity(PN_BINARY));
|
||||
|
||||
ParseNode* loopHead = node->pn_left;
|
||||
@ -1890,6 +1891,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
||||
case PNK_SHORTHAND:
|
||||
case PNK_LETBLOCK:
|
||||
case PNK_FOR:
|
||||
case PNK_COMPREHENSIONFOR:
|
||||
case PNK_CLASSMETHOD:
|
||||
case PNK_IMPORT_SPEC:
|
||||
case PNK_EXPORT_SPEC:
|
||||
|
@ -565,6 +565,19 @@ class FullParseHandler
|
||||
return pn;
|
||||
}
|
||||
|
||||
ParseNode* newComprehensionFor(uint32_t begin, ParseNode* forHead, ParseNode* body) {
|
||||
// A PNK_COMPREHENSIONFOR node is binary: left is loop control, right
|
||||
// is the body.
|
||||
MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF));
|
||||
JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP;
|
||||
BinaryNode* pn = new_<BinaryNode>(PNK_COMPREHENSIONFOR, op,
|
||||
TokenPos(begin, body->pn_pos.end), forHead, body);
|
||||
if (!pn)
|
||||
return null();
|
||||
pn->pn_iflags = JSOP_ITER;
|
||||
return pn;
|
||||
}
|
||||
|
||||
ParseNode* newForHead(ParseNodeKind kind, ParseNode* pn1, ParseNode* pn2, ParseNode* pn3,
|
||||
const TokenPos& pos)
|
||||
{
|
||||
|
@ -448,6 +448,7 @@ class NameResolver
|
||||
case PNK_SWITCH:
|
||||
case PNK_LETBLOCK:
|
||||
case PNK_FOR:
|
||||
case PNK_COMPREHENSIONFOR:
|
||||
case PNK_CLASSMETHOD:
|
||||
case PNK_SETTHIS:
|
||||
MOZ_ASSERT(cur->isArity(PN_BINARY));
|
||||
@ -687,13 +688,15 @@ class NameResolver
|
||||
}
|
||||
break;
|
||||
|
||||
// Array comprehension nodes are lists with a single child -- PNK_FOR for
|
||||
// comprehensions, PNK_LEXICALSCOPE for legacy comprehensions. Probably
|
||||
// this should be a non-list eventually.
|
||||
// Array comprehension nodes are lists with a single child:
|
||||
// PNK_COMPREHENSIONFOR for comprehensions, PNK_LEXICALSCOPE for
|
||||
// legacy comprehensions. Probably this should be a non-list
|
||||
// eventually.
|
||||
case PNK_ARRAYCOMP:
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
MOZ_ASSERT(cur->pn_count == 1);
|
||||
MOZ_ASSERT(cur->pn_head->isKind(PNK_LEXICALSCOPE) || cur->pn_head->isKind(PNK_FOR));
|
||||
MOZ_ASSERT(cur->pn_head->isKind(PNK_LEXICALSCOPE) ||
|
||||
cur->pn_head->isKind(PNK_COMPREHENSIONFOR));
|
||||
if (!resolve(cur->pn_head, prefix))
|
||||
return false;
|
||||
break;
|
||||
|
@ -282,7 +282,8 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||
case PNK_CLASSMETHOD:
|
||||
case PNK_NEWTARGET:
|
||||
case PNK_SETTHIS:
|
||||
case PNK_FOR: {
|
||||
case PNK_FOR:
|
||||
case PNK_COMPREHENSIONFOR: {
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
stack->push(pn->pn_left);
|
||||
stack->push(pn->pn_right);
|
||||
@ -493,15 +494,16 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||
case PNK_CLASSMETHODLIST:
|
||||
return PushListNodeChildren(pn, stack);
|
||||
|
||||
// Array comprehension nodes are lists with a single child -- PNK_FOR for
|
||||
// comprehensions, PNK_LEXICALSCOPE for legacy comprehensions. Probably
|
||||
// this should be a non-list eventually.
|
||||
// Array comprehension nodes are lists with a single child:
|
||||
// PNK_COMPREHENSIONFOR for comprehensions, PNK_LEXICALSCOPE for legacy
|
||||
// comprehensions. Probably this should be a non-list eventually.
|
||||
case PNK_ARRAYCOMP: {
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(pn->isKind(PNK_ARRAYCOMP));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_count == 1);
|
||||
MOZ_ASSERT(pn->pn_head->isKind(PNK_LEXICALSCOPE) || pn->pn_head->isKind(PNK_FOR));
|
||||
MOZ_ASSERT(pn->pn_head->isKind(PNK_LEXICALSCOPE) ||
|
||||
pn->pn_head->isKind(PNK_COMPREHENSIONFOR));
|
||||
#endif
|
||||
return PushListNodeChildren(pn, stack);
|
||||
}
|
||||
|
@ -126,6 +126,7 @@ class PackedScopeCoordinate
|
||||
F(WHILE) \
|
||||
F(DOWHILE) \
|
||||
F(FOR) \
|
||||
F(COMPREHENSIONFOR) \
|
||||
F(BREAK) \
|
||||
F(CONTINUE) \
|
||||
F(VAR) \
|
||||
@ -312,6 +313,8 @@ IsDeleteKind(ParseNodeKind kind)
|
||||
* PNK_FOR binary pn_left: either PNK_FORIN (for-in statement),
|
||||
* PNK_FOROF (for-of) or PNK_FORHEAD (for(;;))
|
||||
* pn_right: body
|
||||
* PNK_COMPREHENSIONFOR pn_left: either PNK_FORIN or PNK_FOROF
|
||||
* binary pn_right: body
|
||||
* PNK_FORIN ternary pn_kid1: PNK_VAR to left of 'in', or nullptr
|
||||
* pn_kid2: PNK_NAME or destructuring expr
|
||||
* to left of 'in'; if pn_kid1, then this
|
||||
@ -619,7 +622,7 @@ class ParseNode
|
||||
ParseNode* left;
|
||||
ParseNode* right;
|
||||
union {
|
||||
unsigned iflags; /* JSITER_* flags for PNK_FOR node */
|
||||
unsigned iflags; /* JSITER_* flags for PNK_{COMPREHENSION,}FOR node */
|
||||
ObjectBox* objbox; /* only for PN_BINARY_OBJ */
|
||||
bool isStatic; /* only for PNK_CLASSMETHOD */
|
||||
uint32_t offset; /* for the emitter's use on PNK_CASE nodes */
|
||||
@ -836,7 +839,8 @@ class ParseNode
|
||||
ParseNode* callee = this->pn_head;
|
||||
ParseNode* body = callee->pn_body;
|
||||
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) || body->last()->isKind(PNK_FOR));
|
||||
MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) ||
|
||||
body->last()->isKind(PNK_COMPREHENSIONFOR));
|
||||
return body->last();
|
||||
}
|
||||
#endif
|
||||
|
@ -7903,12 +7903,10 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode* bodyExpr, unsigned
|
||||
JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
|
||||
while (true) {
|
||||
/*
|
||||
* FOR node is binary, left is loop control and right is body. Use
|
||||
* index to count each block-local let-variable on the left-hand side
|
||||
* of the in/of.
|
||||
*/
|
||||
ParseNode* pn2 = handler.new_<BinaryNode>(PNK_FOR, JSOP_ITER, pos(),
|
||||
// PNK_COMPREHENSIONFOR is binary: left is loop control, right is body.
|
||||
// Use index to count each block-local let-variable on the left-hand
|
||||
// side of the in/of.
|
||||
ParseNode* pn2 = handler.new_<BinaryNode>(PNK_COMPREHENSIONFOR, JSOP_ITER, pos(),
|
||||
nullptr, nullptr);
|
||||
if (!pn2)
|
||||
return null();
|
||||
@ -8357,7 +8355,7 @@ Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind)
|
||||
if (!tail)
|
||||
return null();
|
||||
|
||||
return handler.newForStatement(begin, head, tail, JSOP_ITER);
|
||||
return handler.newComprehensionFor(begin, head, tail);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
@ -339,6 +339,10 @@ class SyntaxParseHandler
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newComprehensionFor(uint32_t begin, Node forHead, Node body) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newForHead(ParseNodeKind kind, Node decls, Node lhs, Node rhs, const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user