Ignore:
Timestamp:
May 4, 2015, 1:42:10 PM (10 years ago)
Author:
[email protected]
Message:

Optimize WeakBlock's "reap" and "visit" operations.
<https://webkit.org/b/144585>

Reviewed by Geoffrey Garen.

WeakBlock was using Heap::isLive(void*) to determine the liveness of weak pointees.
That function was really written with conservative roots marking in mind, and will do a bunch
of sanity and bounds checks.

For weaks, we know that the pointer will have been a valid cell pointer into a block
of appropriate cell size, so we can skip a lot of the checks.

We now keep a pointer to the MarkedBlock in each WeakBlock. That way we no longer have to do
MarkedBlock::blockFor() for every single cell when iterating.

Note that a WeakBlock's MarkedBlock pointer becomes null when we detach a logically empty
WeakBlock from its WeakSet and transfer ownership to Heap. At that point, the block will never
be pointing to any live cells, and the only operation that will run on the block is sweep().

Finally, MarkedBlock allows liveness queries in three states: Marked, Retired, and Allocated.
In Allocated state, all cells are reported as live. This state will reset to Marked on next GC.
This patch uses that knowledge to avoid branching on the MarkedBlock's state for every cell.

This is a ~3x speedup of visit() and a ~2x speedup of reap() on Dromaeo/dom-modify, netting
what looks like a 1% speedup locally.

  • heap/MarkedBlock.cpp:

(JSC::MarkedBlock::MarkedBlock): Pass *this to the WeakSet's ctor.

  • heap/MarkedBlock.h:

(JSC::MarkedBlock::isMarkedOrNewlyAllocated): Added, stripped-down version of isLive() when the
block's state is known to be either Marked or Retired.

(JSC::MarkedBlock::isAllocated): Added, tells WeakBlock it's okay to skip reap/visit since isLive()
would report that all cells are live anyway.

  • heap/WeakBlock.cpp:

(JSC::WeakBlock::create):
(JSC::WeakBlock::WeakBlock): Stash a MarkedBlock* on each WeakBlock.

(JSC::WeakBlock::visit):
(JSC::WeakBlock::reap): Optimized these two to avoid a bunch of pointer arithmetic and branches.

  • heap/WeakBlock.h:

(JSC::WeakBlock::disconnectMarkedBlock): Added.

  • heap/WeakSet.cpp:

(JSC::WeakSet::sweep): Call the above when removing a WeakBlock from WeakSet and transferring
ownership to Heap until it can die peacefully.

(JSC::WeakSet::addAllocator):

  • heap/WeakSet.h:

(JSC::WeakSet::WeakSet): Give WeakSet a MarkedBlock& for passing on to WeakBlocks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/heap/WeakBlock.cpp

    r182347 r183769  
    3535namespace JSC {
    3636
    37 WeakBlock* WeakBlock::create()
     37WeakBlock* WeakBlock::create(MarkedBlock& markedBlock)
    3838{
    39     return new (NotNull, fastMalloc(blockSize)) WeakBlock();
     39    return new (NotNull, fastMalloc(blockSize)) WeakBlock(markedBlock);
    4040}
    4141
     
    4646}
    4747
    48 WeakBlock::WeakBlock()
     48WeakBlock::WeakBlock(MarkedBlock& markedBlock)
    4949    : DoublyLinkedListNode<WeakBlock>()
     50    , m_markedBlock(&markedBlock)
    5051{
    5152    for (size_t i = 0; i < weakImplCount(); ++i) {
     
    99100        return;
    100101
     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
    101108    SlotVisitor& visitor = heapRootVisitor.visitor();
    102109
     
    107114
    108115        const JSValue& jsValue = weakImpl->jsValue();
    109         if (Heap::isLive(jsValue.asCell()))
     116        if (m_markedBlock->isMarkedOrNewlyAllocated(jsValue.asCell()))
    110117            continue;
    111118
     
    127134        return;
    128135
     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
    129142    for (size_t i = 0; i < weakImplCount(); ++i) {
    130143        WeakImpl* weakImpl = &weakImpls()[i];
     
    132145            continue;
    133146
    134         if (Heap::isLive(weakImpl->jsValue().asCell())) {
     147        if (m_markedBlock->isMarkedOrNewlyAllocated(weakImpl->jsValue().asCell())) {
    135148            ASSERT(weakImpl->state() == WeakImpl::Live);
    136149            continue;
Note: See TracChangeset for help on using the changeset viewer.