Title: [255459] trunk/Source/_javascript_Core
Revision
255459
Author
[email protected]
Date
2020-01-30 14:32:43 -0800 (Thu, 30 Jan 2020)

Log Message

[JSC] Remove unnecessary allocations in BytecodeBasicBlock
https://bugs.webkit.org/show_bug.cgi?id=206986

Reviewed by Mark Lam.

We know that BytecodeBasicBlock itself takes 2MB in Gmail. And each BytecodeBasicBlock has Vector<unsigned>
and Vector<BytecodeBasicBlock*>.

BytecodeBasicBlock holds all the offset per bytecode as unsigned in m_offsets. But this offset is
only used when reverse iterating a bytecode in a BytecodeBasicBlock. We can hold a length of each
bytecode instead, which is much smaller (unsigned v.s. uint8_t).

Since each BytecodeBasicBlock has index, we should hold successors in Vector<unsigned> instead of Vector<BytecodeBasicBlock*>.

We are also allocating BytecodeBasicBlock in makeUnique<> and having them in Vector<std::unique_ptr<BytecodeBasicBlock>>.
But this is not necessary since only BytecodeBasicBlock::compute can modify this vector. We should generate Vector<BytecodeBasicBlock>
from BytecodeBasicBlock::compute.

We are also planning purging BytecodeBasicBlock in UnlinkedCodeBlock if it is not used so much. But this will be done in a separate patch.

* bytecode/BytecodeBasicBlock.cpp:
(JSC::BytecodeBasicBlock::BytecodeBasicBlock):
(JSC::BytecodeBasicBlock::addLength):
(JSC::BytecodeBasicBlock::shrinkToFit):
(JSC::BytecodeBasicBlock::computeImpl):
(JSC::BytecodeBasicBlock::compute):
* bytecode/BytecodeBasicBlock.h:
(JSC::BytecodeBasicBlock::delta const):
(JSC::BytecodeBasicBlock::successors const):
(JSC::BytecodeBasicBlock::operator bool const):
(JSC::BytecodeBasicBlock::addSuccessor):
(JSC::BytecodeBasicBlock::offsets const): Deleted.
(JSC::BytecodeBasicBlock:: const): Deleted.
(JSC::BytecodeBasicBlock::BytecodeBasicBlock): Deleted.
(JSC::BytecodeBasicBlock::addLength): Deleted.
* bytecode/BytecodeGeneratorification.cpp:
(JSC::BytecodeGeneratorification::BytecodeGeneratorification):
* bytecode/BytecodeGraph.h:
(JSC::BytecodeGraph::blockContainsBytecodeOffset):
(JSC::BytecodeGraph::findBasicBlockForBytecodeOffset):
(JSC::BytecodeGraph::findBasicBlockWithLeaderOffset):
(JSC::BytecodeGraph::at const):
(JSC::BytecodeGraph::operator[] const):
(JSC::BytecodeGraph::begin):
(JSC::BytecodeGraph::end):
(JSC::BytecodeGraph::first):
(JSC::BytecodeGraph::last):
(JSC::BytecodeGraph::BytecodeGraph):
(JSC::BytecodeGraph::begin const): Deleted.
(JSC::BytecodeGraph::end const): Deleted.
* bytecode/BytecodeLivenessAnalysis.cpp:
(JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeIndex):
(JSC::BytecodeLivenessAnalysis::computeFullLiveness):
(JSC::BytecodeLivenessAnalysis::computeKills):
(JSC::BytecodeLivenessAnalysis::dumpResults):
* bytecode/BytecodeLivenessAnalysis.h:
* bytecode/BytecodeLivenessAnalysisInlines.h:
(JSC::BytecodeLivenessPropagation::computeLocalLivenessForBytecodeIndex):
(JSC::BytecodeLivenessPropagation::computeLocalLivenessForBlock):
(JSC::BytecodeLivenessPropagation::getLivenessInfoAtBytecodeIndex):
(JSC::BytecodeLivenessPropagation::runLivenessFixpoint):
* bytecode/InstructionStream.h:
(JSC::InstructionStream::MutableRef::operator-> const):
(JSC::InstructionStream::MutableRef::ptr const):
(JSC::InstructionStream::MutableRef::unwrap const):
* bytecode/Opcode.h:
* generator/Section.rb:
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* llint/LLIntData.cpp:
(JSC::LLInt::initialize):
* llint/LowLevelInterpreter.cpp:
(JSC::CLoop::execute):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (255458 => 255459)


