|
Lines 26-31
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec1
|
| 26 |
#include "config.h" |
26 |
#include "config.h" |
| 27 |
#include "BytecodeLivenessAnalysis.h" |
27 |
#include "BytecodeLivenessAnalysis.h" |
| 28 |
|
28 |
|
|
|
29 |
#include "BytecodeLivenessAnalysisInlines.h" |
| 29 |
#include "CodeBlock.h" |
30 |
#include "CodeBlock.h" |
| 30 |
#include "PreciseJumpTargets.h" |
31 |
#include "PreciseJumpTargets.h" |
| 31 |
|
32 |
|
|
Lines 38-81
BytecodeLivenessAnalysis::BytecodeLivene
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec2
|
| 38 |
compute(); |
39 |
compute(); |
| 39 |
} |
40 |
} |
| 40 |
|
41 |
|
| 41 |
static int numberOfCapturedVariables(CodeBlock* codeBlock) |
|
|
| 42 |
{ |
| 43 |
if (!codeBlock->symbolTable()) |
| 44 |
return 0; |
| 45 |
return codeBlock->symbolTable()->captureCount(); |
| 46 |
} |
| 47 |
|
| 48 |
static int captureStart(CodeBlock* codeBlock) |
| 49 |
{ |
| 50 |
if (!codeBlock->symbolTable()) |
| 51 |
return 0; |
| 52 |
return codeBlock->symbolTable()->captureStart(); |
| 53 |
} |
| 54 |
|
| 55 |
static int captureEnd(CodeBlock* codeBlock) |
| 56 |
{ |
| 57 |
if (!codeBlock->symbolTable()) |
| 58 |
return 0; |
| 59 |
return codeBlock->symbolTable()->captureEnd(); |
| 60 |
} |
| 61 |
|
| 62 |
static bool isValidRegisterForLiveness(CodeBlock* codeBlock, int operand) |
42 |
static bool isValidRegisterForLiveness(CodeBlock* codeBlock, int operand) |
| 63 |
{ |
43 |
{ |
| 64 |
VirtualRegister virtualReg(operand); |
44 |
VirtualRegister virtualReg(operand); |
| 65 |
return !codeBlock->isConstantRegisterIndex(operand) // Don't care about constants. |
45 |
return !codeBlock->isConstantRegisterIndex(operand) // Don't care about constants. |
| 66 |
&& virtualReg.isLocal() // Don't care about arguments. |
46 |
&& virtualReg.isLocal() // Don't care about arguments. |
| 67 |
&& (!numberOfCapturedVariables(codeBlock) // If we have no captured variables, we're good to go. |
47 |
&& (!codeBlock->captureCount() // If we have no captured variables, we're good to go. |
| 68 |
|| (virtualReg.offset() > captureStart(codeBlock) || (virtualReg.offset() <= captureEnd(codeBlock)))); |
48 |
|| (virtualReg.offset() > codeBlock->captureStart() || (virtualReg.offset() <= codeBlock->captureEnd()))); |
| 69 |
} |
49 |
} |
| 70 |
|
50 |
|
| 71 |
static void setForOperand(CodeBlock* codeBlock, FastBitVector& bits, int operand) |
51 |
static void setForOperand(CodeBlock* codeBlock, FastBitVector& bits, int operand) |
| 72 |
{ |
52 |
{ |
| 73 |
ASSERT(isValidRegisterForLiveness(codeBlock, operand)); |
53 |
ASSERT(isValidRegisterForLiveness(codeBlock, operand)); |
| 74 |
VirtualRegister virtualReg(operand); |
54 |
VirtualRegister virtualReg(operand); |
| 75 |
if (virtualReg.offset() > captureStart(codeBlock)) |
55 |
if (virtualReg.offset() > codeBlock->captureStart()) |
| 76 |
bits.set(virtualReg.toLocal()); |
56 |
bits.set(virtualReg.toLocal()); |
| 77 |
else |
57 |
else |
| 78 |
bits.set(virtualReg.toLocal() - numberOfCapturedVariables(codeBlock)); |
58 |
bits.set(virtualReg.toLocal() - codeBlock->captureCount()); |
| 79 |
} |
59 |
} |
| 80 |
|
60 |
|
| 81 |
static void computeUsesForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& uses) |
61 |
static void computeUsesForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& uses) |
|
Lines 533-538
static BytecodeBasicBlock* findBasicBloc
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec3
|
| 533 |
return basicBlock[1].get(); |
513 |
return basicBlock[1].get(); |
| 534 |
} |
514 |
} |
| 535 |
|
515 |
|
|
|
516 |
static void stepOverInstruction(CodeBlock* codeBlock, Vector<RefPtr<BytecodeBasicBlock>>& basicBlocks, unsigned bytecodeOffset, FastBitVector& uses, FastBitVector& defs, FastBitVector& out) |
| 517 |
{ |
| 518 |
uses.clearAll(); |
| 519 |
defs.clearAll(); |
| 520 |
|
| 521 |
computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, uses); |
| 522 |
computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, defs); |
| 523 |
|
| 524 |
out.exclude(defs); |
| 525 |
out.merge(uses); |
| 526 |
|
| 527 |
// If we have an exception handler, we want the live-in variables of the |
| 528 |
// exception handler block to be included in the live-in of this particular bytecode. |
| 529 |
if ((handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) { |
| 530 |
BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler->target); |
| 531 |
ASSERT(handlerBlock); |
| 532 |
out.merge(handlerBlock->in()); |
| 533 |
} |
| 534 |
} |
| 535 |
|
| 536 |
static void computeLocalLivenessForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector<RefPtr<BytecodeBasicBlock> >& basicBlocks, unsigned targetOffset, FastBitVector& result) |
536 |
static void computeLocalLivenessForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector<RefPtr<BytecodeBasicBlock> >& basicBlocks, unsigned targetOffset, FastBitVector& result) |
| 537 |
{ |
537 |
{ |
| 538 |
ASSERT(!block->isExitBlock()); |
538 |
ASSERT(!block->isExitBlock()); |
|
Lines 550-572
static void computeLocalLivenessForBytec
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec4
|
| 550 |
unsigned bytecodeOffset = block->bytecodeOffsets()[i]; |
550 |
unsigned bytecodeOffset = block->bytecodeOffsets()[i]; |
| 551 |
if (targetOffset > bytecodeOffset) |
551 |
if (targetOffset > bytecodeOffset) |
| 552 |
break; |
552 |
break; |
| 553 |
|
553 |
|
| 554 |
uses.clearAll(); |
554 |
stepOverInstruction(codeBlock, basicBlocks, bytecodeOffset, uses, defs, out); |
| 555 |
defs.clearAll(); |
|
|
| 556 |
|
| 557 |
computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, uses); |
| 558 |
computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, defs); |
| 559 |
|
| 560 |
out.exclude(defs); |
| 561 |
out.merge(uses); |
| 562 |
|
| 563 |
// If we have an exception handler, we want the live-in variables of the |
| 564 |
// exception handler block to be included in the live-in of this particular bytecode. |
| 565 |
if ((handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) { |
| 566 |
BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler->target); |
| 567 |
ASSERT(handlerBlock); |
| 568 |
out.merge(handlerBlock->in()); |
| 569 |
} |
| 570 |
} |
555 |
} |
| 571 |
|
556 |
|
| 572 |
result.set(out); |
557 |
result.set(out); |
|
Lines 583-589
void BytecodeLivenessAnalysis::runLivene
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec5
|
| 583 |
{ |
568 |
{ |
| 584 |
UnlinkedCodeBlock* unlinkedCodeBlock = m_codeBlock->unlinkedCodeBlock(); |
569 |
UnlinkedCodeBlock* unlinkedCodeBlock = m_codeBlock->unlinkedCodeBlock(); |
| 585 |
unsigned numberOfVariables = unlinkedCodeBlock->m_numVars + |
570 |
unsigned numberOfVariables = unlinkedCodeBlock->m_numVars + |
| 586 |
unlinkedCodeBlock->m_numCalleeRegisters - numberOfCapturedVariables(m_codeBlock); |
571 |
unlinkedCodeBlock->m_numCalleeRegisters - m_codeBlock->captureCount(); |
| 587 |
|
572 |
|
| 588 |
for (unsigned i = 0; i < m_basicBlocks.size(); i++) { |
573 |
for (unsigned i = 0; i < m_basicBlocks.size(); i++) { |
| 589 |
BytecodeBasicBlock* block = m_basicBlocks[i].get(); |
574 |
BytecodeBasicBlock* block = m_basicBlocks[i].get(); |
|
Lines 622-657
void BytecodeLivenessAnalysis::getLivene
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec6
|
| 622 |
|
607 |
|
| 623 |
bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset) |
608 |
bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset) |
| 624 |
{ |
609 |
{ |
| 625 |
int numCapturedVars = numberOfCapturedVariables(m_codeBlock); |
610 |
if (operandIsAlwaysLive(m_codeBlock, operand)) |
| 626 |
if (VirtualRegister(operand).isArgument()) |
|
|
| 627 |
return true; |
| 628 |
if (operand <= captureStart(m_codeBlock) && operand > captureEnd(m_codeBlock)) |
| 629 |
return true; |
611 |
return true; |
| 630 |
FastBitVector result; |
612 |
FastBitVector result; |
| 631 |
getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, result); |
613 |
getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, result); |
| 632 |
return result.get(operand - numCapturedVars); |
614 |
return operandThatIsNotAlwaysLiveIsLive(m_codeBlock, result, operand); |
| 633 |
} |
615 |
} |
| 634 |
|
616 |
|
| 635 |
FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset) |
617 |
FastBitVector getLivenessInfo(CodeBlock* codeBlock, const FastBitVector& out) |
| 636 |
{ |
618 |
{ |
| 637 |
FastBitVector temp; |
|
|
| 638 |
FastBitVector result; |
619 |
FastBitVector result; |
| 639 |
|
620 |
|
| 640 |
getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, temp); |
621 |
unsigned numCapturedVars = m_codeBlock->captureCount(); |
| 641 |
|
|
|
| 642 |
unsigned numCapturedVars = numberOfCapturedVariables(m_codeBlock); |
| 643 |
if (numCapturedVars) { |
622 |
if (numCapturedVars) { |
| 644 |
int firstCapturedLocal = VirtualRegister(captureStart(m_codeBlock)).toLocal(); |
623 |
int firstCapturedLocal = VirtualRegister(m_codeBlock->captureStart()).toLocal(); |
| 645 |
result.resize(temp.numBits() + numCapturedVars); |
624 |
result.resize(out.numBits() + numCapturedVars); |
| 646 |
for (unsigned i = 0; i < numCapturedVars; ++i) |
625 |
for (unsigned i = 0; i < numCapturedVars; ++i) |
| 647 |
result.set(firstCapturedLocal + i); |
626 |
result.set(firstCapturedLocal + i); |
| 648 |
} else |
627 |
} else |
| 649 |
result.resize(temp.numBits()); |
628 |
result.resize(out.numBits()); |
| 650 |
|
629 |
|
| 651 |
int tempLength = temp.numBits(); |
630 |
int outLength = out.numBits(); |
| 652 |
ASSERT(tempLength >= 0); |
631 |
ASSERT(outLength >= 0); |
| 653 |
for (int i = 0; i < tempLength; i++) { |
632 |
for (int i = 0; i < outLength; i++) { |
| 654 |
if (!temp.get(i)) |
633 |
if (!out.get(i)) |
| 655 |
continue; |
634 |
continue; |
| 656 |
|
635 |
|
| 657 |
if (!numCapturedVars) { |
636 |
if (!numCapturedVars) { |
|
Lines 659-665
FastBitVector BytecodeLivenessAnalysis::
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec7
|
| 659 |
continue; |
638 |
continue; |
| 660 |
} |
639 |
} |
| 661 |
|
640 |
|
| 662 |
if (virtualRegisterForLocal(i).offset() > captureStart(m_codeBlock)) |
641 |
if (virtualRegisterForLocal(i).offset() > m_codeBlock->captureStart()) |
| 663 |
result.set(i); |
642 |
result.set(i); |
| 664 |
else |
643 |
else |
| 665 |
result.set(numCapturedVars + i); |
644 |
result.set(numCapturedVars + i); |
|
Lines 667-672
FastBitVector BytecodeLivenessAnalysis::
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec8
|
| 667 |
return result; |
646 |
return result; |
| 668 |
} |
647 |
} |
| 669 |
|
648 |
|
|
|
649 |
FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset) |
| 650 |
{ |
| 651 |
FastBitVector out; |
| 652 |
getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, out); |
| 653 |
return getLivenessInfo(m_codeBlock, out); |
| 654 |
} |
| 655 |
|
| 670 |
void BytecodeLivenessAnalysis::dumpResults() |
656 |
void BytecodeLivenessAnalysis::dumpResults() |
| 671 |
{ |
657 |
{ |
| 672 |
Interpreter* interpreter = m_codeBlock->vm()->interpreter; |
658 |
Interpreter* interpreter = m_codeBlock->vm()->interpreter; |