bool run() { ASSERT(m_graph.m_form != SSA); BlockSet blocksThatNeedInvalidationPoints; for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { BasicBlock* block = m_graph.block(blockIndex); if (!block) continue; for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) handle(nodeIndex, block->at(nodeIndex)); // Note: this assumes that control flow occurs at bytecode instruction boundaries. if (m_originThatHadFire.isSet()) { for (unsigned i = block->numSuccessors(); i--;) blocksThatNeedInvalidationPoints.add(block->successor(i)); } m_insertionSet.execute(block); } for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { BasicBlock* block = m_graph.block(blockIndex); if (!blocksThatNeedInvalidationPoints.contains(block)) continue; insertInvalidationCheck(0, block->at(0)); m_insertionSet.execute(block); } return true; }
bool isValidFlushLocation(BasicBlock* startingBlock, unsigned index, VirtualRegister operand) { // This code is not meant to be fast. We just use it for assertions. If we got liveness wrong, // this function would return false for a Flush that we insert. Vector<BasicBlock*, 4> worklist; BlockSet seen; auto addPredecessors = [&] (BasicBlock* block) { for (BasicBlock* predecessor : block->predecessors) { bool isNewEntry = seen.add(predecessor); if (isNewEntry) worklist.append(predecessor); } }; auto flushIsDefinitelyInvalid = [&] (BasicBlock* block, unsigned index) { bool allGood = false; for (unsigned i = index; i--; ) { if (block->at(i)->accessesStack(m_graph) && block->at(i)->local() == operand) { allGood = true; break; } } if (allGood) return false; if (block->predecessors.isEmpty()) { // This is a root block. We proved we reached here, therefore we can't Flush, as // it'll make this local live at the start of a root block, which is invalid IR. return true; } addPredecessors(block); return false; }; if (flushIsDefinitelyInvalid(startingBlock, index)) return false; while (!worklist.isEmpty()) { BasicBlock* block = worklist.takeLast(); if (flushIsDefinitelyInvalid(block, block->size())) return false; } return true; }