diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index 816e0a17519..b2cfa2cef9e 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -3482,7 +3482,9 @@ MakeLoopContiguous(MIRGraph &graph, MBasicBlock *header, size_t numMarked) size_t headerId = header->id(); size_t inLoopId = headerId; size_t notInLoopId = inLoopId + numMarked; + size_t numOSRDominated = 0; ReversePostorderIterator i = graph.rpoBegin(header); + MBasicBlock *osrBlock = graph.osrBlock(); for (;;) { MBasicBlock *block = *i++; MOZ_ASSERT(block->id() >= header->id() && block->id() <= backedge->id(), @@ -3495,6 +3497,15 @@ MakeLoopContiguous(MIRGraph &graph, MBasicBlock *header, size_t numMarked) // If we've reached the loop backedge, we're done! if (block == backedge) break; + } else if (osrBlock && osrBlock->dominates(block)) { + // This block is not in the loop, but since it's dominated by the + // OSR entry, the block was probably in the loop before some + // folding. This probably means that the block has outgoing paths + // which re-enter the loop in the middle. And that, finally, means + // that we can't move this block to the end, since it could create a + // backwards branch to a block which is not the loop header. + block->setId(inLoopId++); + ++numOSRDominated; } else { // This block is not in the loop. Move it to the end. graph.moveBlockBefore(insertPt, block); @@ -3502,8 +3513,11 @@ MakeLoopContiguous(MIRGraph &graph, MBasicBlock *header, size_t numMarked) } } MOZ_ASSERT(header->id() == headerId, "Loop header id changed"); - MOZ_ASSERT(inLoopId == headerId + numMarked, "Wrong number of blocks kept in loop"); - MOZ_ASSERT(notInLoopId == (insertIter != graph.rpoEnd() ? insertPt->id() : graph.numBlocks()), + MOZ_ASSERT(inLoopId == headerId + numMarked + numOSRDominated, + "Wrong number of blocks kept in loop"); + MOZ_ASSERT(notInLoopId == (insertIter != graph.rpoEnd() + ? insertPt->id() + : graph.numBlocks()) - numOSRDominated, "Wrong number of blocks moved out of loop"); }