Bug 1167823 - Handle various nullary/unary nodes in BytecodeEmitter::checkSideEffects. r=shu

--HG--
extra : rebase_source : 28fac27fda1ffe5ffb16fc534bef2397fea3a9b5
This commit is contained in:
Jeff Walden 2015-03-04 13:21:30 -08:00
Родитель f58d959d94
Коммит 71384eabcb
1 изменённых файлов: 85 добавлений и 21 удалений

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

@ -1902,10 +1902,13 @@ BytecodeEmitter::bindNameToSlot(ParseNode* pn)
bool
BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
{
JS_CHECK_RECURSION(cx, return false);
if (!pn || *answer)
return true;
switch (pn->getKind()) {
// Trivial cases with no side effects.
case PNK_NEWTARGET:
case PNK_NOP:
case PNK_STRING:
@ -1918,38 +1921,99 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
case PNK_ELISION:
case PNK_GENERATOR:
case PNK_NUMBER:
case PNK_BREAK:
case PNK_CONTINUE:
case PNK_DEBUGGER:
case PNK_EXPORT_BATCH_SPEC:
case PNK_EXPORT_DEFAULT:
case PNK_OBJECT_PROPERTY_NAME:
case PNK_SUPERPROP:
case PNK_FRESHENBLOCK:
case PNK_TYPEOFNAME:
MOZ_ASSERT(pn->isArity(PN_NULLARY));
*answer = false;
return true;
case PNK_DEBUGGER:
MOZ_ASSERT(pn->isArity(PN_NULLARY));
*answer = true;
return true;
// Unary cases with side effects only if the child has them.
case PNK_TYPEOFEXPR:
case PNK_VOID:
case PNK_NOT:
case PNK_BITNOT:
case PNK_COMPUTED_NAME:
MOZ_ASSERT(pn->isArity(PN_UNARY));
return checkSideEffects(pn->pn_kid, answer);
// Looking up or evaluating the associated name could throw.
case PNK_TYPEOFNAME:
MOZ_ASSERT(pn->isArity(PN_UNARY));
*answer = true;
return true;
// These unary cases have side effects on the enclosing object/array,
// sure. But that's not the question this function answers: it's
// whether the operation may have a side effect on something *other* than
// the result of the overall operation in which it's embedded. The
// answer to that is no, for an object literal having a mutated prototype
// and an array comprehension containing no other effectful operations
// only produce a value, without affecting anything else.
case PNK_MUTATEPROTO:
case PNK_ARRAYPUSH:
MOZ_ASSERT(pn->isArity(PN_UNARY));
return checkSideEffects(pn->pn_kid, answer);
// Unary cases with obvious side effects.
case PNK_PREINCREMENT:
case PNK_POSTINCREMENT:
case PNK_PREDECREMENT:
case PNK_POSTDECREMENT:
case PNK_THROW:
MOZ_ASSERT(pn->isArity(PN_UNARY));
*answer = true;
return true;
// These might invoke valueOf/toString, even with a subexpression without
// side effects! Consider |+{ valueOf: null, toString: null }|.
case PNK_BITNOT:
case PNK_POS:
case PNK_NEG:
MOZ_ASSERT(pn->isArity(PN_UNARY));
*answer = true;
return true;
// This invokes the (user-controllable) iterator protocol.
case PNK_SPREAD:
MOZ_ASSERT(pn->isArity(PN_UNARY));
*answer = true;
return true;
// Deletion generally has side effects, even if isolated cases have none.
case PNK_DELETENAME:
case PNK_DELETEPROP:
case PNK_DELETESUPERPROP:
case PNK_DELETEELEM:
case PNK_DELETESUPERELEM:
case PNK_DELETEEXPR:
case PNK_POS:
case PNK_NEG:
case PNK_PREINCREMENT:
case PNK_POSTINCREMENT:
case PNK_PREDECREMENT:
case PNK_POSTDECREMENT:
case PNK_COMPUTED_NAME:
case PNK_ARRAYPUSH:
case PNK_SPREAD:
case PNK_MUTATEPROTO:
case PNK_EXPORT:
MOZ_ASSERT(pn->isArity(PN_UNARY));
*answer = true;
return true;
// Deletion of a non-Reference expression has side effects only through
// evaluating the expression.
case PNK_DELETEEXPR: {
MOZ_ASSERT(pn->isArity(PN_UNARY));
ParseNode* expr = pn->pn_kid;
return checkSideEffects(expr, answer);
}
case PNK_SEMI:
MOZ_ASSERT(pn->isArity(PN_UNARY));
if (ParseNode* expr = pn->pn_kid)
return checkSideEffects(expr, answer);
*answer = false;
return true;
case PNK_SUPERPROP:
case PNK_BREAK:
case PNK_CONTINUE:
case PNK_EXPORT_BATCH_SPEC:
case PNK_FRESHENBLOCK:
case PNK_EXPORT:
case PNK_EXPORT_DEFAULT:
case PNK_ASSIGN:
case PNK_ADDASSIGN:
case PNK_SUBASSIGN: