Changeset 96372 in webkit
- Timestamp:
- Sep 29, 2011 3:52:45 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r96363 r96372 1 2011-09-29 Oliver Hunt <oliver@apple.com> 2 3 Add logic to collect dirty objects as roots 4 https://bugs.webkit.org/show_bug.cgi?id=69100 5 6 Reviewed by Geoff Garen. 7 8 This gives us the ability to walk all the MarkedBlocks in an 9 AllocationSpace and collect the dirty objects, and then use 10 them as GC roots. 11 12 I also rearranged the order of these instructions because it 13 makes them smaller on some platforms with some card sizes. 14 15 * dfg/DFGJITCodeGenerator.cpp: 16 (JSC::DFG::JITCodeGenerator::markCellCard): 17 * dfg/DFGJITCodeGenerator32_64.cpp: 18 (JSC::DFG::JITCodeGenerator::markCellCard): 19 * heap/AllocationSpace.cpp: 20 Tidy up the write barrier logic a bit. 21 (JSC::MarkedBlock::gatherDirtyObjects): 22 (JSC::TakeIfDirty::returnValue): 23 (JSC::TakeIfDirty::TakeIfDirty): 24 (JSC::TakeIfDirty::operator()): 25 (JSC::AllocationSpace::gatherDirtyObjects): 26 * heap/AllocationSpace.h: 27 * heap/CardSet.h: 28 (JSC::::isCardMarked): 29 (JSC::::clearCard): 30 * heap/Heap.cpp: 31 (JSC::Heap::markRoots): 32 * heap/Heap.h: 33 (JSC::Heap::writeBarrier): 34 * heap/MarkStack.cpp: 35 (JSC::SlotVisitor::visitChildren): 36 * heap/MarkedBlock.h: 37 (JSC::MarkedBlock::setDirtyObject): 38 (JSC::MarkedBlock::addressOfCardFor): 39 * heap/SlotVisitor.h: 40 * jit/JITPropertyAccess.cpp: 41 (JSC::JIT::emitWriteBarrier): 42 Tidy the write barrier a bit. 43 1 44 2011-09-29 Gavin Barraclough <barraclough@apple.com> 2 45 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r95930 r96372 1206 1206 jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1); 1207 1207 jit.move(owner, scratch2); 1208 jit. andPtr(TrustedImm32(static_cast<int32_t>(~MarkedBlock::blockMask)), scratch2);1209 jit. rshift32(TrustedImm32(MarkedBlock::log2CardSize), scratch2);1208 jit.rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2); 1209 jit.andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2); 1210 1210 jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards())); 1211 1211 #endif -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator32_64.cpp
r96230 r96372 1256 1256 jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1); 1257 1257 jit.move(owner, scratch2); 1258 jit. andPtr(TrustedImm32(static_cast<int32_t>(~MarkedBlock::blockMask)), scratch2);1259 jit. rshift32(TrustedImm32(MarkedBlock::log2CardSize), scratch2);1258 jit.rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2); 1259 jit.andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2); 1260 1260 jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards())); 1261 1261 #endif -
trunk/Source/JavaScriptCore/heap/AllocationSpace.cpp
r95912 r96372 163 163 } 164 164 165 #if ENABLE(GGC) 166 class GatherDirtyCells { 167 WTF_MAKE_NONCOPYABLE(GatherDirtyCells); 168 public: 169 typedef void* ReturnType; 170 171 explicit GatherDirtyCells(MarkedBlock::DirtyCellVector*); 172 void operator()(MarkedBlock*); 173 ReturnType returnValue() { return 0; } 174 175 private: 176 MarkedBlock::DirtyCellVector* m_dirtyCells; 177 }; 178 179 inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells) 180 : m_dirtyCells(dirtyCells) 181 { 165 182 } 183 184 inline void GatherDirtyCells::operator()(MarkedBlock* block) 185 { 186 block->gatherDirtyCells(*m_dirtyCells); 187 } 188 189 void AllocationSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells) 190 { 191 GatherDirtyCells gatherDirtyCells(&dirtyCells); 192 forEachBlock(gatherDirtyCells); 193 } 194 #endif 195 196 } -
trunk/Source/JavaScriptCore/heap/AllocationSpace.h
r95912 r96372 51 51 void setHighWaterMark(size_t bytes) { m_markedSpace.setHighWaterMark(bytes); } 52 52 size_t highWaterMark() { return m_markedSpace.highWaterMark(); } 53 53 54 void gatherDirtyCells(MarkedBlock::DirtyCellVector&); 55 54 56 template<typename Functor> typename Functor::ReturnType forEachCell(Functor&); 55 57 template<typename Functor> typename Functor::ReturnType forEachCell(); -
trunk/Source/JavaScriptCore/heap/CardSet.h
r95865 r96372 35 35 template <size_t cardSize, size_t blockSize> class CardSet { 36 36 WTF_MAKE_NONCOPYABLE(CardSet); 37 38 public: 37 39 static const size_t cardCount = (blockSize + cardSize - 1) / cardSize; 38 40 39 public:40 41 CardSet() 41 42 { … … 46 47 void markCardForAtom(const void*); 47 48 uint8_t& cardForAtom(const void*); 49 bool isCardMarked(size_t); 50 void clearCard(size_t); 48 51 49 52 private: … … 70 73 } 71 74 75 template <size_t cardSize, size_t blockSize> bool CardSet<cardSize, blockSize>::isCardMarked(size_t i) 76 { 77 ASSERT(i < cardCount); 78 return m_cards[i]; 79 } 80 81 template <size_t cardSize, size_t blockSize> void CardSet<cardSize, blockSize>::clearCard(size_t i) 82 { 83 ASSERT(i < cardCount); 84 m_cards[i] = 0; 85 } 86 72 87 } 73 88 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r95912 r96372 472 472 registerFile().gatherConservativeRoots(registerFileRoots, m_jettisonedCodeBlocks); 473 473 m_jettisonedCodeBlocks.deleteUnmarkedCodeBlocks(); 474 475 clearMarks(); 474 #if ENABLE(GGC) 475 MarkedBlock::DirtyCellVector dirtyCells; 476 // Until we have a sensible policy we just random choose to perform 477 // young generation collections 90% of the time. 478 if (WTF::randomNumber() > 0.1) 479 m_objectSpace.gatherDirtyCells(dirtyCells); 480 else 481 #endif 482 clearMarks(); 483 476 484 477 485 SlotVisitor& visitor = m_slotVisitor; 478 486 HeapRootVisitor heapRootVisitor(visitor); 479 487 488 #if ENABLE(GGC) 489 for (size_t i = 0; i < dirtyObjectCount; i++) { 490 heapRootVisitor.visitChildren(dirtyCells[i]); 491 visitor.drain(); 492 } 493 #endif 494 480 495 visitor.append(machineThreadRoots); 481 496 visitor.drain(); -
trunk/Source/JavaScriptCore/heap/Heap.h
r95912 r96372 241 241 { 242 242 WriteBarrierCounters::countWriteBarrier(); 243 MarkedBlock::blockFor(owner)->setDirtyObject(owner); 243 MarkedBlock* block = MarkedBlock::blockFor(owner); 244 if (block->isMarked(owner)) 245 block->setDirtyObject(owner); 244 246 } 245 247 -
trunk/Source/JavaScriptCore/heap/HeapRootVisitor.h
r95901 r96372 44 44 void visit(JSString**); 45 45 void visit(JSCell**); 46 46 void visitChildren(JSCell*); 47 47 48 SlotVisitor& visitor(); 48 49 … … 76 77 } 77 78 79 inline void HeapRootVisitor::visitChildren(JSCell* cell) 80 { 81 m_visitor.visitChildren(cell); 82 } 83 78 84 inline SlotVisitor& HeapRootVisitor::visitor() 79 85 { -
trunk/Source/JavaScriptCore/heap/MarkStack.cpp
r96346 r96372 52 52 } 53 53 54 inlinevoid SlotVisitor::visitChildren(JSCell* cell)54 void SlotVisitor::visitChildren(JSCell* cell) 55 55 { 56 56 #if ENABLE(SIMPLE_HEAP_PROFILING) -
trunk/Source/JavaScriptCore/heap/MarkedBlock.h
r96068 r96372 30 30 #include <wtf/PageAllocationAligned.h> 31 31 #include <wtf/StdLibExtras.h> 32 #include <wtf/Vector.h> 32 33 33 34 // Set to log state transitions of blocks. … … 73 74 74 75 static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead 75 static const size_t bytesPerCard = 512; // 1.6% overhead 76 static const int log2CardSize = 9; 76 static const int cardShift = 10; // This is log2 of bytes per card. 77 static const size_t bytesPerCard = 1 << cardShift; 78 static const int cardCount = blockSize / bytesPerCard; 79 static const int cardMask = cardCount - 1; 77 80 78 81 struct FreeCell { … … 124 127 void setDirtyObject(const void* atom) 125 128 { 129 ASSERT(MarkedBlock::blockFor(atom) == this); 126 130 m_cards.markCardForAtom(atom); 127 131 } … … 129 133 uint8_t* addressOfCardFor(const void* atom) 130 134 { 135 ASSERT(MarkedBlock::blockFor(atom) == this); 131 136 return &m_cards.cardForAtom(atom); 132 137 } … … 136 141 return OBJECT_OFFSETOF(MarkedBlock, m_cards); 137 142 } 143 144 typedef Vector<JSCell*, 32> DirtyCellVector; 145 inline void gatherDirtyCells(DirtyCellVector&); 138 146 #endif 139 147 … … 301 309 } 302 310 311 #if ENABLE(GGC) 312 void MarkedBlock::gatherDirtyCells(DirtyCellVector& dirtyCells) 313 { 314 COMPILE_ASSERT(m_cards.cardCount == cardCount, MarkedBlockCardCountsMatch); 315 316 ASSERT(m_state != New && m_state != FreeListed); 317 318 // This is an optimisation to avoid having to walk the set of marked 319 // blocks twice during GC. 320 m_state = Marked; 321 322 if (markCountIsZero()) 323 return; 324 325 size_t cellSize = this->cellSize(); 326 const size_t firstCellOffset = firstAtom() * atomSize % cellSize; 327 328 for (size_t i = 0; i < m_cards.cardCount; i++) { 329 if (!m_cards.isCardMarked(i)) 330 continue; 331 char* ptr = reinterpret_cast<char*>(this); 332 if (i) 333 ptr += firstCellOffset + cellSize * ((i * bytesPerCard + cellSize - 1 - firstCellOffset) / cellSize); 334 else 335 ptr += firstAtom() * atomSize; 336 char* end = reinterpret_cast<char*>(this) + std::min((i + 1) * bytesPerCard, m_endAtom * atomSize); 337 338 while (ptr < end) { 339 JSCell* cell = reinterpret_cast<JSCell*>(ptr); 340 ASSERT(*addressOfCardFor(cell)); 341 if (isMarked(cell)) 342 dirtyCells.append(cell); 343 ptr += cellSize; 344 } 345 m_cards.clearCard(i); 346 } 347 } 348 #endif 349 303 350 } // namespace JSC 304 351 -
trunk/Source/JavaScriptCore/heap/SlotVisitor.h
r95901 r96372 32 32 33 33 class SlotVisitor : public MarkStack { 34 friend class HeapRootVisitor; 34 35 public: 35 36 SlotVisitor(void* jsArrayVPtr); -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r95918 r96372 1045 1045 andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch); 1046 1046 move(owner, scratch2); 1047 andPtr(TrustedImm32(static_cast<int32_t>(~MarkedBlock::blockMask)), scratch2);1048 rshift32(TrustedImm32(MarkedBlock::log2CardSize), scratch2);1047 rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2); 1048 andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2); 1049 1049 store8(TrustedImm32(1), BaseIndex(scratch, scratch2, TimesOne, MarkedBlock::offsetOfCards())); 1050 1050 if (mode == ShouldFilterImmediates)
Note: See TracChangeset
for help on using the changeset viewer.