diff --git a/js/src/asmjs/WasmIonCompile.cpp b/js/src/asmjs/WasmIonCompile.cpp index e26e95c85032..69514ae99a8d 100644 --- a/js/src/asmjs/WasmIonCompile.cpp +++ b/js/src/asmjs/WasmIonCompile.cpp @@ -83,6 +83,8 @@ class FunctionCompiler const CompileInfo& info_; MIRGenerator& mirGen_; + MInstruction* dummyIns_; + MBasicBlock* curBlock_; CallVector callStack_; uint32_t maxStackArgBytes_; @@ -109,6 +111,7 @@ class FunctionCompiler graph_(mirGen.graph()), info_(mirGen.info()), mirGen_(mirGen), + dummyIns_(nullptr), curBlock_(nullptr), maxStackArgBytes_(0), loopDepth_(0), @@ -176,6 +179,9 @@ class FunctionCompiler return false; } + dummyIns_ = MConstant::NewAsmJS(alloc(), Int32Value(0), MIRType::Int32); + curBlock_->add(dummyIns_); + addInterruptCheck(); return true; @@ -964,24 +970,24 @@ class FunctionCompiler curBlock_->push(def); } - MDefinition* popDefIfPushed() + MDefinition* popDefIfPushed(bool shouldReturn = true) { if (!hasPushed(curBlock_)) return nullptr; MDefinition* def = curBlock_->pop(); - MOZ_ASSERT(def->type() != MIRType::Value); - return def; + MOZ_ASSERT_IF(def->type() == MIRType::Value, !shouldReturn); + return shouldReturn ? def : nullptr; } template - void ensurePushInvariants(const GetBlock& getBlock, size_t numBlocks) + bool ensurePushInvariants(const GetBlock& getBlock, size_t numBlocks) { // Preserve the invariant that, for every iterated MBasicBlock, either: // every MBasicBlock has a pushed expression with the same type (to - // prevent creating phis with type Value) OR no MBasicBlock has any + // prevent creating used phis with type Value) OR no MBasicBlock has any // pushed expression. This is required by MBasicBlock::addPredecessor. if (numBlocks < 2) - return; + return true; MBasicBlock* block = getBlock(0); @@ -997,10 +1003,12 @@ class FunctionCompiler if (!allPushed) { for (size_t i = 0; i < numBlocks; i++) { block = getBlock(i); - if (hasPushed(block)) - block->pop(); + if (!hasPushed(block)) + block->push(dummyIns_); } } + + return allPushed; } private: @@ -1071,7 +1079,7 @@ class FunctionCompiler blocks[numJoinPreds++] = elseJoinPred; auto getBlock = [&](size_t i) -> MBasicBlock* { return blocks[i]; }; - ensurePushInvariants(getBlock, numJoinPreds); + bool yieldsValue = ensurePushInvariants(getBlock, numJoinPreds); if (numJoinPreds == 0) { *def = nullptr; @@ -1087,7 +1095,7 @@ class FunctionCompiler } curBlock_ = join; - *def = popDefIfPushed(); + *def = popDefIfPushed(yieldsValue); } return true; @@ -1398,7 +1406,8 @@ class FunctionCompiler return patches[i].ins->block(); return curBlock_; }; - ensurePushInvariants(getBlock, patches.length() + !!curBlock_); + + bool yieldsValue = ensurePushInvariants(getBlock, patches.length() + !!curBlock_); MBasicBlock* join = nullptr; MControlInstruction* ins = patches[0].ins; @@ -1428,9 +1437,10 @@ class FunctionCompiler if (curBlock_ && !goToExistingBlock(curBlock_, join)) return false; + curBlock_ = join; - *def = popDefIfPushed(); + *def = popDefIfPushed(yieldsValue); patches.clear(); return true; diff --git a/js/src/jit-test/tests/wasm/random-control-flow.js b/js/src/jit-test/tests/wasm/random-control-flow.js index 1e61480d66b2..5e45676067d2 100644 --- a/js/src/jit-test/tests/wasm/random-control-flow.js +++ b/js/src/jit-test/tests/wasm/random-control-flow.js @@ -148,3 +148,22 @@ wasmEvalText(` ) ) `); + +wasmEvalText(` +(module + (func + (i32.add + (block $outer + (block $middle + (block $inner + (br_table $middle $outer $inner (i32.const 42) (i32.const 1)) + ) + (nop) + ) + (i32.const 0) + ) + (i32.const 13) + ) + ) +) +`);