Changeset 181467 in webkit
- Timestamp:
- Mar 12, 2015, 6:57:59 PM (10 years ago)
- Location:
- trunk/Source
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r181466 r181467 1 2015-03-12 Filip Pizlo <fpizlo@apple.com> 2 3 Bytecode liveness analysis should have more lambdas and fewer sets 4 https://bugs.webkit.org/show_bug.cgi?id=142647 5 6 Reviewed by Mark Lam. 7 8 In bug 141174 I'll need to identify all of the bytecode kill sites. This requires hooking into 9 the bytecode analysis' stepOverFunction method, except in such a way that we observe uses that 10 are not in outs. This refactors stepOverFunction so that you can pass it use/def functors that 11 can either be used to propagate outs (as we do right now) or to additionally detect kills or 12 whatever else. 13 14 In order to achieve this, the liveness analysis was moved off of maintaining uses/defs 15 bitvectors. This wasn't helping the abstraction and was probably inefficient. The new code 16 should be a bit faster since we don't have to clear uses/defs bitvectors on each instruction. On 17 the other hand, being able to intercept each use means that our code for exception handlers is 18 no longer a bitwise-merge; it requires finding set bits. Fortunately, this code only kicks in 19 for instructions inside a try, and its performance is O(live at catch), so that's probably not 20 bad. 21 22 * bytecode/BytecodeLivenessAnalysis.cpp: 23 (JSC::indexForOperand): 24 (JSC::stepOverInstruction): 25 (JSC::computeLocalLivenessForBytecodeOffset): 26 (JSC::BytecodeLivenessAnalysis::computeFullLiveness): 27 (JSC::setForOperand): Deleted. 28 * bytecode/BytecodeUseDef.h: 29 (JSC::computeUsesForBytecodeOffset): 30 (JSC::computeDefsForBytecodeOffset): 31 * bytecode/CodeBlock.cpp: 32 1 33 2015-03-12 Ryosuke Niwa <rniwa@webkit.org> 2 34 -
trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp
r159943 r181467 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 59 59 } 60 60 61 static void setForOperand(CodeBlock* codeBlock, FastBitVector& bits, int operand)61 static unsigned indexForOperand(CodeBlock* codeBlock, int operand) 62 62 { 63 63 ASSERT(isValidRegisterForLiveness(codeBlock, operand)); 64 64 VirtualRegister virtualReg(operand); 65 65 if (virtualReg.offset() > codeBlock->captureStart()) 66 bits.set(virtualReg.toLocal()); 67 else 68 bits.set(virtualReg.toLocal() - codeBlock->captureCount()); 69 } 70 71 namespace { 72 73 class SetBit { 74 public: 75 SetBit(FastBitVector& bits) 76 : m_bits(bits) 77 { 78 } 79 80 void operator()(CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) 81 { 82 if (isValidRegisterForLiveness(codeBlock, operand)) 83 setForOperand(codeBlock, m_bits, operand); 84 } 85 86 private: 87 FastBitVector& m_bits; 88 }; 89 90 } // anonymous namespace 66 return virtualReg.toLocal(); 67 return virtualReg.toLocal() - codeBlock->captureCount(); 68 } 91 69 92 70 static unsigned getLeaderOffsetForBasicBlock(RefPtr<BytecodeBasicBlock>* basicBlock) … … 134 112 } 135 113 136 static void stepOverInstruction(CodeBlock* codeBlock, Vector<RefPtr<BytecodeBasicBlock>>& basicBlocks, unsigned bytecodeOffset, FastBitVector& uses, FastBitVector& defs, FastBitVector& out) 137 { 138 uses.clearAll(); 139 defs.clearAll(); 140 141 SetBit setUses(uses); 142 SetBit setDefs(defs); 143 computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, setUses); 144 computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, setDefs); 145 146 out.exclude(defs); 147 out.merge(uses); 148 114 // Simplified interface to bytecode use/def, which determines defs first and then uses, and includes 115 // exception handlers in the uses. 116 template<typename UseFunctor, typename DefFunctor> 117 static void stepOverInstruction(CodeBlock* codeBlock, Vector<RefPtr<BytecodeBasicBlock>>& basicBlocks, unsigned bytecodeOffset, const UseFunctor& use, const DefFunctor& def) 118 { 119 // This abstractly execute the instruction in reverse. Instructions logically first use operands and 120 // then define operands. This logical ordering is necessary for operations that use and def the same 121 // operand, like: 122 // 123 // op_add loc1, loc1, loc2 124 // 125 // The use of loc1 happens before the def of loc1. That's a semantic requirement since the add 126 // operation cannot travel forward in time to read the value that it will produce after reading that 127 // value. Since we are executing in reverse, this means that we must do defs before uses (reverse of 128 // uses before defs). 129 // 130 // Since this is a liveness analysis, this ordering ends up being particularly important: if we did 131 // uses before defs, then the add operation above would appear to not have loc1 live, since we'd 132 // first add it to the out set (the use), and then we'd remove it (the def). 133 134 computeDefsForBytecodeOffset( 135 codeBlock, bytecodeOffset, 136 [&] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) { 137 if (isValidRegisterForLiveness(codeBlock, operand)) 138 def(indexForOperand(codeBlock, operand)); 139 }); 140 141 computeUsesForBytecodeOffset( 142 codeBlock, bytecodeOffset, 143 [&] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) { 144 if (isValidRegisterForLiveness(codeBlock, operand)) 145 use(indexForOperand(codeBlock, operand)); 146 }); 147 149 148 // If we have an exception handler, we want the live-in variables of the 150 149 // exception handler block to be included in the live-in of this particular bytecode. … … 152 151 BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler->target); 153 152 ASSERT(handlerBlock); 154 out.merge(handlerBlock->in()); 155 } 153 handlerBlock->in().forEachSetBit(use); 154 } 155 } 156 157 static void stepOverInstruction(CodeBlock* codeBlock, Vector<RefPtr<BytecodeBasicBlock>>& basicBlocks, unsigned bytecodeOffset, FastBitVector& out) 158 { 159 stepOverInstruction( 160 codeBlock, basicBlocks, bytecodeOffset, 161 [&] (unsigned bitIndex) { 162 // This is the use functor, so we set the bit. 163 out.set(bitIndex); 164 }, 165 [&] (unsigned bitIndex) { 166 // This is the def functor, so we clear the bit. 167 out.clear(bitIndex); 168 }); 156 169 } 157 170 … … 162 175 163 176 FastBitVector out = block->out(); 164 165 FastBitVector uses;166 FastBitVector defs;167 uses.resize(out.numBits());168 defs.resize(out.numBits());169 177 170 178 for (int i = block->bytecodeOffsets().size() - 1; i >= 0; i--) { … … 173 181 break; 174 182 175 stepOverInstruction(codeBlock, basicBlocks, bytecodeOffset, uses, defs,out);183 stepOverInstruction(codeBlock, basicBlocks, bytecodeOffset, out); 176 184 } 177 185 … … 278 286 { 279 287 FastBitVector out; 280 FastBitVector uses;281 FastBitVector defs;282 288 283 289 result.m_codeBlock = m_codeBlock; … … 290 296 291 297 out = block->out(); 292 uses.resize(out.numBits());293 defs.resize(out.numBits());294 298 295 299 for (unsigned i = block->bytecodeOffsets().size(); i--;) { 296 300 unsigned bytecodeOffset = block->bytecodeOffsets()[i]; 297 stepOverInstruction(m_codeBlock, m_basicBlocks, bytecodeOffset, uses, defs,out);301 stepOverInstruction(m_codeBlock, m_basicBlocks, bytecodeOffset, out); 298 302 result.m_map.add(bytecodeOffset, out); 299 303 } -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
r181466 r181467 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 template<typename Functor> 34 34 void computeUsesForBytecodeOffset( 35 CodeBlock* codeBlock, unsigned bytecodeOffset, Functor& functor)35 CodeBlock* codeBlock, unsigned bytecodeOffset, const Functor& functor) 36 36 { 37 37 Interpreter* interpreter = codeBlock->vm()->interpreter; … … 236 236 237 237 template<typename Functor> 238 void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Functor& functor)238 void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, const Functor& functor) 239 239 { 240 240 Interpreter* interpreter = codeBlock->vm()->interpreter; -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r181466 r181467 3882 3882 3883 3883 struct VerifyCapturedDef { 3884 void operator()(CodeBlock* codeBlock, Instruction* instruction, OpcodeID opcodeID, int operand) 3884 void operator()(CodeBlock* codeBlock, Instruction* instruction, OpcodeID opcodeID, int operand) const 3885 3885 { 3886 3886 unsigned bytecodeOffset = instruction - codeBlock->instructions().begin(); -
trunk/Source/WTF/ChangeLog
r181462 r181467 1 2015-03-12 Filip Pizlo <fpizlo@apple.com> 2 3 Bytecode liveness analysis should have more lambdas and fewer sets 4 https://bugs.webkit.org/show_bug.cgi?id=142647 5 6 Reviewed by Mark Lam. 7 8 Add a method for iterating each set bit in a FastBitVector. Uses a functor as a callback since 9 this allows for a more efficient algorithm. 10 11 * wtf/FastBitVector.h: 12 (WTF::FastBitVector::forEachSetBit): 13 1 14 2015-03-12 Michael Saboff <msaboff@apple.com> 2 15 -
trunk/Source/WTF/wtf/FastBitVector.h
r159825 r181467 178 178 } 179 179 180 template<typename Functor> 181 void forEachSetBit(const Functor& functor) 182 { 183 unsigned n = arrayLength(); 184 for (unsigned i = 0; i < n; ++i) { 185 uint32_t word = m_array[i]; 186 unsigned j = i << 5; 187 while (word) { 188 if (word & 1) 189 functor(j); 190 word >>= 1; 191 j++; 192 } 193 } 194 } 195 180 196 WTF_EXPORT_PRIVATE void dump(PrintStream&) const; 181 197
Note:
See TracChangeset
for help on using the changeset viewer.