зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1167823 - Handle various nullary/unary nodes in BytecodeEmitter::checkSideEffects. r=shu
--HG-- extra : rebase_source : 28fac27fda1ffe5ffb16fc534bef2397fea3a9b5
This commit is contained in:
Родитель
f58d959d94
Коммит
71384eabcb
|
@ -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:
|
||||
|
|
Загрузка…
Ссылка в новой задаче