зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1593247 - Fix WebAssembly Ion codegen for if/then without else r=luke
Differential Revision: https://phabricator.services.mozilla.com/D51404 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
ad704532b0
Коммит
8ea1934f15
|
@ -8783,7 +8783,7 @@ bool BaseCompiler::emitEnd() {
|
|||
LabelKind kind;
|
||||
ResultType type;
|
||||
NothingVector unused_values;
|
||||
if (!iter_.readEnd(&kind, &type, &unused_values)) {
|
||||
if (!iter_.readEnd(&kind, &type, &unused_values, &unused_values)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1836,7 +1836,8 @@ static bool EmitEnd(FunctionCompiler& f) {
|
|||
LabelKind kind;
|
||||
ResultType type;
|
||||
DefVector preJoinDefs;
|
||||
if (!f.iter().readEnd(&kind, &type, &preJoinDefs)) {
|
||||
DefVector resultsForEmptyElse;
|
||||
if (!f.iter().readEnd(&kind, &type, &preJoinDefs, &resultsForEmptyElse)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1866,17 +1867,22 @@ static bool EmitEnd(FunctionCompiler& f) {
|
|||
return false;
|
||||
}
|
||||
break;
|
||||
case LabelKind::Then:
|
||||
case LabelKind::Then: {
|
||||
// If we didn't see an Else, create a trivial else block so that we create
|
||||
// a diamond anyway, to preserve Ion invariants.
|
||||
if (!f.switchToElse(block, &block)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!f.pushDefs(resultsForEmptyElse)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!f.joinIfElse(block, &postJoinDefs)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LabelKind::Else:
|
||||
if (!f.joinIfElse(block, &postJoinDefs)) {
|
||||
return false;
|
||||
|
|
|
@ -595,7 +595,7 @@ class MOZ_STACK_CLASS OpIter : private Policy {
|
|||
const ModuleEnvironment& env_;
|
||||
|
||||
TypeAndValueStack valueStack_;
|
||||
TypeAndValueStack thenParamStack_;
|
||||
TypeAndValueStack elseParamStack_;
|
||||
ControlStack controlStack_;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -724,9 +724,10 @@ class MOZ_STACK_CLASS OpIter : private Policy {
|
|||
MOZ_MUST_USE bool readLoop(ResultType* paramType);
|
||||
MOZ_MUST_USE bool readIf(ResultType* paramType, Value* condition);
|
||||
MOZ_MUST_USE bool readElse(ResultType* paramType, ResultType* resultType,
|
||||
ValueVector* thenValues);
|
||||
ValueVector* thenResults);
|
||||
MOZ_MUST_USE bool readEnd(LabelKind* kind, ResultType* type,
|
||||
ValueVector* values);
|
||||
ValueVector* results,
|
||||
ValueVector* resultsForEmptyElse);
|
||||
void popEnd();
|
||||
MOZ_MUST_USE bool readBr(uint32_t* relativeDepth, ResultType* type,
|
||||
ValueVector* values);
|
||||
|
@ -1221,7 +1222,7 @@ inline void OpIter<Policy>::peekOp(OpBytes* op) {
|
|||
|
||||
template <typename Policy>
|
||||
inline bool OpIter<Policy>::readFunctionStart(uint32_t funcIndex) {
|
||||
MOZ_ASSERT(thenParamStack_.empty());
|
||||
MOZ_ASSERT(elseParamStack_.empty());
|
||||
MOZ_ASSERT(valueStack_.empty());
|
||||
MOZ_ASSERT(controlStack_.empty());
|
||||
MOZ_ASSERT(op_.b0 == uint16_t(Op::Limit));
|
||||
|
@ -1238,7 +1239,7 @@ inline bool OpIter<Policy>::readFunctionEnd(const uint8_t* bodyEnd) {
|
|||
if (!controlStack_.empty()) {
|
||||
return fail("unbalanced function body control flow");
|
||||
}
|
||||
MOZ_ASSERT(thenParamStack_.empty());
|
||||
MOZ_ASSERT(elseParamStack_.empty());
|
||||
|
||||
#ifdef DEBUG
|
||||
op_ = OpBytes(Op::Limit);
|
||||
|
@ -1307,13 +1308,13 @@ inline bool OpIter<Policy>::readIf(ResultType* paramType, Value* condition) {
|
|||
|
||||
*paramType = type.params();
|
||||
size_t paramsLength = type.params().length();
|
||||
return thenParamStack_.append(valueStack_.end() - paramsLength, paramsLength);
|
||||
return elseParamStack_.append(valueStack_.end() - paramsLength, paramsLength);
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline bool OpIter<Policy>::readElse(ResultType* paramType,
|
||||
ResultType* resultType,
|
||||
ValueVector* values) {
|
||||
ValueVector* thenResults) {
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::Else);
|
||||
|
||||
Control& block = controlStack_.back();
|
||||
|
@ -1322,19 +1323,16 @@ inline bool OpIter<Policy>::readElse(ResultType* paramType,
|
|||
}
|
||||
|
||||
*paramType = block.type().params();
|
||||
if (!checkStackAtEndOfBlock(resultType, values)) {
|
||||
if (!checkStackAtEndOfBlock(resultType, thenResults)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Restore to the entry state of the then block. Since the then block may
|
||||
// clobbered any value in the block's params, we must restore from a
|
||||
// snapshot.
|
||||
valueStack_.shrinkTo(block.valueStackBase());
|
||||
size_t thenParamsLength = block.type().params().length();
|
||||
MOZ_ASSERT(thenParamStack_.length() >= thenParamsLength);
|
||||
valueStack_.infallibleAppend(thenParamStack_.end() - thenParamsLength,
|
||||
thenParamsLength);
|
||||
thenParamStack_.shrinkBy(thenParamsLength);
|
||||
|
||||
size_t nparams = block.type().params().length();
|
||||
MOZ_ASSERT(elseParamStack_.length() >= nparams);
|
||||
valueStack_.infallibleAppend(elseParamStack_.end() - nparams, nparams);
|
||||
elseParamStack_.shrinkBy(nparams);
|
||||
|
||||
block.switchToElse();
|
||||
return true;
|
||||
|
@ -1342,22 +1340,35 @@ inline bool OpIter<Policy>::readElse(ResultType* paramType,
|
|||
|
||||
template <typename Policy>
|
||||
inline bool OpIter<Policy>::readEnd(LabelKind* kind, ResultType* type,
|
||||
ValueVector* values) {
|
||||
ValueVector* results,
|
||||
ValueVector* resultsForEmptyElse) {
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::End);
|
||||
|
||||
if (!checkStackAtEndOfBlock(type, values)) {
|
||||
if (!checkStackAtEndOfBlock(type, results)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Control& block = controlStack_.back();
|
||||
|
||||
// If an `if` block ends with `end` instead of `else`, then we must
|
||||
// additionally validate that the then-block doesn't push anything.
|
||||
if (block.kind() == LabelKind::Then) {
|
||||
if (block.type().params() != block.type().results()) {
|
||||
ResultType params = block.type().params();
|
||||
// If an `if` block ends with `end` instead of `else`, then the `else` block
|
||||
// implicitly passes the `if` parameters as the `else` results. In that
|
||||
// case, assert that the `if`'s param type matches the result type.
|
||||
if (params != block.type().results()) {
|
||||
return fail("if without else with a result value");
|
||||
}
|
||||
thenParamStack_.shrinkBy(block.type().params().length());
|
||||
|
||||
size_t nparams = params.length();
|
||||
MOZ_ASSERT(elseParamStack_.length() >= nparams);
|
||||
if (!resultsForEmptyElse->resize(nparams)) {
|
||||
return false;
|
||||
}
|
||||
const TypeAndValue* elseParams = elseParamStack_.end() - nparams;
|
||||
for (size_t i = 0; i < nparams; i++) {
|
||||
(*resultsForEmptyElse)[i] = elseParams[i].value();
|
||||
}
|
||||
elseParamStack_.shrinkBy(nparams);
|
||||
}
|
||||
|
||||
*kind = block.kind();
|
||||
|
|
|
@ -488,7 +488,7 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
|||
switch (op.b0) {
|
||||
case uint16_t(Op::End): {
|
||||
LabelKind unusedKind;
|
||||
if (!iter.readEnd(&unusedKind, &unusedType, ¬hings)) {
|
||||
if (!iter.readEnd(&unusedKind, &unusedType, ¬hings, ¬hings)) {
|
||||
return false;
|
||||
}
|
||||
iter.popEnd();
|
||||
|
|
Загрузка…
Ссылка в новой задаче