mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1167823 - Remove dead code for checking whether a parse tree node has side effects. r=shu
This commit is contained in:
parent
053b0396c8
commit
7fce2ca1d6
@ -1904,9 +1904,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||||||
{
|
{
|
||||||
JS_CHECK_RECURSION(cx, return false);
|
JS_CHECK_RECURSION(cx, return false);
|
||||||
|
|
||||||
if (!pn || *answer)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
// Trivial cases with no side effects.
|
// Trivial cases with no side effects.
|
||||||
case PNK_NEWTARGET:
|
case PNK_NEWTARGET:
|
||||||
@ -2327,179 +2324,8 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||||||
MOZ_CRASH("invalid node kind");
|
MOZ_CRASH("invalid node kind");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pn->getArity()) {
|
MOZ_CRASH("invalid, unenumerated ParseNodeKind value encountered in "
|
||||||
case PN_CODE:
|
"BytecodeEmitter::checkSideEffects");
|
||||||
/*
|
|
||||||
* A named function, contrary to ES3, is no longer useful, because we
|
|
||||||
* bind its name lexically (using JSOP_CALLEE) instead of creating an
|
|
||||||
* Object instance and binding a readonly, permanent property in it
|
|
||||||
* (the object and binding can be detected and hijacked or captured).
|
|
||||||
* This is a bug fix to ES3; it is fixed in ES3.1 drafts.
|
|
||||||
*/
|
|
||||||
MOZ_ASSERT(*answer == false);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case PN_LIST:
|
|
||||||
if (pn->isOp(JSOP_NOP) || pn->isOp(JSOP_OR) || pn->isOp(JSOP_AND) ||
|
|
||||||
pn->isOp(JSOP_STRICTEQ) || pn->isOp(JSOP_STRICTNE)) {
|
|
||||||
/*
|
|
||||||
* Non-operators along with ||, &&, ===, and !== never invoke
|
|
||||||
* toString or valueOf.
|
|
||||||
*/
|
|
||||||
bool ok = true;
|
|
||||||
for (ParseNode* pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next)
|
|
||||||
ok &= checkSideEffects(pn2, answer);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pn->isKind(PNK_GENEXP)) {
|
|
||||||
/* Generator-expressions are harmless if the result is ignored. */
|
|
||||||
MOZ_ASSERT(*answer == false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* All invocation operations (construct: PNK_NEW, call: PNK_CALL)
|
|
||||||
* are presumed to be useful, because they may have side effects
|
|
||||||
* even if their main effect (their return value) is discarded.
|
|
||||||
*
|
|
||||||
* PNK_ELEM binary trees of 3+ nodes are flattened into lists to
|
|
||||||
* avoid too much recursion. All such lists must be presumed to be
|
|
||||||
* useful because each index operation could invoke a getter.
|
|
||||||
*
|
|
||||||
* Likewise, array and object initialisers may call prototype
|
|
||||||
* setters (the __defineSetter__ built-in, and writable __proto__
|
|
||||||
* on Array.prototype create this hazard). Initialiser list nodes
|
|
||||||
* have JSOP_NEWINIT in their pn_op.
|
|
||||||
*/
|
|
||||||
*answer = true;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case PN_TERNARY:
|
|
||||||
return checkSideEffects(pn->pn_kid1, answer) &&
|
|
||||||
checkSideEffects(pn->pn_kid2, answer) &&
|
|
||||||
checkSideEffects(pn->pn_kid3, answer);
|
|
||||||
|
|
||||||
case PN_BINARY:
|
|
||||||
case PN_BINARY_OBJ:
|
|
||||||
if (pn->isAssignment()) {
|
|
||||||
/*
|
|
||||||
* Assignment is presumed to be useful, even if the next operation
|
|
||||||
* is another assignment overwriting this one's ostensible effect,
|
|
||||||
* because the left operand may be a property with a setter that
|
|
||||||
* has side effects.
|
|
||||||
*
|
|
||||||
* The only exception is assignment of a useless value to a const
|
|
||||||
* declared in the function currently being compiled.
|
|
||||||
*/
|
|
||||||
ParseNode* pn2 = pn->pn_left;
|
|
||||||
if (!pn2->isKind(PNK_NAME)) {
|
|
||||||
*answer = true;
|
|
||||||
} else {
|
|
||||||
if (!bindNameToSlot(pn2))
|
|
||||||
return false;
|
|
||||||
if (!checkSideEffects(pn->pn_right, answer))
|
|
||||||
return false;
|
|
||||||
if (!*answer && (!pn->isOp(JSOP_NOP) || !pn2->isConst()))
|
|
||||||
*answer = true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(!pn->isOp(JSOP_OR), "|| produces a list now");
|
|
||||||
MOZ_ASSERT(!pn->isOp(JSOP_AND), "&& produces a list now");
|
|
||||||
MOZ_ASSERT(!pn->isOp(JSOP_STRICTEQ), "=== produces a list now");
|
|
||||||
MOZ_ASSERT(!pn->isOp(JSOP_STRICTNE), "!== produces a list now");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We can't easily prove that neither operand ever denotes an
|
|
||||||
* object with a toString or valueOf method.
|
|
||||||
*/
|
|
||||||
*answer = true;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case PN_UNARY:
|
|
||||||
switch (pn->getKind()) {
|
|
||||||
case PNK_DELETENAME: {
|
|
||||||
ParseNode* nameExpr = pn->pn_kid;
|
|
||||||
MOZ_ASSERT(nameExpr->isKind(PNK_NAME));
|
|
||||||
if (!bindNameToSlot(nameExpr))
|
|
||||||
return false;
|
|
||||||
*answer = !nameExpr->isConst();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PNK_DELETEPROP:
|
|
||||||
case PNK_DELETESUPERPROP:
|
|
||||||
case PNK_DELETEELEM:
|
|
||||||
case PNK_DELETESUPERELEM:
|
|
||||||
// All these delete addressing modes have effects, too.
|
|
||||||
*answer = true;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case PNK_DELETEEXPR:
|
|
||||||
return checkSideEffects(pn->pn_kid, answer);
|
|
||||||
|
|
||||||
case PNK_TYPEOFNAME:
|
|
||||||
case PNK_TYPEOFEXPR:
|
|
||||||
case PNK_VOID:
|
|
||||||
case PNK_NOT:
|
|
||||||
case PNK_BITNOT:
|
|
||||||
if (pn->isOp(JSOP_NOT)) {
|
|
||||||
/* ! does not convert its operand via toString or valueOf. */
|
|
||||||
return checkSideEffects(pn->pn_kid, answer);
|
|
||||||
}
|
|
||||||
/* FALL THROUGH */
|
|
||||||
|
|
||||||
default:
|
|
||||||
/*
|
|
||||||
* All of PNK_INC, PNK_DEC and PNK_THROW have direct effects. Of
|
|
||||||
* the remaining unary-arity node types, we can't easily prove that
|
|
||||||
* the operand never denotes an object with a toString or valueOf
|
|
||||||
* method.
|
|
||||||
*/
|
|
||||||
*answer = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
MOZ_CRASH("We have a returning default case");
|
|
||||||
|
|
||||||
case PN_NAME:
|
|
||||||
/*
|
|
||||||
* Take care to avoid trying to bind a label name (labels, both for
|
|
||||||
* statements and property values in object initialisers, have pn_op
|
|
||||||
* defaulted to JSOP_NOP).
|
|
||||||
*/
|
|
||||||
if (pn->isKind(PNK_NAME) && !pn->isOp(JSOP_NOP)) {
|
|
||||||
if (!bindNameToSlot(pn))
|
|
||||||
return false;
|
|
||||||
if (!pn->isOp(JSOP_CALLEE) && pn->pn_cookie.isFree()) {
|
|
||||||
/*
|
|
||||||
* Not a use of an unshadowed named function expression's given
|
|
||||||
* name, so this expression could invoke a getter that has side
|
|
||||||
* effects.
|
|
||||||
*/
|
|
||||||
*answer = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pn->isHoistedLexicalUse()) {
|
|
||||||
// Hoisted uses of lexical bindings throw on access.
|
|
||||||
*answer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pn->isKind(PNK_DOT)) {
|
|
||||||
/* Dotted property references in general can call getters. */
|
|
||||||
*answer = true;
|
|
||||||
}
|
|
||||||
return checkSideEffects(pn->maybeExpr(), answer);
|
|
||||||
|
|
||||||
case PN_NULLARY:
|
|
||||||
if (pn->isKind(PNK_DEBUGGER) ||
|
|
||||||
pn->isKind(PNK_SUPERPROP))
|
|
||||||
*answer = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
Loading…
Reference in New Issue
Block a user