Changeset 224138 in webkit
- Timestamp:
- Oct 27, 2017 6:03:22 PM (6 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r224136 r224138 1 2017-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 1 77 2017-10-27 Keith Miller <keith_miller@apple.com> 2 78 -
trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp
r221551 r224138 54 54 55 55 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) 57 59 , m_generatorFrameSymbolTable(*codeBlock->vm(), generatorFrameSymbolTable) 58 60 , m_generatorFrameSymbolTableIndex(generatorFrameSymbolTableIndex) … … 60 62 for (BytecodeBasicBlock* block : m_graph) { 61 63 for (unsigned bytecodeOffset : block->offsets()) { 62 const UnlinkedInstruction* pc = & m_graph.instructions()[bytecodeOffset];64 const UnlinkedInstruction* pc = &instructions[bytecodeOffset]; 63 65 switch (pc->u.opcode) { 64 66 case op_enter: { … … 92 94 void run(); 93 95 94 BytecodeGraph <UnlinkedCodeBlock>& graph() { return m_graph; }96 BytecodeGraph& graph() { return m_graph; } 95 97 96 98 const Yields& yields() const … … 122 124 return *storage; 123 125 124 UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();125 126 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); 128 129 ScopeOffset scopeOffset = m_generatorFrameSymbolTable->takeNextScopeOffset(NoLockingNecessary); 129 130 m_generatorFrameSymbolTable->set(NoLockingNecessary, identifier.impl(), SymbolTableEntry(VarOffset(scopeOffset))); … … 139 140 140 141 unsigned m_enterPoint { 0 }; 141 BytecodeGraph<UnlinkedCodeBlock> m_graph; 142 UnlinkedCodeBlock* m_codeBlock; 143 UnlinkedCodeBlock::UnpackedInstructions& m_instructions; 144 BytecodeGraph m_graph; 142 145 Vector<std::optional<Storage>> m_storages; 143 146 Yields m_yields; … … 153 156 } 154 157 155 void run( )158 void run(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions) 156 159 { 157 160 // Perform modified liveness analysis to determine which locals are live at the merge points. 158 161 // This produces the conservative results for the question, "which variables should be saved and resumed?". 159 162 160 runLivenessFixpoint( m_generatorification.graph());163 runLivenessFixpoint(codeBlock, instructions, m_generatorification.graph()); 161 164 162 165 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)); 164 167 } 165 168 … … 174 177 { 175 178 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); 181 183 182 184 // Setup the global switch for the generator. 183 185 { 184 186 unsigned nextToEnterPoint = enterPoint() + opcodeLength(op_enter); 185 unsigned switchTableIndex = m_ graph.codeBlock()->numberOfSwitchJumpTables();187 unsigned switchTableIndex = m_codeBlock->numberOfSwitchJumpTables(); 186 188 VirtualRegister state = virtualRegisterForArgument(static_cast<int32_t>(JSGeneratorFunction::GeneratorArgument::State)); 187 auto& jumpTable = m_ graph.codeBlock()->addSwitchJumpTable();189 auto& jumpTable = m_codeBlock->addSwitchJumpTable(); 188 190 jumpTable.min = 0; 189 191 jumpTable.branchOffsets.resize(m_yields.size() + 1); … … 228 230 Storage storage = storageForGeneratorLocal(index); 229 231 230 UnlinkedValueProfile profile = codeBlock->addValueProfile();232 UnlinkedValueProfile profile = m_codeBlock->addValueProfile(); 231 233 fragment.appendInstruction( 232 234 op_get_from_scope, -
trunk/Source/JavaScriptCore/bytecode/BytecodeGraph.h
r204994 r224138 36 36 class BytecodeBasicBlock; 37 37 38 template<typename Block>39 38 class BytecodeGraph { 40 39 WTF_MAKE_FAST_ALLOCATED; 41 40 WTF_MAKE_NONCOPYABLE(BytecodeGraph); 42 41 public: 43 typedef Block CodeBlock;44 typedef typename Block::Instruction Instruction;45 42 typedef Vector<std::unique_ptr<BytecodeBasicBlock>> BasicBlocksVector; 46 43 47 typedef WTF::IndexedContainerIterator<BytecodeGraph <Block>> iterator;44 typedef WTF::IndexedContainerIterator<BytecodeGraph> iterator; 48 45 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&); 54 48 55 49 WTF::IteratorRange<BasicBlocksVector::reverse_iterator> basicBlocksInReverseOrder() … … 107 101 108 102 private: 109 Block* m_codeBlock;110 103 BasicBlocksVector m_basicBlocks; 111 typename Block::UnpackedInstructions& m_instructions;112 104 }; 113 105 114 106 115 template<typename Block> 116 BytecodeGraph<Block>::BytecodeGraph(Block* codeBlock, typename Block::UnpackedInstructions& instructions) 117 : m_codeBlock(codeBlock) 118 , m_instructions(instructions) 107 template<typename CodeBlockType> 108 BytecodeGraph::BytecodeGraph(CodeBlockType* codeBlock, typename CodeBlockType::UnpackedInstructions& instructions) 119 109 { 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); 122 111 ASSERT(m_basicBlocks.size()); 123 112 } -
trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp
r221551 r224138 41 41 : m_graph(codeBlock, codeBlock->instructions()) 42 42 { 43 compute(); 43 runLivenessFixpoint(codeBlock, codeBlock->instructions(), m_graph); 44 45 if (Options::dumpBytecodeLivenessResults()) 46 dumpResults(codeBlock); 44 47 } 45 48 46 void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset( unsigned bytecodeOffset, FastBitVector& result)49 void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& result) 47 50 { 48 51 BytecodeBasicBlock* block = m_graph.findBasicBlockForBytecodeOffset(bytecodeOffset); … … 51 54 ASSERT(!block->isExitBlock()); 52 55 result.resize(block->out().numBits()); 53 computeLocalLivenessForBytecodeOffset( m_graph, block, bytecodeOffset, result);56 computeLocalLivenessForBytecodeOffset(codeBlock, codeBlock->instructions(), m_graph, block, bytecodeOffset, result); 54 57 } 55 58 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) 59 FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset) 66 60 { 67 61 FastBitVector out; 68 getLivenessInfoAtBytecodeOffset( bytecodeOffset, out);62 getLivenessInfoAtBytecodeOffset(codeBlock, bytecodeOffset, out); 69 63 return out; 70 64 } 71 65 72 void BytecodeLivenessAnalysis::computeFullLiveness( FullBytecodeLiveness& result)66 void BytecodeLivenessAnalysis::computeFullLiveness(CodeBlock* codeBlock, FullBytecodeLiveness& result) 73 67 { 74 68 FastBitVector out; 75 CodeBlock* codeBlock = m_graph.codeBlock(); 76 69 77 70 result.m_map.resize(codeBlock->instructions().size()); 78 71 … … 85 78 for (unsigned i = block->offsets().size(); i--;) { 86 79 unsigned bytecodeOffset = block->offsets()[i]; 87 stepOverInstruction( m_graph, bytecodeOffset, out);80 stepOverInstruction(codeBlock, codeBlock->instructions(), m_graph, bytecodeOffset, out); 88 81 result.m_map[bytecodeOffset] = out; 89 82 } … … 91 84 } 92 85 93 void BytecodeLivenessAnalysis::computeKills( BytecodeKills& result)86 void BytecodeLivenessAnalysis::computeKills(CodeBlock* codeBlock, BytecodeKills& result) 94 87 { 88 UNUSED_PARAM(result); 95 89 FastBitVector out; 96 97 CodeBlock* codeBlock = m_graph.codeBlock(); 90 98 91 result.m_codeBlock = codeBlock; 99 92 result.m_killSets = std::make_unique<BytecodeKills::KillSet[]>(codeBlock->instructions().size()); … … 108 101 unsigned bytecodeOffset = block->offsets()[i]; 109 102 stepOverInstruction( 110 m_graph, bytecodeOffset,103 codeBlock, codeBlock->instructions(), m_graph, bytecodeOffset, 111 104 [&] (unsigned index) { 112 105 // This is for uses. … … 124 117 } 125 118 126 void BytecodeLivenessAnalysis::dumpResults( )119 void BytecodeLivenessAnalysis::dumpResults(CodeBlock* codeBlock) 127 120 { 128 CodeBlock* codeBlock = m_graph.codeBlock();129 121 dataLog("\nDumping bytecode liveness for ", *codeBlock, ":\n"); 130 122 Instruction* instructionsBegin = codeBlock->instructions().begin(); … … 179 171 180 172 dataLogF("Live variables:"); 181 FastBitVector liveBefore = getLivenessInfoAtBytecodeOffset( bytecodeOffset);173 FastBitVector liveBefore = getLivenessInfoAtBytecodeOffset(codeBlock, bytecodeOffset); 182 174 dumpBitVector(liveBefore); 183 175 dataLogF("\n"); … … 196 188 } 197 189 198 void BytecodeLivenessAnalysis::compute()199 {200 runLivenessFixpoint(m_graph);201 202 if (Options::dumpBytecodeLivenessResults())203 dumpResults();204 }205 206 190 } // namespace JSC -
trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h
r221551 r224138 38 38 class BytecodeLivenessPropagation { 39 39 protected: 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&); 41 41 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); 43 43 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); 45 45 46 template<typename Graph> bool computeLocalLivenessForBlock(Graph&, BytecodeBasicBlock*);46 template<typename CodeBlockType, typename Instructions> bool computeLocalLivenessForBlock(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*); 47 47 48 template<typename Graph> FastBitVector getLivenessInfoAtBytecodeOffset(Graph&, unsigned bytecodeOffset);48 template<typename CodeBlockType, typename Instructions> FastBitVector getLivenessInfoAtBytecodeOffset(CodeBlockType*, const Instructions&, BytecodeGraph&, unsigned bytecodeOffset); 49 49 50 template<typename Graph> void runLivenessFixpoint(Graph&);50 template<typename CodeBlockType, typename Instructions> void runLivenessFixpoint(CodeBlockType*, const Instructions&, BytecodeGraph&); 51 51 }; 52 52 … … 58 58 BytecodeLivenessAnalysis(CodeBlock*); 59 59 60 bool operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset); 61 FastBitVector getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset); 60 FastBitVector getLivenessInfoAtBytecodeOffset(CodeBlock*, unsigned bytecodeOffset); 62 61 63 void computeFullLiveness( FullBytecodeLiveness& result);64 void computeKills( BytecodeKills& result);62 void computeFullLiveness(CodeBlock*, FullBytecodeLiveness& result); 63 void computeKills(CodeBlock*, BytecodeKills& result); 65 64 66 65 private: 67 void compute(); 68 void dumpResults(); 66 void dumpResults(CodeBlock*); 69 67 70 void getLivenessInfoAtBytecodeOffset( unsigned bytecodeOffset, FastBitVector&);68 void getLivenessInfoAtBytecodeOffset(CodeBlock*, unsigned bytecodeOffset, FastBitVector&); 71 69 72 BytecodeGraph <CodeBlock>m_graph;70 BytecodeGraph m_graph; 73 71 }; 74 72 -
trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h
r221551 r224138 62 62 // Simplified interface to bytecode use/def, which determines defs first and then uses, and includes 63 63 // 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)64 template<typename CodeBlockType, typename Instructions, typename UseFunctor, typename DefFunctor> 65 inline void BytecodeLivenessPropagation::stepOverInstruction(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset, const UseFunctor& use, const DefFunctor& def) 66 66 { 67 67 // This abstractly execute the instruction in reverse. Instructions logically first use operands and … … 80 80 // first add it to the out set (the use), and then we'd remove it (the def). 81 81 82 auto* codeBlock = graph.codeBlock(); 83 auto* instructionsBegin = graph.instructions().begin(); 82 auto* instructionsBegin = instructions.begin(); 84 83 auto* instruction = &instructionsBegin[bytecodeOffset]; 85 84 OpcodeID opcodeID = Interpreter::getOpcodeID(*instruction); … … 87 86 computeDefsForBytecodeOffset( 88 87 codeBlock, opcodeID, instruction, 89 [&] ( typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) {88 [&] (CodeBlockType*, const typename CodeBlockType::Instruction*, OpcodeID, int operand) { 90 89 if (isValidRegisterForLiveness(operand)) 91 90 def(VirtualRegister(operand).toLocal()); … … 94 93 computeUsesForBytecodeOffset( 95 94 codeBlock, opcodeID, instruction, 96 [&] ( typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) {95 [&] (CodeBlockType*, const typename CodeBlockType::Instruction*, OpcodeID, int operand) { 97 96 if (isValidRegisterForLiveness(operand)) 98 97 use(VirtualRegister(operand).toLocal()); … … 108 107 } 109 108 110 template<typename Graph>111 inline void BytecodeLivenessPropagation::stepOverInstruction( Graph& graph, unsigned bytecodeOffset, FastBitVector& out)109 template<typename CodeBlockType, typename Instructions> 110 inline void BytecodeLivenessPropagation::stepOverInstruction(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset, FastBitVector& out) 112 111 { 113 112 stepOverInstruction( 114 graph, bytecodeOffset,113 codeBlock, instructions, graph, bytecodeOffset, 115 114 [&] (unsigned bitIndex) { 116 115 // This is the use functor, so we set the bit. … … 123 122 } 124 123 125 template<typename Graph>126 inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset( Graph& graph, BytecodeBasicBlock* block, unsigned targetOffset, FastBitVector& result)124 template<typename CodeBlockType, typename Instructions> 125 inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block, unsigned targetOffset, FastBitVector& result) 127 126 { 128 127 ASSERT(!block->isExitBlock()); … … 135 134 if (targetOffset > bytecodeOffset) 136 135 break; 137 stepOverInstruction( graph, bytecodeOffset, out);136 stepOverInstruction(codeBlock, instructions, graph, bytecodeOffset, out); 138 137 } 139 138 … … 141 140 } 142 141 143 template<typename Graph>144 inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock( Graph& graph, BytecodeBasicBlock* block)142 template<typename CodeBlockType, typename Instructions> 143 inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block) 145 144 { 146 145 if (block->isExitBlock() || block->isEntryBlock()) 147 146 return false; 148 return computeLocalLivenessForBytecodeOffset( graph, block, block->leaderOffset(), block->in());147 return computeLocalLivenessForBytecodeOffset(codeBlock, instructions, graph, block, block->leaderOffset(), block->in()); 149 148 } 150 149 151 template<typename Graph>152 inline FastBitVector BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset( Graph& graph, unsigned bytecodeOffset)150 template<typename CodeBlockType, typename Instructions> 151 inline FastBitVector BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset) 153 152 { 154 153 BytecodeBasicBlock* block = graph.findBasicBlockForBytecodeOffset(bytecodeOffset); … … 158 157 FastBitVector out; 159 158 out.resize(block->out().numBits()); 160 computeLocalLivenessForBytecodeOffset( graph, block, bytecodeOffset, out);159 computeLocalLivenessForBytecodeOffset(codeBlock, instructions, graph, block, bytecodeOffset, out); 161 160 return out; 162 161 } 163 162 164 template<typename Graph>165 inline void BytecodeLivenessPropagation::runLivenessFixpoint( Graph& graph)163 template<typename CodeBlockType, typename Instructions> 164 inline void BytecodeLivenessPropagation::runLivenessFixpoint(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph) 166 165 { 167 auto* codeBlock = graph.codeBlock();168 166 unsigned numberOfVariables = codeBlock->numCalleeLocals(); 169 167 for (BytecodeBasicBlock* block : graph) { … … 187 185 newOut |= successor->in(); 188 186 block->out() = newOut; 189 changed |= computeLocalLivenessForBlock( graph, block.get());187 changed |= computeLocalLivenessForBlock(codeBlock, instructions, graph, block.get()); 190 188 } 191 189 } while (changed); -
trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp
r218412 r224138 39 39 Insertion& insertion = m_insertions[insertionIndex]; 40 40 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()); 42 42 else { 43 43 if (insertion.includeBranch == IncludeBranch::Yes) { … … 45 45 adjustJumpTargetsInFragment(finalOffset, insertion); 46 46 } 47 m_ graph.instructions().insertVector(insertion.index.bytecodeOffset, insertion.instructions);47 m_instructions.insertVector(insertion.index.bytecodeOffset, insertion.instructions); 48 48 } 49 49 } … … 57 57 }); 58 58 59 UnlinkedCodeBlock* codeBlock = m_graph.codeBlock(); 60 codeBlock->applyModification(*this); 59 m_codeBlock->applyModification(*this, m_instructions); 61 60 } 62 61 … … 70 69 if (isBranch(opcodeID)) { 71 70 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) { 74 72 int absoluteOffset = adjustAbsoluteOffset(label); 75 73 label = absoluteOffset - static_cast<int>(bytecodeOffset); -
trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.h
r204994 r224138 162 162 }; 163 163 164 BytecodeRewriter(BytecodeGraph <UnlinkedCodeBlock>& graph)164 BytecodeRewriter(BytecodeGraph& graph, UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions) 165 165 : m_graph(graph) 166 , m_codeBlock(codeBlock) 167 , m_instructions(instructions) 166 168 { 167 169 } … … 189 191 void removeBytecode(unsigned bytecodeOffset) 190 192 { 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), { } }); 192 194 } 193 195 194 196 void execute(); 195 197 196 BytecodeGraph <UnlinkedCodeBlock>& graph() { return m_graph; }198 BytecodeGraph& graph() { return m_graph; } 197 199 198 200 int adjustAbsoluteOffset(int absoluteOffset) … … 216 218 template<typename Iterator> int calculateDifference(Iterator begin, Iterator end); 217 219 218 BytecodeGraph<UnlinkedCodeBlock>& m_graph; 220 BytecodeGraph& m_graph; 221 UnlinkedCodeBlock* m_codeBlock; 222 UnlinkedCodeBlock::UnpackedInstructions& m_instructions; 219 223 Vector<Insertion, 8> m_insertions; 220 224 }; -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r223727 r224138 399 399 } 400 400 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. 401 409 bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, 402 410 JSScope* scope) 403 411 { 404 412 Base::finishCreation(vm); 413 405 414 auto throwScope = DECLARE_THROW_SCOPE(vm); 406 415 … … 1720 1729 // we can avoid profiling them and extracting them when doing OSR entry 1721 1730 // into the DFG. 1722 FastBitVector liveLocals = bytecodeLiveness.getLivenessInfoAtBytecodeOffset( bytecodeOffset + OPCODE_LENGTH(op_catch));1731 FastBitVector liveLocals = bytecodeLiveness.getLivenessInfoAtBytecodeOffset(this, bytecodeOffset + OPCODE_LENGTH(op_catch)); 1723 1732 Vector<VirtualRegister> liveOperands; 1724 1733 liveOperands.reserveInitialCapacity(liveLocals.bitCount()); … … 2853 2862 BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint. 2854 2863 2855 FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset( 0);2864 FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(this, 0); 2856 2865 2857 2866 if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeLocals)) { … … 3227 3236 } 3228 3237 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 3240 3238 void setPrinter(Printer::PrintRecord& record, CodeBlock* codeBlock) 3241 3239 { -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r223989 r224138 116 116 117 117 public: 118 118 119 enum CopyParsedBlockTag { CopyParsedBlock }; 119 120 … … 601 602 BytecodeLivenessAnalysis& livenessAnalysis() 602 603 { 603 { 604 ConcurrentJSLocker locker(m_lock); 605 if (!!m_livenessAnalysis) 606 return *m_livenessAnalysis; 607 } 608 return livenessAnalysisSlow(); 604 return m_unlinkedCode->livenessAnalysis(this); 609 605 } 610 606 … … 1060 1056 std::chrono::steady_clock::time_point m_creationTime; 1061 1057 1062 std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis;1063 1064 1058 std::unique_ptr<RareData> m_rareData; 1065 1059 -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
r223989 r224138 29 29 30 30 #include "BytecodeGenerator.h" 31 #include "BytecodeLivenessAnalysis.h" 31 32 #include "BytecodeRewriter.h" 32 33 #include "ClassInfo.h" … … 340 341 } 341 342 342 void UnlinkedCodeBlock::applyModification(BytecodeRewriter& rewriter )343 void UnlinkedCodeBlock::applyModification(BytecodeRewriter& rewriter, UnpackedInstructions& instructions) 343 344 { 344 345 // Before applying the changes, we adjust the jumps based on the original bytecode offset, the offset to the jump target, and 345 346 // the insertion information. 346 347 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;) { 351 351 UnlinkedInstruction* current = instructionsBegin + bytecodeOffset; 352 352 OpcodeID opcodeID = current[0].u.opcode; … … 387 387 // And recompute the jump target based on the modified unlinked instructions. 388 388 m_jumpTargets.clear(); 389 recomputePreciseJumpTargets(this, graph.instructions().begin(), graph.instructions().size(), m_jumpTargets);389 recomputePreciseJumpTargets(this, instructions.begin(), instructions.size(), m_jumpTargets); 390 390 } 391 391 … … 419 419 } 420 420 421 BytecodeLivenessAnalysis& 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 421 438 } // namespace JSC -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
r223989 r224138 47 47 namespace JSC { 48 48 49 class BytecodeLivenessAnalysis; 49 50 class BytecodeRewriter; 51 class CodeBlock; 50 52 class Debugger; 51 53 class FunctionExecutable; … … 396 398 void dump(PrintStream&) const; 397 399 400 BytecodeLivenessAnalysis& livenessAnalysis(CodeBlock* codeBlock) 401 { 402 if (m_liveness) 403 return *m_liveness; 404 return livenessAnalysisSlow(codeBlock); 405 } 406 398 407 protected: 399 408 UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode); … … 407 416 private: 408 417 friend class BytecodeRewriter; 409 void applyModification(BytecodeRewriter& );418 void applyModification(BytecodeRewriter&, UnpackedInstructions&); 410 419 411 420 void createRareDataIfNecessary() … … 418 427 419 428 void getLineAndColumn(const ExpressionRangeInfo&, unsigned& line, unsigned& column) const; 429 BytecodeLivenessAnalysis& livenessAnalysisSlow(CodeBlock*); 420 430 421 431 int m_numParameters; 422 432 423 433 std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions; 434 std::unique_ptr<BytecodeLivenessAnalysis> m_liveness; 424 435 425 436 VirtualRegister m_thisRegister; … … 446 457 unsigned m_endColumn; 447 458 459 Lock m_lock; 448 460 TriState m_didOptimize; 449 461 SourceParseMode m_parseMode; -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r223614 r224138 1087 1087 1088 1088 std::unique_ptr<FullBytecodeLiveness> liveness = std::make_unique<FullBytecodeLiveness>(); 1089 codeBlock->livenessAnalysis().computeFullLiveness( *liveness);1089 codeBlock->livenessAnalysis().computeFullLiveness(codeBlock, *liveness); 1090 1090 FullBytecodeLiveness& result = *liveness; 1091 1091 m_bytecodeLiveness.add(codeBlock, WTFMove(liveness)); … … 1105 1105 1106 1106 std::unique_ptr<BytecodeKills> kills = std::make_unique<BytecodeKills>(); 1107 codeBlock->livenessAnalysis().computeKills( *kills);1107 codeBlock->livenessAnalysis().computeKills(codeBlock, *kills); 1108 1108 BytecodeKills& result = *kills; 1109 1109 m_bytecodeKills.add(codeBlock, WTFMove(kills)); -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r223086 r224138 698 698 return; 699 699 700 FastBitVector liveness = codeBlock->alternative()->livenessAnalysis().getLivenessInfoAtBytecodeOffset(osrEntryBytecodeIndex); 700 CodeBlock* alternative = codeBlock->alternative(); 701 FastBitVector liveness = alternative->livenessAnalysis().getLivenessInfoAtBytecodeOffset(alternative, osrEntryBytecodeIndex); 701 702 702 703 for (unsigned local = mustHandleValues.numberOfLocals(); local--;) { -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r223823 r224138 196 196 // compile code from that bytecode offset onwards. 197 197 198 BytecodeGraph <CodeBlock>graph(m_codeBlock, m_instructions);198 BytecodeGraph graph(m_codeBlock, m_instructions); 199 199 BytecodeBasicBlock* block = graph.findBasicBlockForBytecodeOffset(m_loopOSREntryBytecodeOffset); 200 200 RELEASE_ASSERT(block);
Note: See TracChangeset
for help on using the changeset viewer.