Bug 1234702 - Part 1: Allow opt-in calls to content invoking spread opts in self-hosted code. (r=till)

This commit is contained in:
Eric Faust 2016-01-06 14:26:14 -08:00
parent f0aed3b4d8
commit 6f61ae17c2
3 changed files with 41 additions and 11 deletions

View File

@ -3972,9 +3972,9 @@ BytecodeEmitter::emitDestructuringLHS(ParseNode* target, VarEmitOption emitOptio
}
bool
BytecodeEmitter::emitIteratorNext(ParseNode* pn)
BytecodeEmitter::emitIteratorNext(ParseNode* pn, bool allowSelfHosted)
{
MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting,
MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
".next() iteration is prohibited in self-hosted code because it "
"can run user-modifiable iteration code");
@ -5514,7 +5514,7 @@ BytecodeEmitter::emitForInOrOfVariables(ParseNode* pn)
}
bool
BytecodeEmitter::emitForOf(StmtType type, ParseNode* pn)
BytecodeEmitter::emitForOf(StmtType type, ParseNode* pn, bool allowSelfHosted)
{
MOZ_ASSERT(type == StmtType::FOR_OF_LOOP || type == StmtType::SPREAD);
#ifdef DEBUG
@ -5623,7 +5623,7 @@ BytecodeEmitter::emitForOf(StmtType type, ParseNode* pn)
if (!emitDupAt(2)) // ITER ARR I ITER
return false;
}
if (!emitIteratorNext(forHead)) // ... RESULT
if (!emitIteratorNext(forHead, allowSelfHosted)) // ... RESULT
return false;
if (!emit1(JSOP_DUP)) // ... RESULT RESULT
return false;
@ -7269,6 +7269,18 @@ BytecodeEmitter::emitSelfHostedForceInterpreter(ParseNode* pn)
return true;
}
bool
BytecodeEmitter::emitSelfHostedAllowContentSpread(ParseNode* pn)
{
if (pn->pn_count != 2) {
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "allowContentSpread", "1", "");
return false;
}
// We're just here as a sentinel. Pass the value through directly.
return emitTree(pn->pn_head->pn_next);
}
bool
BytecodeEmitter::emitCallOrNew(ParseNode* pn)
{
@ -7317,6 +7329,8 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
return emitSelfHostedResumeGenerator(pn);
if (pn2->name() == cx->names().forceInterpreter)
return emitSelfHostedForceInterpreter(pn);
if (pn2->name() == cx->names().allowContentSpread)
return emitSelfHostedAllowContentSpread(pn);
// Fall through.
}
if (!emitNameOp(pn2, callop))
@ -7932,9 +7946,9 @@ BytecodeEmitter::emitArrayComp(ParseNode* pn)
}
bool
BytecodeEmitter::emitSpread()
BytecodeEmitter::emitSpread(bool allowSelfHosted)
{
return emitForOf(StmtType::SPREAD, nullptr);
return emitForOf(StmtType::SPREAD, nullptr, allowSelfHosted);
}
bool
@ -8024,11 +8038,25 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
}
if (!updateSourceCoordNotes(pn2->pn_pos.begin))
return false;
bool allowSelfHostedSpread = false;
if (pn2->isKind(PNK_ELISION)) {
if (!emit1(JSOP_HOLE))
return false;
} else {
ParseNode* expr = pn2->isKind(PNK_SPREAD) ? pn2->pn_kid : pn2;
ParseNode* expr;
if (pn2->isKind(PNK_SPREAD)) {
expr = pn2->pn_kid;
if (emitterMode == BytecodeEmitter::SelfHosting &&
expr->isKind(PNK_CALL) &&
expr->pn_head->name() == cx->names().allowContentSpread)
{
allowSelfHostedSpread = true;
}
} else {
expr = pn2;
}
if (!emitTree(expr)) // ARRAY INDEX? VALUE
return false;
}
@ -8039,7 +8067,7 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
return false;
if (!emit2(JSOP_PICK, 2)) // ITER ARRAY INDEX
return false;
if (!emitSpread()) // ARRAY INDEX
if (!emitSpread(allowSelfHostedSpread)) // ARRAY INDEX
return false;
} else if (afterSpread) {
if (!emit1(JSOP_INITELEM_INC))

View File

@ -577,7 +577,7 @@ struct BytecodeEmitter
// Pops iterator from the top of the stack. Pushes the result of |.next()|
// onto the stack.
bool emitIteratorNext(ParseNode* pn);
bool emitIteratorNext(ParseNode* pn, bool allowSelfHosted = false);
// Check if the value on top of the stack is "undefined". If so, replace
// that value on the stack with the value defined by |defaultExpr|.
@ -614,6 +614,7 @@ struct BytecodeEmitter
bool emitSelfHostedCallFunction(ParseNode* pn);
bool emitSelfHostedResumeGenerator(ParseNode* pn);
bool emitSelfHostedForceInterpreter(ParseNode* pn);
bool emitSelfHostedAllowContentSpread(ParseNode* pn);
bool emitComprehensionFor(ParseNode* compFor);
bool emitComprehensionForIn(ParseNode* pn);
@ -643,7 +644,7 @@ struct BytecodeEmitter
// |.next()| and put the results into the I-th element of array with
// incrementing I, then push the result I (it will be original I +
// iteration count). The stack after iteration will look like |ARRAY INDEX|.
bool emitSpread();
bool emitSpread(bool allowSelfHosted = false);
// 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.
@ -653,7 +654,7 @@ struct BytecodeEmitter
//
// Please refer the comment above emitSpread for additional information about
// stack convention.
bool emitForOf(StmtType type, ParseNode* pn);
bool emitForOf(StmtType type, ParseNode* pn, bool allowSelfHosted = false);
bool emitClass(ParseNode* pn);
bool emitSuperPropLHS(ParseNode* superBase, bool isCall = false);

View File

@ -13,6 +13,7 @@
#define FOR_EACH_COMMON_PROPERTYNAME(macro) \
macro(add, add, "add") \
macro(allowContentSpread, allowContentSpread, "allowContentSpread") \
macro(anonymous, anonymous, "anonymous") \
macro(Any, Any, "Any") \
macro(apply, apply, "apply") \