Changeset 224138 in webkit


Ignore:
Timestamp:
Oct 27, 2017 6:03:22 PM (6 years ago)
Author:
sbarati@apple.com
Message:

Bytecode liveness should live on UnlinkedCodeBlock so it can be shared amongst CodeBlocks
https://bugs.webkit.org/show_bug.cgi?id=178949

Reviewed by Keith Miller.

This patch stores BytecodeLiveness on UnlinkedCodeBlock instead of CodeBlock
so that we don't need to recompute liveness for the same UnlinkedCodeBlock
more than once. To do this, this patch solidifies the invariant that CodeBlock
linking can't do anything that would change the result of liveness. For example,
it can't introduce new locals. This invariant was met my JSC before, because we
didn't do anything in bytecode linking that would change liveness. However, it is
now a correctness requirement that we don't do anything that would change the
result of running liveness. To support this change, I've refactored BytecodeGraph
to not be tied to a CodeBlockType*. Things that perform liveness will pass in
CodeBlockType* and the instruction stream as needed. This means that we may
compute liveness with one CodeBlock*'s instruction stream, and then perform
queries on that analysis with a different CodeBlock*'s instruction stream.

This seems to be a 2% JSBench progression.

  • bytecode/BytecodeGeneratorification.cpp:

(JSC::BytecodeGeneratorification::BytecodeGeneratorification):
(JSC::BytecodeGeneratorification::graph):
(JSC::BytecodeGeneratorification::storageForGeneratorLocal):
(JSC::GeneratorLivenessAnalysis::run):
(JSC::BytecodeGeneratorification::run):

  • bytecode/BytecodeGraph.h:

(JSC::BytecodeGraph::BytecodeGraph):
(JSC::BytecodeGraph::codeBlock const): Deleted.
(JSC::BytecodeGraph::instructions): Deleted.
(JSC::BytecodeGraph<Block>::BytecodeGraph): Deleted.

  • bytecode/BytecodeLivenessAnalysis.cpp:

(JSC::BytecodeLivenessAnalysis::BytecodeLivenessAnalysis):
(JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset):
(JSC::BytecodeLivenessAnalysis::computeFullLiveness):
(JSC::BytecodeLivenessAnalysis::computeKills):
(JSC::BytecodeLivenessAnalysis::dumpResults):
(JSC::BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset): Deleted.
(JSC::BytecodeLivenessAnalysis::compute): Deleted.

  • bytecode/BytecodeLivenessAnalysis.h:
  • bytecode/BytecodeLivenessAnalysisInlines.h:

(JSC::BytecodeLivenessPropagation::stepOverInstruction):
(JSC::BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset):
(JSC::BytecodeLivenessPropagation::computeLocalLivenessForBlock):
(JSC::BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset):
(JSC::BytecodeLivenessPropagation::runLivenessFixpoint):

  • bytecode/BytecodeRewriter.cpp:

(JSC::BytecodeRewriter::applyModification):
(JSC::BytecodeRewriter::execute):
(JSC::BytecodeRewriter::adjustJumpTargetsInFragment):

  • bytecode/BytecodeRewriter.h:

(JSC::BytecodeRewriter::BytecodeRewriter):
(JSC::BytecodeRewriter::removeBytecode):
(JSC::BytecodeRewriter::graph):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::ensureCatchLivenessIsComputedForBytecodeOffsetSlow):
(JSC::CodeBlock::validate):
(JSC::CodeBlock::livenessAnalysisSlow): Deleted.

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::livenessAnalysis):

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedCodeBlock::applyModification):
(JSC::UnlinkedCodeBlock::livenessAnalysisSlow):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedCodeBlock::livenessAnalysis):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::livenessFor):
(JSC::DFG::Graph::killsFor):

  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::cleanMustHandleValuesIfNecessary):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

