1344477 - Part 1: Add JSOP_CALL_IGNORES_RV for function call that ignores return value.

This commit is contained in:
Gaming4JC 2019-07-14 19:04:34 -04:00 • committed by Roy Tam
commit 417aa02122
22 changed files with 243 additions and 92 deletions

View file

@ -4603,7 +4603,7 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
// If the expression is a literal, suppress line number emission so
// that debugging works more naturally.
if (caseValue) {
if (!emitTree(caseValue,
if (!emitTree(caseValue, ValueUsage::WantValue,
caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE))
{
return false;
@ -6652,7 +6652,7 @@ BytecodeEmitter::emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLi
}
// Line notes were updated by emitLexicalScope.
return emitTree(body, emitLineNote);
return emitTree(body, ValueUsage::WantValue, emitLineNote);
}
// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
@ -6754,9 +6754,9 @@ BytecodeEmitter::emitRequireObjectCoercible()
return false;
if (!emit2(JSOP_PICK, 2)) // VAL REQUIREOBJECTCOERCIBLE UNDEFINED VAL
return false;
if (!emitCall(JSOP_CALL, 1)) // VAL IGNORED
if (!emitCall(JSOP_CALL_IGNORES_RV, 1))// VAL IGNORED
return false;
checkTypeSet(JSOP_CALL);
checkTypeSet(JSOP_CALL_IGNORES_RV);
if (!emit1(JSOP_POP)) // VAL
return false;
@ -7276,12 +7276,14 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
// scope, but we still need to emit code for the initializers.)
if (!updateSourceCoordNotes(init->pn_pos.begin))
return false;
if (!emitTree(init))
return false;
if (!init->isForLoopDeclaration()) {
if (init->isForLoopDeclaration()) {
if (!emitTree(init))
return false;
} else {
// 'init' is an expression, not a declaration. emitTree left its
// value on the stack.
if (!emitTree(init, ValueUsage::IgnoreValue))
return false;
if (!emit1(JSOP_POP))
return false;
}
@ -7363,7 +7365,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
if (!updateSourceCoordNotes(update->pn_pos.begin))
return false;
if (!emitTree(update))
if (!emitTree(update, ValueUsage::IgnoreValue))
return false;
if (!emit1(JSOP_POP))
return false;
@ -8690,8 +8692,9 @@ BytecodeEmitter::emitStatement(ParseNode* pn)
if (useful) {
JSOp op = wantval ? JSOP_SETRVAL : JSOP_POP;
ValueUsage valueUsage = wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
MOZ_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP));
if (!emitTree(pn2))
if (!emitTree(pn2, valueUsage))
return false;
if (!emit1(op))
return false;
@ -9041,7 +9044,7 @@ BytecodeEmitter::emitOptimizeSpread(ParseNode* arg0, JumpList* jmp, bool* emitte
}
bool
BytecodeEmitter::emitCallOrNew(ParseNode* pn)
BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
{
bool callop = pn->isKind(PNK_CALL) || pn->isKind(PNK_TAGGED_TEMPLATE);
/*
@ -9220,13 +9223,20 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
}
if (!spread) {
if (!emitCall(pn->getOp(), argc, pn))
return false;
if (pn->getOp() == JSOP_CALL && valueUsage == ValueUsage::IgnoreValue) {
if (!emitCall(JSOP_CALL_IGNORES_RV, argc, pn))
return false;
checkTypeSet(JSOP_CALL_IGNORES_RV);
} else {
if (!emitCall(pn->getOp(), argc, pn))
return false;
checkTypeSet(pn->getOp());
}
} else {
if (!emit1(pn->getOp()))
return false;
checkTypeSet(pn->getOp());
}
checkTypeSet(pn->getOp());
if (pn->isOp(JSOP_EVAL) ||
pn->isOp(JSOP_STRICTEVAL) ||
pn->isOp(JSOP_SPREADEVAL) ||
@ -9324,12 +9334,13 @@ BytecodeEmitter::emitLogical(ParseNode* pn)
}
bool
BytecodeEmitter::emitSequenceExpr(ParseNode* pn)
BytecodeEmitter::emitSequenceExpr(ParseNode* pn,
ValueUsage valueUsage /* = ValueUsage::WantValue */)
{
for (ParseNode* child = pn->pn_head; ; child = child->pn_next) {
if (!updateSourceCoordNotes(child->pn_pos.begin))
return false;
if (!emitTree(child))
if (!emitTree(child, child->pn_next ? ValueUsage::IgnoreValue : valueUsage))
return false;
if (!child->pn_next)
break;
@ -9392,7 +9403,8 @@ BytecodeEmitter::emitLabeledStatement(const LabeledStatement* pn)
}
bool
BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional)
BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional,
ValueUsage valueUsage /* = ValueUsage::WantValue */)
{
/* Emit the condition, then branch if false to the else part. */
if (!emitTree(&conditional.condition()))
@ -9402,13 +9414,13 @@ BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional)
if (!ifThenElse.emitCond())
return false;
if (!emitTreeInBranch(&conditional.thenExpression()))
if (!emitTreeInBranch(&conditional.thenExpression(), valueUsage))
return false;
if (!ifThenElse.emitElse())
return false;
if (!emitTreeInBranch(&conditional.elseExpression()))
if (!emitTreeInBranch(&conditional.elseExpression(), valueUsage))
return false;
if (!ifThenElse.emitEnd())
@ -10289,7 +10301,8 @@ BytecodeEmitter::emitClass(ParseNode* pn)
}
bool
BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */)
{
JS_CHECK_RECURSION(cx, return false);
@ -10411,7 +10424,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
break;
case PNK_COMMA:
if (!emitSequenceExpr(pn))
if (!emitSequenceExpr(pn, valueUsage))
return false;
break;
@ -10433,7 +10446,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
break;
case PNK_CONDITIONAL:
if (!emitConditionalExpression(pn->as<ConditionalExpression>()))
if (!emitConditionalExpression(pn->as<ConditionalExpression>(), valueUsage))
return false;
break;
@ -10546,7 +10559,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
case PNK_CALL:
case PNK_GENEXP:
case PNK_SUPERCALL:
if (!emitCallOrNew(pn))
if (!emitCallOrNew(pn, valueUsage))
return false;
break;
@ -10704,12 +10717,13 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
}
bool
BytecodeEmitter::emitTreeInBranch(ParseNode* pn)
BytecodeEmitter::emitTreeInBranch(ParseNode* pn,
ValueUsage valueUsage /* = ValueUsage::WantValue */)
{
// Code that may be conditionally executed always need their own TDZ
// cache.
TDZCheckCache tdzCache(this);
return emitTree(pn);
return emitTree(pn, valueUsage);
}
static bool