--- trunk/Source/_javascript_Core/ChangeLog	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-01-30 22:32:43 UTC (rev 255459)
@@ -1,3 +1,79 @@
+2020-01-30  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Remove unnecessary allocations in BytecodeBasicBlock
+        https://bugs.webkit.org/show_bug.cgi?id=206986
+
+        Reviewed by Mark Lam.
+
+        We know that BytecodeBasicBlock itself takes 2MB in Gmail. And each BytecodeBasicBlock has Vector<unsigned>
+        and Vector<BytecodeBasicBlock*>.
+
+        BytecodeBasicBlock holds all the offset per bytecode as unsigned in m_offsets. But this offset is
+        only used when reverse iterating a bytecode in a BytecodeBasicBlock. We can hold a length of each
+        bytecode instead, which is much smaller (unsigned v.s. uint8_t).
+
+        Since each BytecodeBasicBlock has index, we should hold successors in Vector<unsigned> instead of Vector<BytecodeBasicBlock*>.
+
+        We are also allocating BytecodeBasicBlock in makeUnique<> and having them in Vector<std::unique_ptr<BytecodeBasicBlock>>.
+        But this is not necessary since only BytecodeBasicBlock::compute can modify this vector. We should generate Vector<BytecodeBasicBlock>
+        from BytecodeBasicBlock::compute.
+
+        We are also planning purging BytecodeBasicBlock in UnlinkedCodeBlock if it is not used so much. But this will be done in a separate patch.
+
+        * bytecode/BytecodeBasicBlock.cpp:
+        (JSC::BytecodeBasicBlock::BytecodeBasicBlock):
+        (JSC::BytecodeBasicBlock::addLength):
+        (JSC::BytecodeBasicBlock::shrinkToFit):
+        (JSC::BytecodeBasicBlock::computeImpl):
+        (JSC::BytecodeBasicBlock::compute):
+        * bytecode/BytecodeBasicBlock.h:
+        (JSC::BytecodeBasicBlock::delta const):
+        (JSC::BytecodeBasicBlock::successors const):
+        (JSC::BytecodeBasicBlock::operator bool const):
+        (JSC::BytecodeBasicBlock::addSuccessor):
+        (JSC::BytecodeBasicBlock::offsets const): Deleted.
+        (JSC::BytecodeBasicBlock:: const): Deleted.
+        (JSC::BytecodeBasicBlock::BytecodeBasicBlock): Deleted.
+        (JSC::BytecodeBasicBlock::addLength): Deleted.
+        * bytecode/BytecodeGeneratorification.cpp:
+        (JSC::BytecodeGeneratorification::BytecodeGeneratorification):
+        * bytecode/BytecodeGraph.h:
+        (JSC::BytecodeGraph::blockContainsBytecodeOffset):
+        (JSC::BytecodeGraph::findBasicBlockForBytecodeOffset):
+        (JSC::BytecodeGraph::findBasicBlockWithLeaderOffset):
+        (JSC::BytecodeGraph::at const):
+        (JSC::BytecodeGraph::operator[] const):
+        (JSC::BytecodeGraph::begin):
+        (JSC::BytecodeGraph::end):
+        (JSC::BytecodeGraph::first):
+        (JSC::BytecodeGraph::last):
+        (JSC::BytecodeGraph::BytecodeGraph):
+        (JSC::BytecodeGraph::begin const): Deleted.
+        (JSC::BytecodeGraph::end const): Deleted.
+        * bytecode/BytecodeLivenessAnalysis.cpp:
+        (JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeIndex):
+        (JSC::BytecodeLivenessAnalysis::computeFullLiveness):
+        (JSC::BytecodeLivenessAnalysis::computeKills):
+        (JSC::BytecodeLivenessAnalysis::dumpResults):
+        * bytecode/BytecodeLivenessAnalysis.h:
+        * bytecode/BytecodeLivenessAnalysisInlines.h:
+        (JSC::BytecodeLivenessPropagation::computeLocalLivenessForBytecodeIndex):
+        (JSC::BytecodeLivenessPropagation::computeLocalLivenessForBlock):
+        (JSC::BytecodeLivenessPropagation::getLivenessInfoAtBytecodeIndex):
+        (JSC::BytecodeLivenessPropagation::runLivenessFixpoint):
+        * bytecode/InstructionStream.h:
+        (JSC::InstructionStream::MutableRef::operator-> const):
+        (JSC::InstructionStream::MutableRef::ptr const):
+        (JSC::InstructionStream::MutableRef::unwrap const):
+        * bytecode/Opcode.h:
+        * generator/Section.rb:
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * llint/LLIntData.cpp:
+        (JSC::LLInt::initialize):
+        * llint/LowLevelInterpreter.cpp:
+        (JSC::CLoop::execute):
+
 2020-01-30  Alexey Shvayka  <[email protected]>
 
         Incomplete braced quantifiers should be banned in Unicode patterns only

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.cpp (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.cpp	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.cpp	2020-01-30 22:32:43 UTC (rev 255459)
@@ -35,9 +35,30 @@
 
 DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(BytecodeBasicBlock);
 
+BytecodeBasicBlock::BytecodeBasicBlock(const InstructionStream::Ref& instruction, unsigned blockIndex)
+    : m_leaderOffset(instruction.offset())
+    , m_totalLength(0)
+    , m_index(blockIndex)
+{
+    addLength(instruction->size());
+}
+
+BytecodeBasicBlock::BytecodeBasicBlock(BytecodeBasicBlock::SpecialBlockType blockType, unsigned blockIndex)
+    : m_leaderOffset(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
+    , m_totalLength(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
+    , m_index(blockIndex)
+{
+}
+
+void BytecodeBasicBlock::addLength(unsigned bytecodeLength)
+{
+    m_delta.append(bytecodeLength);
+    m_totalLength += bytecodeLength;
+}
+
 void BytecodeBasicBlock::shrinkToFit()
 {
-    m_offsets.shrinkToFit();
+    m_delta.shrinkToFit();
     m_successors.shrinkToFit();
 }
 
@@ -50,76 +71,80 @@
 }
 
 template<typename Block>
-void BytecodeBasicBlock::computeImpl(Block* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks)
+auto BytecodeBasicBlock::computeImpl(Block* codeBlock, const InstructionStream& instructions) -> BasicBlockVector
 {
+    BasicBlockVector basicBlocks;
     Vector<InstructionStream::Offset, 32> jumpTargets;
     computePreciseJumpTargets(codeBlock, instructions, jumpTargets);
 
-    auto appendBlock = [&] (std::unique_ptr<BytecodeBasicBlock>&& block) {
-        block->m_index = basicBlocks.size();
-        basicBlocks.append(WTFMove(block));
+    auto linkBlocks = [&] (BytecodeBasicBlock& from, BytecodeBasicBlock& to) {
+        from.addSuccessor(to);
     };
 
-    auto linkBlocks = [&] (BytecodeBasicBlock* from, BytecodeBasicBlock* to) {
-        from->addSuccessor(to);
-    };
+    {
+        // Create the entry and exit basic blocks.
+        basicBlocks.reserveCapacity(jumpTargets.size() + 2);
+        {
+            // Entry block.
+            basicBlocks.constructAndAppend(BytecodeBasicBlock::EntryBlock, basicBlocks.size());
+            // First block.
+            basicBlocks.constructAndAppend(BytecodeBasicBlock::EntryBlock, basicBlocks.size());
+            linkBlocks(basicBlocks[0], basicBlocks[1]);
+        }
 
-    // Create the entry and exit basic blocks.
-    basicBlocks.reserveCapacity(jumpTargets.size() + 2);
+        BytecodeBasicBlock* current = &basicBlocks.last();
+        auto appendBlock = [&] (const InstructionStream::Ref& instruction) -> BytecodeBasicBlock* {
+            basicBlocks.constructAndAppend(instruction, basicBlocks.size());
+            return &basicBlocks.last();
+        };
+        bool nextInstructionIsLeader = false;
+        for (const auto& instruction : instructions) {
+            auto bytecodeOffset = instruction.offset();
+            OpcodeID opcodeID = instruction->opcodeID();
 
-    auto entry = makeUnique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock);
-    auto firstBlock = makeUnique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock);
-    linkBlocks(entry.get(), firstBlock.get());
+            bool createdBlock = false;
+            // If the current bytecode is a jump target, then it's the leader of its own basic block.
+            if (nextInstructionIsLeader || isJumpTarget(opcodeID, jumpTargets, bytecodeOffset)) {
+                current = appendBlock(instruction);
+                createdBlock = true;
+                nextInstructionIsLeader = false;
+            }
 
-    appendBlock(WTFMove(entry));
-    BytecodeBasicBlock* current = firstBlock.get();
-    appendBlock(WTFMove(firstBlock));
+            // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block.
+            if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID))
+                nextInstructionIsLeader = true;
 
-    auto exit = makeUnique<BytecodeBasicBlock>(BytecodeBasicBlock::ExitBlock);
+            if (createdBlock)
+                continue;
 
-    bool nextInstructionIsLeader = false;
-
-    for (const auto& instruction : instructions) {
-        auto bytecodeOffset = instruction.offset();
-        OpcodeID opcodeID = instruction->opcodeID();
-
-        bool createdBlock = false;
-        // If the current bytecode is a jump target, then it's the leader of its own basic block.
-        if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) {
-            auto newBlock = makeUnique<BytecodeBasicBlock>(instruction);
-            current = newBlock.get();
-            appendBlock(WTFMove(newBlock));
-            createdBlock = true;
-            nextInstructionIsLeader = false;
+            // Otherwise, just add to the length of the current block.
+            current->addLength(instruction->size());
         }
-
-        // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block.
-        if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID))
-            nextInstructionIsLeader = true;
-
-        if (createdBlock)
-            continue;
-
-        // Otherwise, just add to the length of the current block.
-        current->addLength(instruction->size());
+        // Exit block.
+        basicBlocks.constructAndAppend(BytecodeBasicBlock::ExitBlock, basicBlocks.size());
+        basicBlocks.shrinkToFit();
+        ASSERT(basicBlocks.last().isExitBlock());
     }