Location:
trunk/Source/JavaScriptCore
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r224136 r224138  
     12017-10-27  Saam Barati  <sbarati@apple.com>
     2
     3        Bytecode liveness should live on UnlinkedCodeBlock so it can be shared amongst CodeBlocks
     4        https://bugs.webkit.org/show_bug.cgi?id=178949
     5
     6        Reviewed by Keith Miller.
     7
     8        This patch stores BytecodeLiveness on UnlinkedCodeBlock instead of CodeBlock
     9        so that we don't need to recompute liveness for the same UnlinkedCodeBlock
     10        more than once. To do this, this patch solidifies the invariant that CodeBlock
     11        linking can't do anything that would change the result of liveness. For example,
     12        it can't introduce new locals. This invariant was met my JSC before, because we
     13        didn't do anything in bytecode linking that would change liveness. However, it is
     14        now a correctness requirement that we don't do anything that would change the
     15        result of running liveness. To support this change, I've refactored BytecodeGraph
     16        to not be tied to a CodeBlockType*. Things that perform liveness will pass in
     17        CodeBlockType* and the instruction stream as needed. This means that we may
     18        compute liveness with one CodeBlock*'s instruction stream, and then perform
     19        queries on that analysis with a different CodeBlock*'s instruction stream.
     20
     21        This seems to be a 2% JSBench progression.
     22
     23        * bytecode/BytecodeGeneratorification.cpp:
     24        (JSC::BytecodeGeneratorification::BytecodeGeneratorification):
     25        (JSC::BytecodeGeneratorification::graph):
     26        (JSC::BytecodeGeneratorification::storageForGeneratorLocal):
     27        (JSC::GeneratorLivenessAnalysis::run):
     28        (JSC::BytecodeGeneratorification::run):
     29        * bytecode/BytecodeGraph.h:
     30        (JSC::BytecodeGraph::BytecodeGraph):
     31        (JSC::BytecodeGraph::codeBlock const): Deleted.
     32        (JSC::BytecodeGraph::instructions): Deleted.
     33        (JSC::BytecodeGraph<Block>::BytecodeGraph): Deleted.
     34        * bytecode/BytecodeLivenessAnalysis.cpp:
     35        (JSC::BytecodeLivenessAnalysis::BytecodeLivenessAnalysis):
     36        (JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset):
     37        (JSC::BytecodeLivenessAnalysis::computeFullLiveness):
     38        (JSC::BytecodeLivenessAnalysis::computeKills):
     39        (JSC::BytecodeLivenessAnalysis::dumpResults):
     40        (JSC::BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset): Deleted.
     41        (JSC::BytecodeLivenessAnalysis::compute): Deleted.
     42        * bytecode/BytecodeLivenessAnalysis.h:
     43        * bytecode/BytecodeLivenessAnalysisInlines.h:
     44        (JSC::BytecodeLivenessPropagation::stepOverInstruction):
     45        (JSC::BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset):
     46        (JSC::BytecodeLivenessPropagation::computeLocalLivenessForBlock):
     47        (JSC::BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset):
     48        (JSC::BytecodeLivenessPropagation::runLivenessFixpoint):
     49        * bytecode/BytecodeRewriter.cpp:
     50        (JSC::BytecodeRewriter::applyModification):
     51        (JSC::BytecodeRewriter::execute):
     52        (JSC::BytecodeRewriter::adjustJumpTargetsInFragment):
     53        * bytecode/BytecodeRewriter.h:
     54        (JSC::BytecodeRewriter::BytecodeRewriter):
     55        (JSC::BytecodeRewriter::removeBytecode):
     56        (JSC::BytecodeRewriter::graph):
     57        * bytecode/CodeBlock.cpp:
     58        (JSC::CodeBlock::finishCreation):
     59        (JSC::CodeBlock::ensureCatchLivenessIsComputedForBytecodeOffsetSlow):
     60        (JSC::CodeBlock::validate):
     61        (JSC::CodeBlock::livenessAnalysisSlow): Deleted.
     62        * bytecode/CodeBlock.h:
     63        (JSC::CodeBlock::livenessAnalysis):
     64        * bytecode/UnlinkedCodeBlock.cpp:
     65        (JSC::UnlinkedCodeBlock::applyModification):
     66        (JSC::UnlinkedCodeBlock::livenessAnalysisSlow):
     67        * bytecode/UnlinkedCodeBlock.h:
     68        (JSC::UnlinkedCodeBlock::livenessAnalysis):
     69        * dfg/DFGGraph.cpp:
     70        (JSC::DFG::Graph::livenessFor):
     71        (JSC::DFG::Graph::killsFor):
     72        * dfg/DFGPlan.cpp:
     73        (JSC::DFG::Plan::cleanMustHandleValuesIfNecessary):
     74        * jit/JIT.cpp:
     75        (JSC::JIT::privateCompileMainPass):
     76
    1772017-10-27  Keith Miller  <keith_miller@apple.com>
    278
  • trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp

    r221551 r224138  
    5454
    5555    BytecodeGeneratorification(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions, SymbolTable* generatorFrameSymbolTable, int generatorFrameSymbolTableIndex)
    56         : m_graph(codeBlock, instructions)
     56        : m_codeBlock(codeBlock)
     57        , m_instructions(instructions)
     58        , m_graph(m_codeBlock, m_instructions)
    5759        , m_generatorFrameSymbolTable(*codeBlock->vm(), generatorFrameSymbolTable)
    5860        , m_generatorFrameSymbolTableIndex(generatorFrameSymbolTableIndex)
     
    6062        for (BytecodeBasicBlock* block : m_graph) {
    6163            for (unsigned bytecodeOffset : block->offsets()) {
    62                 const UnlinkedInstruction* pc = &m_graph.instructions()[bytecodeOffset];
     64                const UnlinkedInstruction* pc = &instructions[bytecodeOffset];
    6365                switch (pc->u.opcode) {
    6466                case op_enter: {
     
    9294    void run();
    9395
    94     BytecodeGraph<UnlinkedCodeBlock>& graph() { return m_graph; }
     96    BytecodeGraph& graph() { return m_graph; }
    9597
    9698    const Yields& yields() const
     
    122124            return *storage;
    123125
    124         UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
    125126        Identifier identifier = Identifier::fromUid(PrivateName());
    126         unsigned identifierIndex = codeBlock->numberOfIdentifiers();
    127         codeBlock->addIdentifier(identifier);
     127        unsigned identifierIndex = m_codeBlock->numberOfIdentifiers();
     128        m_codeBlock->addIdentifier(identifier);
    128129        ScopeOffset scopeOffset = m_generatorFrameSymbolTable->takeNextScopeOffset(NoLockingNecessary);
    129130        m_generatorFrameSymbolTable->set(NoLockingNecessary, identifier.impl(), SymbolTableEntry(VarOffset(scopeOffset)));
     
    139140
    140141    unsigned m_enterPoint { 0 };
    141     BytecodeGraph<UnlinkedCodeBlock> m_graph;
     142    UnlinkedCodeBlock* m_codeBlock;
     143    UnlinkedCodeBlock::UnpackedInstructions& m_instructions;
     144    BytecodeGraph m_graph;
    142145    Vector<std::optional<Storage>> m_storages;
    143146    Yields m_yields;
     
    153156    }
    154157
    155     void run()
     158    void run(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions)
    156159    {
    157160        // Perform modified liveness analysis to determine which locals are live at the merge points.
    158161        // This produces the conservative results for the question, "which variables should be saved and resumed?".
    159162
    160         runLivenessFixpoint(m_generatorification.graph());
     163        runLivenessFixpoint(codeBlock, instructions, m_generatorification.graph());
    161164
    162165        for (YieldData& data : m_generatorification.yields())
    163             data.liveness = getLivenessInfoAtBytecodeOffset(m_generatorification.graph(), data.point + opcodeLength(op_yield));
     166            data.liveness = getLivenessInfoAtBytecodeOffset(codeBlock, instructions, m_generatorification.graph(), data.point + opcodeLength(op_yield));
    164167    }
    165168
     
    174177    {
    175178        GeneratorLivenessAnalysis pass(*this);
    176         pass.run();
    177     }
    178 
    179     UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
    180     BytecodeRewriter rewriter(m_graph);
     179        pass.run(m_codeBlock, m_instructions);
     180    }
     181
     182    BytecodeRewriter rewriter(m_graph, m_codeBlock, m_instructions);
    181183
    182184    // Setup the global switch for the generator.
    183185    {
    184186        unsigned nextToEnterPoint = enterPoint() + opcodeLength(op_enter);
    185         unsigned switchTableIndex = m_graph.codeBlock()->numberOfSwitchJumpTables();
     187        unsigned switchTableIndex = m_codeBlock->numberOfSwitchJumpTables();
    186188        VirtualRegister state = virtualRegisterForArgument(static_cast<int32_t>(JSGeneratorFunction::GeneratorArgument::State));
    187         auto& jumpTable = m_graph.codeBlock()->addSwitchJumpTable();
     189        auto& jumpTable = m_codeBlock->addSwitchJumpTable();
    188190        jumpTable.min = 0;
    189191        jumpTable.branchOffsets.resize(m_yields.size() + 1);
     
    228230                Storage storage = storageForGeneratorLocal(index);
    229231
    230                 UnlinkedValueProfile profile = codeBlock->addValueProfile();
     232                UnlinkedValueProfile profile = m_codeBlock->addValueProfile();
    231233                fragment.appendInstruction(
    232234                    op_get_from_scope,
  • trunk/Source/JavaScriptCore/bytecode/BytecodeGraph.h

    r204994 r224138  
    3636class BytecodeBasicBlock;
    3737
    38 template<typename Block>
    3938class BytecodeGraph {
    4039    WTF_MAKE_FAST_ALLOCATED;
    4140    WTF_MAKE_NONCOPYABLE(BytecodeGraph);
    4241public:
    43     typedef Block CodeBlock;
    44     typedef typename Block::Instruction Instruction;
    4542    typedef Vector<std::unique_ptr<BytecodeBasicBlock>> BasicBlocksVector;
    4643
    47     typedef WTF::IndexedContainerIterator<BytecodeGraph<Block>> iterator;
     44    typedef WTF::IndexedContainerIterator<BytecodeGraph> iterator;
    4845
    49     inline BytecodeGraph(Block*, typename Block::UnpackedInstructions&);
    50 
    51     Block* codeBlock() const { return m_codeBlock; }
    52 
    53     typename Block::UnpackedInstructions& instructions() { return m_instructions; }
     46    template <typename CodeBlockType>
     47    inline BytecodeGraph(CodeBlockType*, typename CodeBlockType::UnpackedInstructions&);
    5448
    5549    WTF::IteratorRange<BasicBlocksVector::reverse_iterator> basicBlocksInReverseOrder()
     
    107101
    108102private:
    109     Block* m_codeBlock;
    110103    BasicBlocksVector m_basicBlocks;
    111     typename Block::UnpackedInstructions& m_instructions;
    112104};
    113105
    114106
    115 template<typename Block>
    116 BytecodeGraph<Block>::BytecodeGraph(Block* codeBlock, typename Block::UnpackedInstructions& instructions)
    117     : m_codeBlock(codeBlock)
    118     , m_instructions(instructions)
     107template<typename CodeBlockType>
     108BytecodeGraph::BytecodeGraph(CodeBlockType* codeBlock, typename CodeBlockType::UnpackedInstructions& instructions)
    119109{
    120     ASSERT(m_codeBlock);
    121     BytecodeBasicBlock::compute(m_codeBlock, instructions.begin(), instructions.size(), m_basicBlocks);
     110    BytecodeBasicBlock::compute(codeBlock, instructions.begin(), instructions.size(), m_basicBlocks);
    122111    ASSERT(m_basicBlocks.size());
    123112}
  • trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp

    r221551 r224138  
    4141    : m_graph(codeBlock, codeBlock->instructions())
    4242{
    43     compute();
     43    runLivenessFixpoint(codeBlock, codeBlock->instructions(), m_graph);
     44
     45    if (Options::dumpBytecodeLivenessResults())
     46        dumpResults(codeBlock);
    4447}
    4548
    46 void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector& result)
     49void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& result)
    4750{
    4851    BytecodeBasicBlock* block = m_graph.findBasicBlockForBytecodeOffset(bytecodeOffset);
     
    5154    ASSERT(!block->isExitBlock());
    5255    result.resize(block->out().numBits());
    53     computeLocalLivenessForBytecodeOffset(m_graph, block, bytecodeOffset, result);
     56    computeLocalLivenessForBytecodeOffset(codeBlock, codeBlock->instructions(), m_graph, block, bytecodeOffset, result);
    5457}
    5558
    56 bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset)
    57 {
    58     if (operandIsAlwaysLive(operand))
    59         return true;
    60     FastBitVector result;
    61     getLivenessInfoAtBytecodeOffset(bytecodeOffset, result);
    62     return operandThatIsNotAlwaysLiveIsLive(result, operand);
    63 }
    64 
    65 FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset)
     59FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset)
    6660{
    6761    FastBitVector out;
    68     getLivenessInfoAtBytecodeOffset(bytecodeOffset, out);
     62    getLivenessInfoAtBytecodeOffset(codeBlock, bytecodeOffset, out);
    6963    return out;
    7064}
    7165
    72 void BytecodeLivenessAnalysis::computeFullLiveness(FullBytecodeLiveness& result)
     66void BytecodeLivenessAnalysis::computeFullLiveness(CodeBlock* codeBlock, FullBytecodeLiveness& result)
    7367{
    7468    FastBitVector out;
    75     CodeBlock* codeBlock = m_graph.codeBlock();
    76    
     69
    7770    result.m_map.resize(codeBlock->instructions().size());
    7871   
     
    8578        for (unsigned i = block->offsets().size(); i--;) {
    8679            unsigned bytecodeOffset = block->offsets()[i];
    87             stepOverInstruction(m_graph, bytecodeOffset, out);
     80            stepOverInstruction(codeBlock, codeBlock->instructions(), m_graph, bytecodeOffset, out);
    8881            result.m_map[bytecodeOffset] = out;
    8982        }
     
    9184}
    9285
    93 void BytecodeLivenessAnalysis::computeKills(BytecodeKills& result)
     86void BytecodeLivenessAnalysis::computeKills(CodeBlock* codeBlock, BytecodeKills& result)
    9487{
     88    UNUSED_PARAM(result);
    9589    FastBitVector out;
    96    
    97     CodeBlock* codeBlock = m_graph.codeBlock();
     90
    9891    result.m_codeBlock = codeBlock;
    9992    result.m_killSets = std::make_unique<BytecodeKills::KillSet[]>(codeBlock->instructions().size());
     
    108101            unsigned bytecodeOffset = block->offsets()[i];
    109102            stepOverInstruction(
    110                 m_graph, bytecodeOffset,
     103                codeBlock, codeBlock->instructions(), m_graph, bytecodeOffset,
    111104                [&] (unsigned index) {
    112105                    // This is for uses.
     
    124117}
    125118
    126 void BytecodeLivenessAnalysis::dumpResults()
     119void BytecodeLivenessAnalysis::dumpResults(CodeBlock* codeBlock)
    127120{
    128     CodeBlock* codeBlock = m_graph.codeBlock();
    129121    dataLog("\nDumping bytecode liveness for ", *codeBlock, ":\n");
    130122    Instruction* instructionsBegin = codeBlock->instructions().begin();
     
    179171
    180172            dataLogF("Live variables:");
    181             FastBitVector liveBefore = getLivenessInfoAtBytecodeOffset(bytecodeOffset);
     173            FastBitVector liveBefore = getLivenessInfoAtBytecodeOffset(codeBlock, bytecodeOffset);
    182174            dumpBitVector(liveBefore);
    183175            dataLogF("\n");
     
    196188}
    197189
    198 void BytecodeLivenessAnalysis::compute()
    199 {
    200     runLivenessFixpoint(m_graph);
    201 
    202     if (Options::dumpBytecodeLivenessResults())
    203         dumpResults();
    204 }
    205 
    206190} // namespace JSC
  • trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h

    r221551 r224138  
    3838class BytecodeLivenessPropagation {
    3939protected:
    40     template<typename Graph, typename UseFunctor, typename DefFunctor> void stepOverInstruction(Graph&, unsigned bytecodeOffset, const UseFunctor&, const DefFunctor&);
     40    template<typename CodeBlockType, typename Instructions, typename UseFunctor, typename DefFunctor> void stepOverInstruction(CodeBlockType*, const Instructions&, BytecodeGraph&, unsigned bytecodeOffset, const UseFunctor&, const DefFunctor&);
    4141
    42     template<typename Graph> void stepOverInstruction(Graph&, unsigned bytecodeOffset, FastBitVector& out);
     42    template<typename CodeBlockType, typename Instructions> void stepOverInstruction(CodeBlockType*, const Instructions&, BytecodeGraph&, unsigned bytecodeOffset, FastBitVector& out);
    4343
    44     template<typename Graph> bool computeLocalLivenessForBytecodeOffset(Graph&, BytecodeBasicBlock*, unsigned targetOffset, FastBitVector& result);
     44    template<typename CodeBlockType, typename Instructions> bool computeLocalLivenessForBytecodeOffset(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*, unsigned targetOffset, FastBitVector& result);
    4545
    46     template<typename Graph> bool computeLocalLivenessForBlock(Graph&, BytecodeBasicBlock*);
     46    template<typename CodeBlockType, typename Instructions> bool computeLocalLivenessForBlock(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*);
    4747
    48     template<typename Graph> FastBitVector getLivenessInfoAtBytecodeOffset(Graph&, unsigned bytecodeOffset);
     48    template<typename CodeBlockType, typename Instructions> FastBitVector getLivenessInfoAtBytecodeOffset(CodeBlockType*, const Instructions&, BytecodeGraph&, unsigned bytecodeOffset);
    4949
    50     template<typename Graph> void runLivenessFixpoint(Graph&);
     50    template<typename CodeBlockType, typename Instructions> void runLivenessFixpoint(CodeBlockType*, const Instructions&, BytecodeGraph&);
    5151};
    5252
     
    5858    BytecodeLivenessAnalysis(CodeBlock*);
    5959   
    60     bool operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset);
    61     FastBitVector getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset);
     60    FastBitVector getLivenessInfoAtBytecodeOffset(CodeBlock*, unsigned bytecodeOffset);
    6261   
    63     void computeFullLiveness(FullBytecodeLiveness& result);
    64     void computeKills(BytecodeKills& result);
     62    void computeFullLiveness(CodeBlock*, FullBytecodeLiveness& result);
     63    void computeKills(CodeBlock*, BytecodeKills& result);
    6564
    6665private:
    67     void compute();
    68     void dumpResults();
     66    void dumpResults(CodeBlock*);
    6967
    70     void getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector&);
     68    void getLivenessInfoAtBytecodeOffset(CodeBlock*, unsigned bytecodeOffset, FastBitVector&);
    7169
    72     BytecodeGraph<CodeBlock> m_graph;
     70    BytecodeGraph m_graph;
    7371};
    7472
  • trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h

    r221551 r224138  
    6262// Simplified interface to bytecode use/def, which determines defs first and then uses, and includes
    6363// exception handlers in the uses.
    64 template<typename Graph, typename UseFunctor, typename DefFunctor>
    65 inline void BytecodeLivenessPropagation::stepOverInstruction(Graph& graph, unsigned bytecodeOffset, const UseFunctor& use, const DefFunctor& def)
     64template<typename CodeBlockType, typename Instructions, typename UseFunctor, typename DefFunctor>
     65inline void BytecodeLivenessPropagation::stepOverInstruction(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset, const UseFunctor& use, const DefFunctor& def)
    6666{
    6767    // This abstractly execute the instruction in reverse. Instructions logically first use operands and
     
    8080    // first add it to the out set (the use), and then we'd remove it (the def).
    8181
    82     auto* codeBlock = graph.codeBlock();
    83     auto* instructionsBegin = graph.instructions().begin();
     82    auto* instructionsBegin = instructions.begin();
    8483    auto* instruction = &instructionsBegin[bytecodeOffset];
    8584    OpcodeID opcodeID = Interpreter::getOpcodeID(*instruction);
     
    8786    computeDefsForBytecodeOffset(
    8887        codeBlock, opcodeID, instruction,
    89         [&] (typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) {
     88        [&] (CodeBlockType*, const typename CodeBlockType::Instruction*, OpcodeID, int operand) {
    9089            if (isValidRegisterForLiveness(operand))
    9190                def(VirtualRegister(operand).toLocal());
     
    9493    computeUsesForBytecodeOffset(
    9594        codeBlock, opcodeID, instruction,
    96         [&] (typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) {
     95        [&] (CodeBlockType*, const typename CodeBlockType::Instruction*, OpcodeID, int operand) {
    9796            if (isValidRegisterForLiveness(operand))
    9897                use(VirtualRegister(operand).toLocal());
     
    108107}
    109108
    110 template<typename Graph>
    111 inline void BytecodeLivenessPropagation::stepOverInstruction(Graph& graph, unsigned bytecodeOffset, FastBitVector& out)
     109template<typename CodeBlockType, typename Instructions>
     110inline void BytecodeLivenessPropagation::stepOverInstruction(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset, FastBitVector& out)
    112111{
    113112    stepOverInstruction(
    114         graph, bytecodeOffset,
     113        codeBlock, instructions, graph, bytecodeOffset,
    115114        [&] (unsigned bitIndex) {
    116115            // This is the use functor, so we set the bit.
     
    123122}
    124123
    125 template<typename Graph>
    126 inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset(Graph& graph, BytecodeBasicBlock* block, unsigned targetOffset, FastBitVector& result)
     124template<typename CodeBlockType, typename Instructions>
     125inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block, unsigned targetOffset, FastBitVector& result)
    127126{
    128127    ASSERT(!block->isExitBlock());
     
    135134        if (targetOffset > bytecodeOffset)
    136135            break;
    137         stepOverInstruction(graph, bytecodeOffset, out);
     136        stepOverInstruction(codeBlock, instructions, graph, bytecodeOffset, out);
    138137    }
    139138
     
    141140}
    142141
    143 template<typename Graph>
    144 inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(Graph& graph, BytecodeBasicBlock* block)
     142template<typename CodeBlockType, typename Instructions>
     143inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block)
    145144{
    146145    if (block->isExitBlock() || block->isEntryBlock())
    147146        return false;
    148     return computeLocalLivenessForBytecodeOffset(graph, block, block->leaderOffset(), block->in());
     147    return computeLocalLivenessForBytecodeOffset(codeBlock, instructions, graph, block, block->leaderOffset(), block->in());
    149148}
    150149
    151 template<typename Graph>
    152 inline FastBitVector BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset(Graph& graph, unsigned bytecodeOffset)
     150template<typename CodeBlockType, typename Instructions>
     151inline FastBitVector BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset)
    153152{
    154153    BytecodeBasicBlock* block = graph.findBasicBlockForBytecodeOffset(bytecodeOffset);
     
    158157    FastBitVector out;
    159158    out.resize(block->out().numBits());
    160     computeLocalLivenessForBytecodeOffset(graph, block, bytecodeOffset, out);
     159    computeLocalLivenessForBytecodeOffset(codeBlock, instructions, graph, block, bytecodeOffset, out);
    161160    return out;
    162161}
    163162
    164 template<typename Graph>
    165 inline void BytecodeLivenessPropagation::runLivenessFixpoint(Graph& graph)
     163template<typename CodeBlockType, typename Instructions>
     164inline void BytecodeLivenessPropagation::runLivenessFixpoint(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph)
    166165{
    167     auto* codeBlock = graph.codeBlock();
    168166    unsigned numberOfVariables = codeBlock->numCalleeLocals();
    169167    for (BytecodeBasicBlock* block : graph) {
     
    187185                newOut |= successor->in();
    188186            block->out() = newOut;
    189             changed |= computeLocalLivenessForBlock(graph, block.get());
     187            changed |= computeLocalLivenessForBlock(codeBlock, instructions, graph, block.get());
    190188        }
    191189    } while (changed);
  • trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp

    r218412 r224138  
    3939        Insertion& insertion = m_insertions[insertionIndex];
    4040        if (insertion.type == Insertion::Type::Remove)
    41             m_graph.instructions().remove(insertion.index.bytecodeOffset, insertion.length());
     41            m_instructions.remove(insertion.index.bytecodeOffset, insertion.length());
    4242        else {
    4343            if (insertion.includeBranch == IncludeBranch::Yes) {
     
    4545                adjustJumpTargetsInFragment(finalOffset, insertion);
    4646            }
    47             m_graph.instructions().insertVector(insertion.index.bytecodeOffset, insertion.instructions);
     47            m_instructions.insertVector(insertion.index.bytecodeOffset, insertion.instructions);
    4848        }
    4949    }
     
    5757    });
    5858
    59     UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
    60     codeBlock->applyModification(*this);
     59    m_codeBlock->applyModification(*this, m_instructions);
    6160}
    6261
     
    7069        if (isBranch(opcodeID)) {
    7170            unsigned bytecodeOffset = finalOffset + fragmentOffset;
    72             UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
    73             extractStoredJumpTargetsForBytecodeOffset(codeBlock, instructionsBegin, fragmentOffset, [&](int32_t& label) {
     71            extractStoredJumpTargetsForBytecodeOffset(m_codeBlock, instructionsBegin, fragmentOffset, [&](int32_t& label) {
    7472                int absoluteOffset = adjustAbsoluteOffset(label);
    7573                label = absoluteOffset - static_cast<int>(bytecodeOffset);
  • trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.h

    r204994 r224138  
    162162    };
    163163
    164     BytecodeRewriter(BytecodeGraph<UnlinkedCodeBlock>& graph)
     164    BytecodeRewriter(BytecodeGraph& graph, UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions)
    165165        : m_graph(graph)
     166        , m_codeBlock(codeBlock)
     167        , m_instructions(instructions)
    166168    {
    167169    }
     
    189191    void removeBytecode(unsigned bytecodeOffset)
    190192    {
    191         m_insertions.append(Insertion { InsertionPoint(bytecodeOffset, Position::OriginalBytecodePoint), Insertion::Type::Remove, IncludeBranch::No, opcodeLength(m_graph.instructions()[bytecodeOffset].u.opcode), { } });
     193        m_insertions.append(Insertion { InsertionPoint(bytecodeOffset, Position::OriginalBytecodePoint), Insertion::Type::Remove, IncludeBranch::No, opcodeLength(m_instructions[bytecodeOffset].u.opcode), { } });
    192194    }
    193195
    194196    void execute();
    195197
    196     BytecodeGraph<UnlinkedCodeBlock>& graph() { return m_graph; }
     198    BytecodeGraph& graph() { return m_graph; }
    197199
    198200    int adjustAbsoluteOffset(int absoluteOffset)
     
    216218    template<typename Iterator> int calculateDifference(Iterator begin, Iterator end);
    217219
    218     BytecodeGraph<UnlinkedCodeBlock>& m_graph;
     220    BytecodeGraph& m_graph;
     221    UnlinkedCodeBlock* m_codeBlock;
     222    UnlinkedCodeBlock::UnpackedInstructions& m_instructions;
    219223    Vector<Insertion, 8> m_insertions;
    220224};
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r223727 r224138  
    399399}
    400400
     401// The main purpose of this function is to generate linked bytecode from unlinked bytecode. The process
     402// of linking is taking an abstract representation of bytecode and tying it to a GlobalObject and scope
     403// chain. For example, this process allows us to cache the depth of lexical environment reads that reach
     404// outside of this CodeBlock's compilation unit. It also allows us to generate particular constants that
     405// we can't generate during unlinked bytecode generation. This process is not allowed to generate control
     406// flow or introduce new locals. The reason for this is we rely on liveness analysis to be the same for
     407// all the CodeBlocks of an UnlinkedCodeBlock. We rely on this fact by caching the liveness analysis
     408// inside UnlinkedCodeBlock.
    401409bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
    402410    JSScope* scope)
    403411{
    404412    Base::finishCreation(vm);
     413
    405414    auto throwScope = DECLARE_THROW_SCOPE(vm);
    406415
     
    17201729    // we can avoid profiling them and extracting them when doing OSR entry
    17211730    // into the DFG.
    1722     FastBitVector liveLocals = bytecodeLiveness.getLivenessInfoAtBytecodeOffset(bytecodeOffset + OPCODE_LENGTH(op_catch));
     1731    FastBitVector liveLocals = bytecodeLiveness.getLivenessInfoAtBytecodeOffset(this, bytecodeOffset + OPCODE_LENGTH(op_catch));
    17231732    Vector<VirtualRegister> liveOperands;
    17241733    liveOperands.reserveInitialCapacity(liveLocals.bitCount());
     
    28532862    BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint.
    28542863   
    2855     FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(0);
     2864    FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(this, 0);
    28562865   
    28572866    if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeLocals)) {
     
    32273236}
    32283237
    3229 BytecodeLivenessAnalysis& CodeBlock::livenessAnalysisSlow()
    3230 {
    3231     std::unique_ptr<BytecodeLivenessAnalysis> analysis = std::make_unique<BytecodeLivenessAnalysis>(this);
    3232     {
    3233         ConcurrentJSLocker locker(m_lock);
    3234         if (!m_livenessAnalysis)
    3235             m_livenessAnalysis = WTFMove(analysis);
    3236         return *m_livenessAnalysis;
    3237     }
    3238 }
    3239 
    32403238void setPrinter(Printer::PrintRecord& record, CodeBlock* codeBlock)
    32413239{
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r223989 r224138  
    116116
    117117public:
     118
    118119    enum CopyParsedBlockTag { CopyParsedBlock };
    119120
     
    601602    BytecodeLivenessAnalysis& livenessAnalysis()
    602603    {
    603         {
    604             ConcurrentJSLocker locker(m_lock);
    605             if (!!m_livenessAnalysis)
    606                 return *m_livenessAnalysis;
    607         }
    608         return livenessAnalysisSlow();
     604        return m_unlinkedCode->livenessAnalysis(this);
    609605    }
    610606   
     
    10601056    std::chrono::steady_clock::time_point m_creationTime;
    10611057
    1062     std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis;
    1063 
    10641058    std::unique_ptr<RareData> m_rareData;
    10651059
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp

    r223989 r224138  
    2929
    3030#include "BytecodeGenerator.h"
     31#include "BytecodeLivenessAnalysis.h"
    3132#include "BytecodeRewriter.h"
    3233#include "ClassInfo.h"
     
    340341}
    341342
    342 void UnlinkedCodeBlock::applyModification(BytecodeRewriter& rewriter)
     343void UnlinkedCodeBlock::applyModification(BytecodeRewriter& rewriter, UnpackedInstructions& instructions)
    343344{
    344345    // Before applying the changes, we adjust the jumps based on the original bytecode offset, the offset to the jump target, and
    345346    // the insertion information.
    346347
    347     BytecodeGraph<UnlinkedCodeBlock>& graph = rewriter.graph();
    348     UnlinkedInstruction* instructionsBegin = graph.instructions().begin();
    349 
    350     for (int bytecodeOffset = 0, instructionCount = graph.instructions().size(); bytecodeOffset < instructionCount;) {
     348    UnlinkedInstruction* instructionsBegin = instructions.begin(); // OOPS: make this an accessor on rewriter.
     349
     350    for (int bytecodeOffset = 0, instructionCount = instructions.size(); bytecodeOffset < instructionCount;) {
    351351        UnlinkedInstruction* current = instructionsBegin + bytecodeOffset;
    352352        OpcodeID opcodeID = current[0].u.opcode;
     
    387387    // And recompute the jump target based on the modified unlinked instructions.
    388388    m_jumpTargets.clear();
    389     recomputePreciseJumpTargets(this, graph.instructions().begin(), graph.instructions().size(), m_jumpTargets);
     389    recomputePreciseJumpTargets(this, instructions.begin(), instructions.size(), m_jumpTargets);
    390390}
    391391
     
    419419}
    420420
     421BytecodeLivenessAnalysis& UnlinkedCodeBlock::livenessAnalysisSlow(CodeBlock* codeBlock)
     422{
     423    RELEASE_ASSERT(codeBlock->unlinkedCodeBlock() == this);
     424
     425
     426    {
     427        auto locker = holdLock(m_lock);
     428        if (!m_liveness) {
     429            // There is a chance two compiler threads raced to the slow path.
     430            // We defend against computing liveness twice.
     431            m_liveness = std::make_unique<BytecodeLivenessAnalysis>(codeBlock);
     432        }
     433    }
     434   
     435    return *m_liveness;
     436}
     437
    421438} // namespace JSC
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

    r223989 r224138  
    4747namespace JSC {
    4848
     49class BytecodeLivenessAnalysis;
    4950class BytecodeRewriter;
     51class CodeBlock;
    5052class Debugger;
    5153class FunctionExecutable;
     
    396398    void dump(PrintStream&) const;
    397399
     400    BytecodeLivenessAnalysis& livenessAnalysis(CodeBlock* codeBlock)
     401    {
     402        if (m_liveness)
     403            return *m_liveness;
     404        return livenessAnalysisSlow(codeBlock);
     405    }
     406
    398407protected:
    399408    UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode);
     
    407416private:
    408417    friend class BytecodeRewriter;
    409     void applyModification(BytecodeRewriter&);
     418    void applyModification(BytecodeRewriter&, UnpackedInstructions&);
    410419
    411420    void createRareDataIfNecessary()
     
    418427
    419428    void getLineAndColumn(const ExpressionRangeInfo&, unsigned& line, unsigned& column) const;
     429    BytecodeLivenessAnalysis& livenessAnalysisSlow(CodeBlock*);
    420430
    421431    int m_numParameters;
    422432
    423433    std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions;
     434    std::unique_ptr<BytecodeLivenessAnalysis> m_liveness;
    424435
    425436    VirtualRegister m_thisRegister;
     
    446457    unsigned m_endColumn;
    447458
     459    Lock m_lock;
    448460    TriState m_didOptimize;
    449461    SourceParseMode m_parseMode;
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r223614 r224138  
    10871087   
    10881088    std::unique_ptr<FullBytecodeLiveness> liveness = std::make_unique<FullBytecodeLiveness>();
    1089     codeBlock->livenessAnalysis().computeFullLiveness(*liveness);
     1089    codeBlock->livenessAnalysis().computeFullLiveness(codeBlock, *liveness);
    10901090    FullBytecodeLiveness& result = *liveness;
    10911091    m_bytecodeLiveness.add(codeBlock, WTFMove(liveness));
     
    11051105   
    11061106    std::unique_ptr<BytecodeKills> kills = std::make_unique<BytecodeKills>();
    1107     codeBlock->livenessAnalysis().computeKills(*kills);
     1107    codeBlock->livenessAnalysis().computeKills(codeBlock, *kills);
    11081108    BytecodeKills& result = *kills;
    11091109    m_bytecodeKills.add(codeBlock, WTFMove(kills));
  • trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp

    r223086 r224138  
    698698        return;
    699699   
    700     FastBitVector liveness = codeBlock->alternative()->livenessAnalysis().getLivenessInfoAtBytecodeOffset(osrEntryBytecodeIndex);
     700    CodeBlock* alternative = codeBlock->alternative();
     701    FastBitVector liveness = alternative->livenessAnalysis().getLivenessInfoAtBytecodeOffset(alternative, osrEntryBytecodeIndex);
    701702   
    702703    for (unsigned local = mustHandleValues.numberOfLocals(); local--;) {
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r223823 r224138  
    196196            // compile code from that bytecode offset onwards.
    197197
    198             BytecodeGraph<CodeBlock> graph(m_codeBlock, m_instructions);
     198            BytecodeGraph graph(m_codeBlock, m_instructions);
    199199            BytecodeBasicBlock* block = graph.findBasicBlockForBytecodeOffset(m_loopOSREntryBytecodeOffset);
    200200            RELEASE_ASSERT(block);
Note: See TracChangeset for help on using the changeset viewer.