FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset) { FastBitVector temp; FastBitVector result; getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, temp); unsigned numCapturedVars = numberOfCapturedVariables(m_codeBlock); if (numCapturedVars) { int firstCapturedLocal = VirtualRegister(captureStart(m_codeBlock)).toLocal(); result.resize(temp.numBits() + numCapturedVars); for (unsigned i = 0; i < numCapturedVars; ++i) result.set(firstCapturedLocal + i); } else result.resize(temp.numBits()); int tempLength = temp.numBits(); ASSERT(tempLength >= 0); for (int i = 0; i < tempLength; i++) { if (!temp.get(i)) continue; if (!numCapturedVars) { result.set(i); continue; } if (virtualRegisterForLocal(i).offset() > captureStart(m_codeBlock)) result.set(i); else result.set(numCapturedVars + i); } return result; }
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"); } }
static void computeLocalLivenessForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector<RefPtr<BytecodeBasicBlock> >& basicBlocks, unsigned targetOffset, FastBitVector& result) { ASSERT(!block->isExitBlock()); ASSERT(!block->isEntryBlock()); FastBitVector out = block->out(); HandlerInfo* handler = 0; FastBitVector uses; FastBitVector defs; uses.resize(out.numBits()); defs.resize(out.numBits()); for (int i = block->bytecodeOffsets().size() - 1; i >= 0; i--) { unsigned bytecodeOffset = block->bytecodeOffsets()[i]; if (targetOffset > bytecodeOffset) break; uses.clearAll(); defs.clearAll(); computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, uses); computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, defs); out.exclude(defs); out.merge(uses); // If we have an exception handler, we want the live-in variables of the // exception handler block to be included in the live-in of this particular bytecode. if ((handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) { BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler->target); ASSERT(handlerBlock); out.merge(handlerBlock->in()); } } result.set(out); }