Changeset 183769 in webkit
- Timestamp:
- May 4, 2015 1:42:10 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r183763 r183769 1 2015-05-04 Andreas Kling <akling@apple.com> 2 3 Optimize WeakBlock's "reap" and "visit" operations. 4 <https://webkit.org/b/144585> 5 6 Reviewed by Geoffrey Garen. 7 8 WeakBlock was using Heap::isLive(void*) to determine the liveness of weak pointees. 9 That function was really written with conservative roots marking in mind, and will do a bunch 10 of sanity and bounds checks. 11 12 For weaks, we know that the pointer will have been a valid cell pointer into a block 13 of appropriate cell size, so we can skip a lot of the checks. 14 15 We now keep a pointer to the MarkedBlock in each WeakBlock. That way we no longer have to do 16 MarkedBlock::blockFor() for every single cell when iterating. 17 18 Note that a WeakBlock's MarkedBlock pointer becomes null when we detach a logically empty 19 WeakBlock from its WeakSet and transfer ownership to Heap. At that point, the block will never 20 be pointing to any live cells, and the only operation that will run on the block is sweep(). 21 22 Finally, MarkedBlock allows liveness queries in three states: Marked, Retired, and Allocated. 23 In Allocated state, all cells are reported as live. This state will reset to Marked on next GC. 24 This patch uses that knowledge to avoid branching on the MarkedBlock's state for every cell. 25 26 This is a ~3x speedup of visit() and a ~2x speedup of reap() on Dromaeo/dom-modify, netting 27 what looks like a 1% speedup locally. 28 29 * heap/MarkedBlock.cpp: 30 (JSC::MarkedBlock::MarkedBlock): Pass *this to the WeakSet's ctor. 31 32 * heap/MarkedBlock.h: 33 (JSC::MarkedBlock::isMarkedOrNewlyAllocated): Added, stripped-down version of isLive() when the 34 block's state is known to be either Marked or Retired. 35 36 (JSC::MarkedBlock::isAllocated): Added, tells WeakBlock it's okay to skip reap/visit since isLive() 37 would report that all cells are live anyway. 38 39 * heap/WeakBlock.cpp: 40 (JSC::WeakBlock::create): 41 (JSC::WeakBlock::WeakBlock): Stash a MarkedBlock* on each WeakBlock. 42 43 (JSC::WeakBlock::visit): 44 (JSC::WeakBlock::reap): Optimized these two to avoid a bunch of pointer arithmetic and branches. 45 46 * heap/WeakBlock.h: 47 (JSC::WeakBlock::disconnectMarkedBlock): Added. 48 * heap/WeakSet.cpp: 49 (JSC::WeakSet::sweep): Call the above when removing a WeakBlock from WeakSet and transferring 50 ownership to Heap until it can die peacefully. 51 52 (JSC::WeakSet::addAllocator): 53 * heap/WeakSet.h: 54 (JSC::WeakSet::WeakSet): Give WeakSet a MarkedBlock& for passing on to WeakBlocks. 55 1 56 2015-05-04 Basile Clement <basile_clement@apple.com> 2 57 -
trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp
r183124 r183769 53 53 , m_allocator(allocator) 54 54 , m_state(New) // All cells start out unmarked. 55 , m_weakSet(allocator->heap()->vm() )55 , m_weakSet(allocator->heap()->vm(), *this) 56 56 { 57 57 ASSERT(allocator); -
trunk/Source/JavaScriptCore/heap/MarkedBlock.h
r183124 r183769 165 165 bool isLive(const JSCell*); 166 166 bool isLiveCell(const void*); 167 bool isMarkedOrNewlyAllocated(const JSCell*); 167 168 void setMarked(const void*); 168 169 void clearMarked(const void*); … … 177 178 void clearNewlyAllocated(const void*); 178 179 180 bool isAllocated() const; 179 181 bool needsSweeping(); 180 182 void didRetireBlock(const FreeList&); … … 411 413 } 412 414 415 inline bool MarkedBlock::isMarkedOrNewlyAllocated(const JSCell* cell) 416 { 417 ASSERT(m_state == Retired || m_state == Marked); 418 return m_marks.get(atomNumber(cell)) || (m_newlyAllocated && isNewlyAllocated(cell)); 419 } 420 413 421 inline bool MarkedBlock::isLive(const JSCell* cell) 414 422 { … … 419 427 case Retired: 420 428 case Marked: 421 return m_marks.get(atomNumber(cell)) || (m_newlyAllocated && isNewlyAllocated(cell));429 return isMarkedOrNewlyAllocated(cell); 422 430 423 431 case New: … … 487 495 } 488 496 497 inline bool MarkedBlock::isAllocated() const 498 { 499 return m_state == Allocated; 500 } 501 489 502 } // namespace JSC 490 503 -
trunk/Source/JavaScriptCore/heap/WeakBlock.cpp
r182347 r183769 35 35 namespace JSC { 36 36 37 WeakBlock* WeakBlock::create( )37 WeakBlock* WeakBlock::create(MarkedBlock& markedBlock) 38 38 { 39 return new (NotNull, fastMalloc(blockSize)) WeakBlock( );39 return new (NotNull, fastMalloc(blockSize)) WeakBlock(markedBlock); 40 40 } 41 41 … … 46 46 } 47 47 48 WeakBlock::WeakBlock( )48 WeakBlock::WeakBlock(MarkedBlock& markedBlock) 49 49 : DoublyLinkedListNode<WeakBlock>() 50 , m_markedBlock(&markedBlock) 50 51 { 51 52 for (size_t i = 0; i < weakImplCount(); ++i) { … … 99 100 return; 100 101 102 // If this WeakBlock doesn't belong to a MarkedBlock, we won't even be here. 103 ASSERT(m_markedBlock); 104 105 if (m_markedBlock->isAllocated()) 106 return; 107 101 108 SlotVisitor& visitor = heapRootVisitor.visitor(); 102 109 … … 107 114 108 115 const JSValue& jsValue = weakImpl->jsValue(); 109 if ( Heap::isLive(jsValue.asCell()))116 if (m_markedBlock->isMarkedOrNewlyAllocated(jsValue.asCell())) 110 117 continue; 111 118 … … 127 134 return; 128 135 136 // If this WeakBlock doesn't belong to a MarkedBlock, we won't even be here. 137 ASSERT(m_markedBlock); 138 139 if (m_markedBlock->isAllocated()) 140 return; 141 129 142 for (size_t i = 0; i < weakImplCount(); ++i) { 130 143 WeakImpl* weakImpl = &weakImpls()[i]; … … 132 145 continue; 133 146 134 if ( Heap::isLive(weakImpl->jsValue().asCell())) {147 if (m_markedBlock->isMarkedOrNewlyAllocated(weakImpl->jsValue().asCell())) { 135 148 ASSERT(weakImpl->state() == WeakImpl::Live); 136 149 continue; -
trunk/Source/JavaScriptCore/heap/WeakBlock.h
r182878 r183769 37 37 class HeapRootVisitor; 38 38 class JSValue; 39 class MarkedBlock; 39 40 class WeakHandleOwner; 40 41 … … 56 57 }; 57 58 58 static WeakBlock* create( );59 static WeakBlock* create(MarkedBlock&); 59 60 static void destroy(WeakBlock*); 60 61 … … 71 72 72 73 void lastChanceToFinalize(); 74 void disconnectMarkedBlock() { m_markedBlock = nullptr; } 73 75 74 76 private: 75 77 static FreeCell* asFreeCell(WeakImpl*); 76 78 77 WeakBlock();79 explicit WeakBlock(MarkedBlock&); 78 80 WeakImpl* firstWeakImpl(); 79 81 void finalize(WeakImpl*); … … 82 84 void addToFreeList(FreeCell**, WeakImpl*); 83 85 86 MarkedBlock* m_markedBlock; 84 87 WeakBlock* m_prev; 85 88 WeakBlock* m_next; -
trunk/Source/JavaScriptCore/heap/WeakSet.cpp
r182347 r183769 54 54 m_blocks.remove(block); 55 55 heap()->addLogicallyEmptyWeakBlock(block); 56 block->disconnectMarkedBlock(); 56 57 } 57 58 block = nextBlock; … … 85 86 WeakBlock::FreeCell* WeakSet::addAllocator() 86 87 { 87 WeakBlock* block = WeakBlock::create( );88 WeakBlock* block = WeakBlock::create(m_markedBlock); 88 89 heap()->didAllocate(WeakBlock::blockSize); 89 90 m_blocks.append(block); -
trunk/Source/JavaScriptCore/heap/WeakSet.h
r156794 r183769 32 32 33 33 class Heap; 34 class MarkedBlock; 34 35 class WeakImpl; 35 36 … … 41 42 static void deallocate(WeakImpl*); 42 43 43 WeakSet(VM* );44 WeakSet(VM*, MarkedBlock&); 44 45 ~WeakSet(); 45 46 void lastChanceToFinalize(); … … 66 67 DoublyLinkedList<WeakBlock> m_blocks; 67 68 VM* m_vm; 69 MarkedBlock& m_markedBlock; 68 70 }; 69 71 70 inline WeakSet::WeakSet(VM* vm )72 inline WeakSet::WeakSet(VM* vm, MarkedBlock& markedBlock) 71 73 : m_allocator(0) 72 74 , m_nextAllocator(0) 73 75 , m_vm(vm) 76 , m_markedBlock(markedBlock) 74 77 { 75 78 }
Note: See TracChangeset
for help on using the changeset viewer.