// OSR fixups serve the purpose of representing the non-OSR entry into a loop // when the only real entry is an OSR entry into the middle. However, if the // entry into the middle is subsequently folded away, the loop may actually // have become unreachable. Mark-and-sweep all blocks to remove all such code. bool ValueNumberer::cleanupOSRFixups() { // Mark. Vector<MBasicBlock*, 0, JitAllocPolicy> worklist(graph_.alloc()); unsigned numMarked = 2; graph_.entryBlock()->mark(); graph_.osrBlock()->mark(); if (!worklist.append(graph_.entryBlock()) || !worklist.append(graph_.osrBlock())) return false; while (!worklist.empty()) { MBasicBlock* block = worklist.popCopy(); for (size_t i = 0, e = block->numSuccessors(); i != e; ++i) { MBasicBlock* succ = block->getSuccessor(i); if (!succ->isMarked()) { ++numMarked; succ->mark(); if (!worklist.append(succ)) return false; } else if (succ->isLoopHeader() && succ->loopPredecessor() == block && succ->numPredecessors() == 3) { // Unmark fixup blocks if the loop predecessor is marked after // the loop header. succ->getPredecessor(1)->unmarkUnchecked(); } } // OSR fixup blocks are needed if and only if the loop header is // reachable from its backedge (via the OSR block) and not from its // original loop predecessor. // // Thus OSR fixup blocks are removed if the loop header is not // reachable, or if the loop header is reachable from both its backedge // and its original loop predecessor. if (block->isLoopHeader()) { MBasicBlock* maybeFixupBlock = nullptr; if (block->numPredecessors() == 2) { maybeFixupBlock = block->getPredecessor(0); } else { MOZ_ASSERT(block->numPredecessors() == 3); if (!block->loopPredecessor()->isMarked()) maybeFixupBlock = block->getPredecessor(1); } if (maybeFixupBlock && !maybeFixupBlock->isMarked() && maybeFixupBlock->numPredecessors() == 0) { MOZ_ASSERT(maybeFixupBlock->numSuccessors() == 1, "OSR fixup block should have exactly one successor"); MOZ_ASSERT(maybeFixupBlock != graph_.entryBlock(), "OSR fixup block shouldn't be the entry block"); MOZ_ASSERT(maybeFixupBlock != graph_.osrBlock(), "OSR fixup block shouldn't be the OSR entry block"); maybeFixupBlock->mark(); } } } // And sweep. return RemoveUnmarkedBlocks(mir_, graph_, numMarked); }