bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset) { if (operandIsAlwaysLive(operand)) return true; FastBitVector result; getLivenessInfoAtBytecodeOffset(bytecodeOffset, result); return operandThatIsNotAlwaysLiveIsLive(result, operand); }
void run() { // Perform modified liveness analysis to determine which locals are live at the merge points. // This produces the conservative results for the question, "which variables should be saved and resumed?". runLivenessFixpoint(m_generatorification.graph()); for (YieldData& data : m_generatorification.yields()) data.liveness = getLivenessInfoAtBytecodeOffset(m_generatorification.graph(), data.point + opcodeLength(op_yield)); }
void run(UnlinkedCodeBlock* codeBlock, InstructionStreamWriter& instructions) { // Perform modified liveness analysis to determine which locals are live at the merge points. // This produces the conservative results for the question, "which variables should be saved and resumed?". runLivenessFixpoint(codeBlock, instructions, m_generatorification.graph()); for (YieldData& data : m_generatorification.yields()) data.liveness = getLivenessInfoAtBytecodeOffset(codeBlock, instructions, m_generatorification.graph(), m_generatorification.instructions().at(data.point).next().offset()); }
void BytecodeLivenessAnalysis::dumpResults() { Interpreter* interpreter = m_codeBlock->vm()->interpreter; Instruction* instructionsBegin = m_codeBlock->instructions().begin(); for (unsigned i = 0; i < m_basicBlocks.size(); i++) { BytecodeBasicBlock* block = m_basicBlocks[i].get(); dataLogF("\nBytecode basic block %u: %p (offset: %u, length: %u)\n", i, block, block->leaderBytecodeOffset(), block->totalBytecodeLength()); dataLogF("Predecessors: "); for (unsigned j = 0; j < block->predecessors().size(); j++) { BytecodeBasicBlock* predecessor = block->predecessors()[j]; dataLogF("%p ", predecessor); } dataLogF("\n"); dataLogF("Successors: "); for (unsigned j = 0; j < block->successors().size(); j++) { BytecodeBasicBlock* successor = block->successors()[j]; dataLogF("%p ", successor); } dataLogF("\n"); if (block->isEntryBlock()) { dataLogF("Entry block %p\n", block); continue; } if (block->isExitBlock()) { dataLogF("Exit block: %p\n", block); continue; } for (unsigned bytecodeOffset = block->leaderBytecodeOffset(); bytecodeOffset < block->leaderBytecodeOffset() + block->totalBytecodeLength();) { const Instruction* currentInstruction = &instructionsBegin[bytecodeOffset]; dataLogF("Live variables: "); FastBitVector liveBefore = getLivenessInfoAtBytecodeOffset(bytecodeOffset); for (unsigned j = 0; j < liveBefore.numBits(); j++) { if (liveBefore.get(j)) dataLogF("%u ", j); } dataLogF("\n"); m_codeBlock->dumpBytecode(WTF::dataFile(), m_codeBlock->globalObject()->globalExec(), instructionsBegin, currentInstruction); OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); unsigned opcodeLength = opcodeLengths[opcodeID]; bytecodeOffset += opcodeLength; } dataLogF("Live variables: "); FastBitVector liveAfter = block->out(); for (unsigned j = 0; j < liveAfter.numBits(); j++) { if (liveAfter.get(j)) dataLogF("%u ", j); } dataLogF("\n"); } }
FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset) { FastBitVector out; getLivenessInfoAtBytecodeOffset(bytecodeOffset, out); return out; }