+    // After this point, we never change basicBlocks.
 
     // Link basic blocks together.
     for (unsigned i = 0; i < basicBlocks.size(); i++) {
-        BytecodeBasicBlock* block = basicBlocks[i].get();
+        BytecodeBasicBlock& block = basicBlocks[i];
 
-        if (block->isEntryBlock() || block->isExitBlock())
+        if (block.isEntryBlock() || block.isExitBlock())
             continue;
 
         bool fallsThrough = true;
-        for (auto bytecodeOffset : block->offsets()) {
-            auto instruction = instructions.at(bytecodeOffset);
+        for (unsigned visitedLength = 0; visitedLength < block.totalLength();) {
+            InstructionStream::Ref instruction = instructions.at(block.leaderOffset() + visitedLength);
             OpcodeID opcodeID = instruction->opcodeID();
 
+            visitedLength += instruction->size();
+
             // If we found a terminal bytecode, link to the exit block.
             if (isTerminal(opcodeID)) {
-                ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
-                linkBlocks(block, exit.get());
+                ASSERT(instruction.offset() + instruction->size() == block.leaderOffset() + block.totalLength());
+                linkBlocks(block, basicBlocks.last());
                 fallsThrough = false;
                 break;
             }
@@ -128,16 +153,15 @@
             // If there isn't one, treat this throw as a terminal. This is true even if we have a finally
             // block because the finally block will create its own catch, which will generate a HandlerInfo.
             if (isThrow(opcodeID)) {
-                ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
+                ASSERT(instruction.offset() + instruction->size() == block.leaderOffset() + block.totalLength());
                 auto* handler = codeBlock->handlerForBytecodeIndex(BytecodeIndex(instruction.offset()));
                 fallsThrough = false;
                 if (!handler) {
-                    linkBlocks(block, exit.get());
+                    linkBlocks(block, basicBlocks.last());
                     break;
                 }
-                for (unsigned i = 0; i < basicBlocks.size(); i++) {
-                    BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
-                    if (handler->target == otherBlock->leaderOffset()) {
+                for (auto& otherBlock : basicBlocks) {
+                    if (handler->target == otherBlock.leaderOffset()) {
                         linkBlocks(block, otherBlock);
                         break;
                     }
@@ -147,15 +171,14 @@
 
             // If we found a branch, link to the block(s) that we jump to.
             if (isBranch(opcodeID)) {
-                ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
+                ASSERT(instruction.offset() + instruction->size() == block.leaderOffset() + block.totalLength());
                 Vector<InstructionStream::Offset, 1> bytecodeOffsetsJumpedTo;
                 findJumpTargetsForInstruction(codeBlock, instruction, bytecodeOffsetsJumpedTo);
 
                 size_t numberOfJumpTargets = bytecodeOffsetsJumpedTo.size();
                 ASSERT(numberOfJumpTargets);
-                for (unsigned i = 0; i < basicBlocks.size(); i++) {
-                    BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
-                    if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderOffset())) {
+                for (auto& otherBlock : basicBlocks) {
+                    if (bytecodeOffsetsJumpedTo.contains(otherBlock.leaderOffset())) {
                         linkBlocks(block, otherBlock);
                         --numberOfJumpTargets;
                         if (!numberOfJumpTargets)
@@ -178,25 +201,28 @@
         // If we fall through then link to the next block in program order.
         if (fallsThrough) {
             ASSERT(i + 1 < basicBlocks.size());
-            BytecodeBasicBlock* nextBlock = basicBlocks[i + 1].get();
+            BytecodeBasicBlock& nextBlock = basicBlocks[i + 1];
             linkBlocks(block, nextBlock);
         }
     }
 
-    appendBlock(WTFMove(exit));
+    unsigned index = 0;
+    for (auto& basicBlock : basicBlocks) {
+        basicBlock.shrinkToFit();
+        ASSERT_UNUSED(index, basicBlock.index() == index++);
+    }
 
-    for (auto& basicBlock : basicBlocks)
-        basicBlock->shrinkToFit();
+    return basicBlocks;
 }
 
-void BytecodeBasicBlock::compute(CodeBlock* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks)
+auto BytecodeBasicBlock::compute(CodeBlock* codeBlock, const InstructionStream& instructions) -> BasicBlockVector
 {
-    computeImpl(codeBlock, instructions, basicBlocks);
+    return computeImpl(codeBlock, instructions);
 }
 
-void BytecodeBasicBlock::compute(UnlinkedCodeBlock* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks)
+auto BytecodeBasicBlock::compute(UnlinkedCodeBlock* codeBlock, const InstructionStream& instructions) -> BasicBlockVector
 {
-    computeImpl(codeBlock, instructions, basicBlocks);
+    return computeImpl(codeBlock, instructions);
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.h (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.h	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.h	2020-01-30 22:32:43 UTC (rev 255459)
@@ -26,12 +26,15 @@
 #pragma once
 
 #include "InstructionStream.h"
+#include "Opcode.h"
 #include <limits.h>
 #include <wtf/FastBitVector.h>
+#include <wtf/PackedIntVector.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 
+class BytecodeGraph;
 class CodeBlock;
 class UnlinkedCodeBlock;
 struct Instruction;
@@ -39,13 +42,18 @@
 DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(BytecodeBasicBlock);
 
 class BytecodeBasicBlock {
-    WTF_MAKE_STRUCT_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(BytecodeBasicBlock);
+    WTF_MAKE_FAST_ALLOCATED(BytecodeBasicBlock);
+    WTF_MAKE_NONCOPYABLE(BytecodeBasicBlock);
+    friend class BytecodeGraph;
 public:
+    using BasicBlockVector = Vector<BytecodeBasicBlock, 0, UnsafeVectorOverflow, 16, BytecodeBasicBlockMalloc>;
+    static_assert(maxOpcodeLength <= UINT8_MAX);
     enum SpecialBlockType { EntryBlock, ExitBlock };
-    BytecodeBasicBlock(const InstructionStream::Ref&);
-    BytecodeBasicBlock(SpecialBlockType);
-    void shrinkToFit();
+    inline BytecodeBasicBlock(const InstructionStream::Ref&, unsigned blockIndex);
+    inline BytecodeBasicBlock(SpecialBlockType, unsigned blockIndex);
+    BytecodeBasicBlock(BytecodeBasicBlock&&) = default;
 
+
     bool isEntryBlock() { return !m_leaderOffset && !m_totalLength; }
     bool isExitBlock() { return m_leaderOffset == UINT_MAX && m_totalLength == UINT_MAX; }
 
@@ -52,53 +60,36 @@
     unsigned leaderOffset() const { return m_leaderOffset; }
     unsigned totalLength() const { return m_totalLength; }
 
-    const Vector<InstructionStream::Offset>& offsets() const { return m_offsets; }
+    const Vector<uint8_t>& delta() const { return m_delta; }
+    const Vector<unsigned>& successors() const { return m_successors; }
 
-    const Vector<BytecodeBasicBlock*>& successors() const { return m_successors; }
-
     FastBitVector& in() { return m_in; }
     FastBitVector& out() { return m_out; }
 
     unsigned index() const { return m_index; }
 
-    static void compute(CodeBlock*, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>&);
-    static void compute(UnlinkedCodeBlock*, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>&);
+    explicit operator bool() const { return true; }
 
 private:
-    template<typename Block> static void computeImpl(Block* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks);
+    // Only called from BytecodeGraph.
+    static BasicBlockVector compute(CodeBlock*, const InstructionStream& instructions);
+    static BasicBlockVector compute(UnlinkedCodeBlock*, const InstructionStream& instructions);
+    template<typename Block> static BasicBlockVector computeImpl(Block* codeBlock, const InstructionStream& instructions);
+    void shrinkToFit();
 
-    void addSuccessor(BytecodeBasicBlock* block) { m_successors.append(block); }
+    void addSuccessor(BytecodeBasicBlock& block) { m_successors.append(block.index()); }
 
-    void addLength(unsigned);
+    inline void addLength(unsigned);
 
     InstructionStream::Offset m_leaderOffset;
     unsigned m_totalLength;
     unsigned m_index;
 
-    Vector<InstructionStream::Offset> m_offsets;
-    Vector<BytecodeBasicBlock*> m_successors;
+    Vector<uint8_t> m_delta;
+    Vector<unsigned> m_successors;
 
     FastBitVector m_in;
     FastBitVector m_out;
 };
 
-inline BytecodeBasicBlock::BytecodeBasicBlock(const InstructionStream::Ref& instruction)
-    : m_leaderOffset(instruction.offset())
-    , m_totalLength(instruction->size())
-{
-    m_offsets.append(m_leaderOffset);
-}
-
-inline BytecodeBasicBlock::BytecodeBasicBlock(BytecodeBasicBlock::SpecialBlockType blockType)
-    : m_leaderOffset(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
-    , m_totalLength(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
-{
-}
-
-inline void BytecodeBasicBlock::addLength(unsigned bytecodeLength)
-{
-    m_offsets.append(m_leaderOffset + m_totalLength);
-    m_totalLength += bytecodeLength;
-}
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp	2020-01-30 22:32:43 UTC (rev 255459)
@@ -72,41 +72,38 @@
         , m_generatorFrameSymbolTable(codeBlock->vm(), generatorFrameSymbolTable)
         , m_generatorFrameSymbolTableIndex(generatorFrameSymbolTableIndex)
     {
-        for (BytecodeBasicBlock* block : m_graph) {
-            for (const auto offset : block->offsets()) {
-                const auto instruction = m_instructions.at(offset);
-                switch (instruction->opcodeID()) {
-                case op_enter: {
-                    m_enterPoint = instruction.offset();
-                    break;
-                }
+        for (const auto& instruction : m_instructions) {
+            switch (instruction->opcodeID()) {
+            case op_enter: {
+                m_enterPoint = instruction.offset();
+                break;
+            }
 
-                case op_yield: {
-                    auto bytecode = instruction->as<OpYield>();
-                    unsigned liveCalleeLocalsIndex = bytecode.m_yieldPoint;
-                    if (liveCalleeLocalsIndex >= m_yields.size())
-                        m_yields.resize(liveCalleeLocalsIndex + 1);
-                    YieldData& data = ""
-                    data.point = instruction.offset();
-                    data.argument = bytecode.m_argument;
-                    break;
-                }
+            case op_yield: {
+                auto bytecode = instruction->as<OpYield>();
+                unsigned liveCalleeLocalsIndex = bytecode.m_yieldPoint;
+                if (liveCalleeLocalsIndex >= m_yields.size())
+                    m_yields.resize(liveCalleeLocalsIndex + 1);
+                YieldData& data = ""
+                data.point = instruction.offset();
+                data.argument = bytecode.m_argument;
+                break;
+            }
 
-                case op_create_generator_frame_environment: {
-                    auto bytecode = instruction->as<OpCreateGeneratorFrameEnvironment>();
-                    GeneratorFrameData data;
-                    data.m_point = instruction.offset();
-                    data.m_dst = bytecode.m_dst;
-                    data.m_scope = bytecode.m_scope;
-                    data.m_symbolTable = bytecode.m_symbolTable;
-                    data.m_initialValue = bytecode.m_initialValue;
-                    m_generatorFrameData = WTFMove(data);
-                    break;
-                }
+            case op_create_generator_frame_environment: {
+                auto bytecode = instruction->as<OpCreateGeneratorFrameEnvironment>();
+                GeneratorFrameData data;
+                data.m_point = instruction.offset();
+                data.m_dst = bytecode.m_dst;
+                data.m_scope = bytecode.m_scope;
+                data.m_symbolTable = bytecode.m_symbolTable;
+                data.m_initialValue = bytecode.m_initialValue;
+                m_generatorFrameData = WTFMove(data);
+                break;
+            }
 
-                default:
-                    break;
-                }
+            default:
+                break;
             }
         }
     }

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h	2020-01-30 22:32:43 UTC (rev 255459)
@@ -39,7 +39,7 @@
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(BytecodeGraph);
 public:
-    typedef Vector<std::unique_ptr<BytecodeBasicBlock>> BasicBlocksVector;
+    using BasicBlocksVector = BytecodeBasicBlock::BasicBlockVector;
 
     typedef WTF::IndexedContainerIterator<BytecodeGraph> iterator;
 
@@ -51,10 +51,10 @@
         return WTF::makeIteratorRange(m_basicBlocks.rbegin(), m_basicBlocks.rend());
     }
 
-    static bool blockContainsBytecodeOffset(BytecodeBasicBlock* block, InstructionStream::Offset bytecodeOffset)
+    static bool blockContainsBytecodeOffset(const BytecodeBasicBlock& block, InstructionStream::Offset bytecodeOffset)
     {
-        unsigned leaderOffset = block->leaderOffset();
-        return bytecodeOffset >= leaderOffset && bytecodeOffset < leaderOffset + block->totalLength();
+        unsigned leaderOffset = block.leaderOffset();
+        return bytecodeOffset >= leaderOffset && bytecodeOffset < leaderOffset + block.totalLength();
     }
 
     BytecodeBasicBlock* findBasicBlockForBytecodeOffset(InstructionStream::Offset bytecodeOffset)
@@ -61,43 +61,43 @@
     {
         /*
             for (unsigned i = 0; i < m_basicBlocks.size(); i++) {
-                if (blockContainsBytecodeOffset(m_basicBlocks[i].get(), bytecodeOffset))
-                    return m_basicBlocks[i].get();
+                if (blockContainsBytecodeOffset(m_basicBlocks[i], bytecodeOffset))
+                    return &m_basicBlocks[i];
             }
             return 0;
         */
 
-        std::unique_ptr<BytecodeBasicBlock>* basicBlock = approximateBinarySearch<std::unique_ptr<BytecodeBasicBlock>, unsigned>(m_basicBlocks, m_basicBlocks.size(), bytecodeOffset, [] (std::unique_ptr<BytecodeBasicBlock>* basicBlock) { return (*basicBlock)->leaderOffset(); });
+        BytecodeBasicBlock* basicBlock = approximateBinarySearch<BytecodeBasicBlock, unsigned>(m_basicBlocks, m_basicBlocks.size(), bytecodeOffset, [] (BytecodeBasicBlock* basicBlock) { return basicBlock->leaderOffset(); });
         // We found the block we were looking for.
-        if (blockContainsBytecodeOffset((*basicBlock).get(), bytecodeOffset))
-            return (*basicBlock).get();
+        if (blockContainsBytecodeOffset(*basicBlock, bytecodeOffset))
+            return basicBlock;
 
         // Basic block is to the left of the returned block.
-        if (bytecodeOffset < (*basicBlock)->leaderOffset()) {
+        if (bytecodeOffset < basicBlock->leaderOffset()) {
             ASSERT(basicBlock - 1 >= m_basicBlocks.data());
-            ASSERT(blockContainsBytecodeOffset(basicBlock[-1].get(), bytecodeOffset));
-            return basicBlock[-1].get();
+            ASSERT(blockContainsBytecodeOffset(basicBlock[-1], bytecodeOffset));
+            return &basicBlock[-1];
         }
 
         // Basic block is to the right of the returned block.
         ASSERT(&basicBlock[1] <= &m_basicBlocks.last());
-        ASSERT(blockContainsBytecodeOffset(basicBlock[1].get(), bytecodeOffset));
-        return basicBlock[1].get();
+        ASSERT(blockContainsBytecodeOffset(basicBlock[1], bytecodeOffset));
+        return &basicBlock[1];
     }
 
     BytecodeBasicBlock* findBasicBlockWithLeaderOffset(InstructionStream::Offset leaderOffset)
     {
-        return (*tryBinarySearch<std::unique_ptr<BytecodeBasicBlock>, unsigned>(m_basicBlocks, m_basicBlocks.size(), leaderOffset, [] (std::unique_ptr<BytecodeBasicBlock>* basicBlock) { return (*basicBlock)->leaderOffset(); })).get();
+        return tryBinarySearch<BytecodeBasicBlock, unsigned>(m_basicBlocks, m_basicBlocks.size(), leaderOffset, [] (BytecodeBasicBlock* basicBlock) { return basicBlock->leaderOffset(); });
     }
 
     unsigned size() const { return m_basicBlocks.size(); }
-    BytecodeBasicBlock* at(unsigned index) const { return m_basicBlocks[index].get(); }
-    BytecodeBasicBlock* operator[](unsigned index) const { return at(index); }
+    BytecodeBasicBlock& at(unsigned index) const { return const_cast<BytecodeGraph*>(this)->m_basicBlocks[index]; }
+    BytecodeBasicBlock& operator[](unsigned index) const { return at(index); }
 
-    iterator begin() const { return iterator(*this, 0); }
-    iterator end() const { return iterator(*this, size()); }
-    BytecodeBasicBlock* first() { return at(0); }
-    BytecodeBasicBlock* last() { return at(size() - 1); }
+    iterator begin() { return iterator(*this, 0); }
+    iterator end() { return iterator(*this, size()); }
+    BytecodeBasicBlock& first() { return at(0); }
+    BytecodeBasicBlock& last() { return at(size() - 1); }
 
 private:
     BasicBlocksVector m_basicBlocks;
@@ -106,8 +106,8 @@
 
 template<typename CodeBlockType>
 BytecodeGraph::BytecodeGraph(CodeBlockType* codeBlock, const InstructionStream& instructions)
+    : m_basicBlocks(BytecodeBasicBlock::compute(codeBlock, instructions))
 {
-    BytecodeBasicBlock::compute(codeBlock, instructions, m_basicBlocks);
     ASSERT(m_basicBlocks.size());
 }
 

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp	2020-01-30 22:32:43 UTC (rev 255459)
@@ -53,7 +53,7 @@
     ASSERT(!block->isEntryBlock());
     ASSERT(!block->isExitBlock());
     result.resize(block->out().numBits());
-    computeLocalLivenessForBytecodeIndex(codeBlock, codeBlock->instructions(), m_graph, block, bytecodeIndex, result);
+    computeLocalLivenessForBytecodeIndex(codeBlock, codeBlock->instructions(), m_graph, *block, bytecodeIndex, result);
 }
 
 FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeIndex(CodeBlock* codeBlock, BytecodeIndex bytecodeIndex)
@@ -70,11 +70,11 @@
     result.m_beforeUseVector.resize(codeBlock->instructions().size());
     result.m_afterUseVector.resize(codeBlock->instructions().size());
     
-    for (std::unique_ptr<BytecodeBasicBlock>& block : m_graph.basicBlocksInReverseOrder()) {
-        if (block->isEntryBlock() || block->isExitBlock())
+    for (BytecodeBasicBlock& block : m_graph.basicBlocksInReverseOrder()) {
+        if (block.isEntryBlock() || block.isExitBlock())
             continue;
         
-        out = block->out();
+        out = block.out();
         
         auto use = [&] (unsigned bitIndex) {
             // This is the use functor, so we set the bit.
@@ -87,8 +87,10 @@
         };
 
         auto& instructions = codeBlock->instructions();
-        for (unsigned i = block->offsets().size(); i--;) {
-            BytecodeIndex bytecodeIndex = BytecodeIndex(block->offsets()[i]);
+        unsigned cursor = block.totalLength();
+        for (unsigned i = block.delta().size(); i--;) {
+            cursor -= block.delta()[i];
+            BytecodeIndex bytecodeIndex = BytecodeIndex(block.leaderOffset() + cursor);
 
             stepOverInstructionDef(codeBlock, instructions, m_graph, bytecodeIndex, def);
             stepOverInstructionUseInExceptionHandler(codeBlock, instructions, m_graph, bytecodeIndex, use);
@@ -107,21 +109,23 @@
     result.m_codeBlock = codeBlock;
     result.m_killSets = makeUniqueArray<BytecodeKills::KillSet>(codeBlock->instructions().size());
     
-    for (std::unique_ptr<BytecodeBasicBlock>& block : m_graph.basicBlocksInReverseOrder()) {
-        if (block->isEntryBlock() || block->isExitBlock())
+    for (BytecodeBasicBlock& block : m_graph.basicBlocksInReverseOrder()) {
+        if (block.isEntryBlock() || block.isExitBlock())
             continue;
         
-        out = block->out();
+        out = block.out();
         
-        for (unsigned i = block->offsets().size(); i--;) {
-            unsigned bytecodeOffset = block->offsets()[i];
+        unsigned cursor = block.totalLength();
+        for (unsigned i = block.delta().size(); i--;) {
+            cursor -= block.delta()[i];
+            BytecodeIndex bytecodeIndex = BytecodeIndex(block.leaderOffset() + cursor);
             stepOverInstruction(
-                codeBlock, codeBlock->instructions(), m_graph, BytecodeIndex(bytecodeOffset),
+                codeBlock, codeBlock->instructions(), m_graph, bytecodeIndex,
                 [&] (unsigned index) {
                     // This is for uses.
                     if (out[index])
                         return;
-                    result.m_killSets[bytecodeOffset].add(index);
+                    result.m_killSets[bytecodeIndex.offset()].add(index);
                     out[index] = true;
                 },
                 [&] (unsigned index) {
@@ -140,12 +144,11 @@
 
     unsigned numberOfBlocks = m_graph.size();
     Vector<FastBitVector> predecessors(numberOfBlocks);
-    for (BytecodeBasicBlock* block : m_graph)
-        predecessors[block->index()].resize(numberOfBlocks);
-    for (BytecodeBasicBlock* block : m_graph) {
-        for (unsigned j = 0; j < block->successors().size(); j++) {
-            unsigned blockIndex = block->index();
-            unsigned successorIndex = block->successors()[j]->index();
+    for (BytecodeBasicBlock& block : m_graph)
+        predecessors[block.index()].resize(numberOfBlocks);
+    for (BytecodeBasicBlock& block : m_graph) {
+        for (unsigned successorIndex : block.successors()) {
+            unsigned blockIndex = block.index();
             predecessors[successorIndex][blockIndex] = true;
         }
     }
@@ -157,32 +160,30 @@
         }
     };
 
-    for (BytecodeBasicBlock* block : m_graph) {
-        dataLogF("\nBytecode basic block %u: %p (offset: %u, length: %u)\n", i++, block, block->leaderOffset(), block->totalLength());
+    for (BytecodeBasicBlock& block : m_graph) {
+        dataLogF("\nBytecode basic block %u: %p (offset: %u, length: %u)\n", i++, &block, block.leaderOffset(), block.totalLength());
 
         dataLogF("Predecessors:");
-        dumpBitVector(predecessors[block->index()]);
+        dumpBitVector(predecessors[block.index()]);
         dataLogF("\n");
 
         dataLogF("Successors:");
         FastBitVector successors;
         successors.resize(numberOfBlocks);
-        for (unsigned j = 0; j < block->successors().size(); j++) {
-            BytecodeBasicBlock* successor = block->successors()[j];
-            successors[successor->index()] = true;
-        }
+        for (unsigned successorIndex : block.successors())
+            successors[successorIndex] = true;
         dumpBitVector(successors); // Dump in sorted order.
         dataLogF("\n");
 
-        if (block->isEntryBlock()) {
-            dataLogF("Entry block %p\n", block);
+        if (block.isEntryBlock()) {
+            dataLogF("Entry block %p\n", &block);
             continue;
         }
-        if (block->isExitBlock()) {
-            dataLogF("Exit block: %p\n", block);
+        if (block.isExitBlock()) {
+            dataLogF("Exit block: %p\n", &block);
             continue;
         }
-        for (unsigned bytecodeOffset = block->leaderOffset(); bytecodeOffset < block->leaderOffset() + block->totalLength();) {
+        for (unsigned bytecodeOffset = block.leaderOffset(); bytecodeOffset < block.leaderOffset() + block.totalLength();) {
             const auto currentInstruction = instructions.at(bytecodeOffset);
 
             dataLogF("Live variables:");
@@ -195,7 +196,7 @@
         }
 
         dataLogF("Live variables:");
-        FastBitVector liveAfter = block->out();
+        FastBitVector liveAfter = block.out();
         dumpBitVector(liveAfter);
         dataLogF("\n");
     }

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h	2020-01-30 22:32:43 UTC (rev 255459)
@@ -64,10 +64,10 @@
     static void stepOverInstruction(CodeBlockType*, const InstructionStream&, BytecodeGraph&, BytecodeIndex, FastBitVector& out);
 
     template<typename CodeBlockType, typename Instructions>
-    static bool computeLocalLivenessForBytecodeIndex(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*, BytecodeIndex, FastBitVector& result);
+    static bool computeLocalLivenessForBytecodeIndex(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock&, BytecodeIndex, FastBitVector& result);
 
     template<typename CodeBlockType, typename Instructions>
-    static bool computeLocalLivenessForBlock(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*);
+    static bool computeLocalLivenessForBlock(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock&);
 
     template<typename CodeBlockType, typename Instructions>
     static FastBitVector getLivenessInfoAtBytecodeIndex(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeIndex);

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h	2020-01-30 22:32:43 UTC (rev 255459)
@@ -135,18 +135,20 @@
 }
 
 template<typename CodeBlockType, typename Instructions>
-inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeIndex(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block, BytecodeIndex targetIndex, FastBitVector& result)
+inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeIndex(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock& block, BytecodeIndex targetIndex, FastBitVector& result)
 {
-    ASSERT(!block->isExitBlock());
-    ASSERT(!block->isEntryBlock());
+    ASSERT(!block.isExitBlock());
+    ASSERT(!block.isEntryBlock());
 
-    FastBitVector out = block->out();
+    FastBitVector out = block.out();
 
-    for (int i = block->offsets().size() - 1; i >= 0; i--) {
-        unsigned bytecodeOffset = block->offsets()[i];
-        if (targetIndex.offset() > bytecodeOffset)
+    unsigned cursor = block.totalLength();
+    for (unsigned i = block.delta().size(); i--;) {
+        cursor -= block.delta()[i];
+        BytecodeIndex bytecodeIndex = BytecodeIndex(block.leaderOffset() + cursor);
+        if (targetIndex.offset() > bytecodeIndex.offset())
             break;
-        stepOverInstruction(codeBlock, instructions, graph, BytecodeIndex(bytecodeOffset), out);
+        stepOverInstruction(codeBlock, instructions, graph, bytecodeIndex, out);
     }
 
     return result.setAndCheck(out);
@@ -153,11 +155,11 @@
 }
 
 template<typename CodeBlockType, typename Instructions>
-inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block)
+inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock& block)
 {
-    if (block->isExitBlock() || block->isEntryBlock())
+    if (block.isExitBlock() || block.isEntryBlock())
         return false;
-    return computeLocalLivenessForBytecodeIndex(codeBlock, instructions, graph, block, BytecodeIndex(block->leaderOffset()), block->in());
+    return computeLocalLivenessForBytecodeIndex(codeBlock, instructions, graph, block, BytecodeIndex(block.leaderOffset()), block.in());
 }
 
 template<typename CodeBlockType, typename Instructions>
@@ -169,7 +171,7 @@
     ASSERT(!block->isExitBlock());
     FastBitVector out;
     out.resize(block->out().numBits());
-    computeLocalLivenessForBytecodeIndex(codeBlock, instructions, graph, block, bytecodeIndex, out);
+    computeLocalLivenessForBytecodeIndex(codeBlock, instructions, graph, *block, bytecodeIndex, out);
     return out;
 }
 
@@ -177,27 +179,29 @@
 inline void BytecodeLivenessPropagation::runLivenessFixpoint(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph)
 {
     unsigned numberOfVariables = codeBlock->numCalleeLocals();
-    for (BytecodeBasicBlock* block : graph) {
-        block->in().resize(numberOfVariables);
-        block->out().resize(numberOfVariables);
-        block->in().clearAll();
-        block->out().clearAll();
+    for (BytecodeBasicBlock& block : graph) {
+        block.in().resize(numberOfVariables);
+        block.out().resize(numberOfVariables);
+        block.in().clearAll();
+        block.out().clearAll();
     }
 
     bool changed;
-    BytecodeBasicBlock* lastBlock = graph.last();
-    lastBlock->in().clearAll();
-    lastBlock->out().clearAll();
+    BytecodeBasicBlock& lastBlock = graph.last();
+    lastBlock.in().clearAll();
+    lastBlock.out().clearAll();
     FastBitVector newOut;
-    newOut.resize(lastBlock->out().numBits());
+    newOut.resize(lastBlock.out().numBits());
     do {
         changed = false;
-        for (std::unique_ptr<BytecodeBasicBlock>& block : graph.basicBlocksInReverseOrder()) {
+        for (BytecodeBasicBlock& block : graph.basicBlocksInReverseOrder()) {
             newOut.clearAll();
-            for (BytecodeBasicBlock* successor : block->successors())
-                newOut |= successor->in();
-            block->out() = newOut;
-            changed |= computeLocalLivenessForBlock(codeBlock, instructions, graph, block.get());
+            for (unsigned blockIndex : block.successors()) {
+                BytecodeBasicBlock& successor = graph[blockIndex];
+                newOut |= successor.in();
+            }
+            block.out() = newOut;
+            changed |= computeLocalLivenessForBlock(codeBlock, instructions, graph, block);
         }
     } while (changed);
 }

Modified: trunk/Source/_javascript_Core/bytecode/InstructionStream.h (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/InstructionStream.h	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/InstructionStream.h	2020-01-30 22:32:43 UTC (rev 255459)
@@ -111,7 +111,9 @@
     public:
         Ref freeze() const  { return Ref { m_instructions, m_index }; }
         inline Instruction* operator->() { return unwrap(); }
+        inline const Instruction* operator->() const { return unwrap(); }
         inline Instruction* ptr() { return unwrap(); }
+        inline const Instruction* ptr() const { return unwrap(); }
         inline operator Ref()
         {
             return Ref { m_instructions, m_index };
@@ -119,6 +121,7 @@
 
     private:
         inline Instruction* unwrap() { return reinterpret_cast<Instruction*>(&m_instructions[m_index]); }
+        inline const Instruction* unwrap() const { return reinterpret_cast<const Instruction*>(&m_instructions[m_index]); }
     };
 
 private:

Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (255458 => 255459)


--- trunk/Source/_javascript_Core/bytecode/Opcode.h	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h	2020-01-30 22:32:43 UTC (rev 255459)
@@ -36,6 +36,7 @@
 #include <string.h>
 
 #include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
 
 namespace JSC {
 
@@ -53,7 +54,6 @@
     )
 
 
-const int maxOpcodeLength = 40;
 #if ENABLE(C_LOOP)
 const int numOpcodeIDs = NUMBER_OF_BYTECODE_IDS + NUMBER_OF_CLOOP_BYTECODE_HELPER_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
 #else
@@ -88,6 +88,11 @@
     FOR_EACH_WASM_ID(OPCODE_ID_LENGTHS);
 #undef OPCODE_ID_LENGTHS
 
+static constexpr unsigned maxJSOpcodeLength = /* Opcode */ 1 + /* Wide32 Opcode */ 1 + /* Operands */ (MAX_LENGTH_OF_BYTECODE_IDS - 1) * 4;
+static constexpr unsigned maxWasmOpcodeLength = /* Opcode */ 1 + /* Wide32 Opcode */ 1 + /* Operands */ (MAX_LENGTH_OF_WASM_IDS - 1) * 4;
+static constexpr unsigned maxOpcodeLength = std::max(maxJSOpcodeLength, maxWasmOpcodeLength);
+static constexpr unsigned bitWidthForMaxOpcodeLength = WTF::getMSBSetConstexpr(maxOpcodeLength) + 1;
+
 #define FOR_EACH_OPCODE_WITH_VALUE_PROFILE(macro) \
     macro(OpCallVarargs) \
     macro(OpTailCallVarargs) \

Modified: trunk/Source/_javascript_Core/generator/Section.rb (255458 => 255459)


--- trunk/Source/_javascript_Core/generator/Section.rb	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/generator/Section.rb	2020-01-30 22:32:43 UTC (rev 255459)
@@ -69,6 +69,7 @@
           out << "\n"
 
           out.write("#define NUMBER_OF_#{config[:macro_name_component]}_IDS #{opcodes.length}\n")
+          out.write("#define MAX_LENGTH_OF_#{config[:macro_name_component]}_IDS #{(opcodes.max {|a, b| a.length <=> b.length }).length}\n")
       end
 
       if config[:emit_in_structs_file]

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (255458 => 255459)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2020-01-30 22:32:43 UTC (rev 255459)
@@ -215,7 +215,8 @@
 
             while (BytecodeBasicBlock* block = worklist.pop()) {
                 startBytecodeIndex = BytecodeIndex(std::min(startBytecodeIndex.offset(), block->leaderOffset()));
-                worklist.pushAll(block->successors());
+                for (unsigned successorIndex : block->successors())
+                    worklist.push(&graph[successorIndex]);
 
                 // Also add catch blocks for bytecodes that throw.
                 if (m_codeBlock->numberOfExceptionHandlers()) {

Modified: trunk/Source/_javascript_Core/llint/LLIntData.cpp (255458 => 255459)


--- trunk/Source/_javascript_Core/llint/LLIntData.cpp	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/llint/LLIntData.cpp	2020-01-30 22:32:43 UTC (rev 255459)
@@ -81,7 +81,7 @@
     }
 
     ASSERT(llint_throw_from_slow_path_trampoline < UINT8_MAX);
-    for (int i = 0; i < maxOpcodeLength + 1; ++i) {
+    for (unsigned i = 0; i < maxOpcodeLength + 1; ++i) {
         Data::s_exceptionInstructions[i] = llint_throw_from_slow_path_trampoline;
         Data::s_wasmExceptionInstructions[i] = wasm_throw_from_slow_path_trampoline;
     }

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp (255458 => 255459)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp	2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp	2020-01-30 22:32:43 UTC (rev 255459)
@@ -280,7 +280,7 @@
         // initialized the opcodeMap above. This is because getCodePtr()
         // can depend on the opcodeMap.
         uint8_t* exceptionInstructions = reinterpret_cast<uint8_t*>(LLInt::exceptionInstructions());
-        for (int i = 0; i < maxOpcodeLength + 1; ++i)
+        for (unsigned i = 0; i < maxOpcodeLength + 1; ++i)
             exceptionInstructions[i] = llint_throw_from_slow_path_trampoline;
 
         return JSValue();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to