Skip to content
  • ggaren@apple.com's avatar
    Allocate new objects unmarked · b94f6ba6
    ggaren@apple.com authored
    https://bugs.webkit.org/show_bug.cgi?id=68764
    
    Source/JavaScriptCore: 
    
    Reviewed by Oliver Hunt.
            
    This is a pre-requisite to using the mark bit to determine object age.
    
    ~2% v8 speedup, mostly due to a 12% v8-splay speedup.
    
    * heap/MarkedBlock.h:
    (JSC::MarkedBlock::isLive):
    (JSC::MarkedBlock::isLiveCell): These two functions are the reason for
    this patch. They can now determine object liveness without relying on
    newly allocated objects having their mark bits set. Each MarkedBlock
    now has a state variable that tells us how to determine whether its
    cells are live. (This new state variable supercedes the old one about
    destructor state. The rest of this patch is just refactoring to support
    the invariants of this new state variable without introducing a
    performance regression.)
    
    (JSC::MarkedBlock::didConsumeFreeList): New function for updating interal
    state when a block becomes fully allocated.
    
    (JSC::MarkedBlock::clearMarks): Folded a state change to 'Marked' into
    this function because, logically, clearing all mark bits is the first
    step in saying "mark bits now exactly reflect object liveness".
    
    (JSC::MarkedBlock::markCountIsZero): Renamed from isEmpty() to clarify
    that this function only tells you about the mark bits, so it's only
    meaningful if you've put the mark bits into a meaningful state before
    calling it.
    
    (JSC::MarkedBlock::forEachCell): Changed to use isLive() helper function
    instead of testing mark bits, since mark bits are not always the right
    way to find out if an object is live anymore. (New objects are live, but
    not marked.)
    
    * heap/MarkedBlock.cpp:
    (JSC::MarkedBlock::recycle):
    (JSC::MarkedBlock::MarkedBlock): Folded all initialization -- even
    initialization when recycling an old block -- into the MarkedBlock
    constructor, for simplicity.
    
    (JSC::MarkedBlock::callDestructor): Inlined for speed. Always check for
    a zapped cell before running a destructor, and always zap after
    running a destructor. This does not seem to be expensive, and the
    alternative just creates a too-confusing matrix of possible cell states
    ((zombie undestructed cell + zombie destructed cell + zapped destructed
    cell) * 5! permutations for progressing through block states = "Oh my!").
    
    (JSC::MarkedBlock::specializedSweep):
    (JSC::MarkedBlock::sweep): Maintained and expanded a pre-existing
    optimization to use template specialization to constant fold lots of
    branches and elide certain operations entirely during a sweep. Merged
    four or five functions that were logically about sweeping into this one
    function pair, so there's only one way to do things now, it's
    automatically correct, and it's always fast.
    
    (JSC::MarkedBlock::zapFreeList): Renamed this function to be more explicit
    about exactly what it does, and to honor the new block state system.
    
    * heap/AllocationSpace.cpp:
    (JSC::AllocationSpace::allocateBlock): Updated for rename.
    
    (JSC::AllocationSpace::freeBlocks): Updated for changed interface.
    
    (JSC::TakeIfUnmarked::TakeIfUnmarked):
    (JSC::TakeIfUnmarked::operator()):
    (JSC::TakeIfUnmarked::returnValue): Just like isEmpty() above, renamed
    to clarify that this functor only tests the mark bits, so it's only
    valid if you've put the mark bits into a meaningful state before
    calling it.
            
    (JSC::AllocationSpace::shrink): Updated for rename.
    
    * heap/AllocationSpace.h:
    (JSC::AllocationSpace::canonicalizeCellLivenessData): Renamed to be a
    little more specific about what we're making canonical.
    
    (JSC::AllocationSpace::forEachCell): Updated for rename.
    
    (JSC::AllocationSpace::forEachBlock): No need to canonicalize cell
    liveness data before iterating blocks -- clients that want iterated
    blocks to have valid cell lieveness data should make this call for
    themselves. (And not all clients want it.)
    
    * heap/ConservativeRoots.cpp:
    (JSC::ConservativeRoots::genericAddPointer): Updated for rename. Removed
    obsolete comment.
    
    * heap/Heap.cpp:
    (JSC::CountFunctor::ClearMarks::operator()): Removed call to notify...()
    because clearMarks() now does that implicitly.
    
    (JSC::Heap::destroy): Make sure to canonicalize before tear-down, since
    tear-down tests cell liveness when running destructors.
    
    (JSC::Heap::markRoots):
    (JSC::Heap::collect): Moved weak reference harvesting out of markRoots()
    and into collect, since it strictly depends on root marking, and does
    not contribute to root marking.
    
    (JSC::Heap::canonicalizeCellLivenessData): Renamed to be a little more
    specific about what we're making canonical.
    
    * heap/Heap.h:
    (JSC::Heap::forEachProtectedCell): No need to canonicalize cell liveness
    data before iterating protected cells, since we know they're all live,
    and don't need to test for it.
    
    * heap/Local.h:
    (JSC::::set): Can't make the same ASSERT we used to because we just don't
    have the mark bits for it anymore. Perhaps we can bring this ASSERT back
    in a weaker form in the future.
    
    * heap/MarkedSpace.cpp:
    (JSC::MarkedSpace::addBlock):
    (JSC::MarkedSpace::removeBlock): Updated for interface change.
    (JSC::MarkedSpace::canonicalizeCellLivenessData): Renamed to be a little more
    specific about what we're making canonical.
    
    * heap/MarkedSpace.h:
    (JSC::MarkedSpace::allocate):
    (JSC::MarkedSpace::SizeClass::SizeClass):
    (JSC::MarkedSpace::SizeClass::resetAllocator):
    (JSC::MarkedSpace::SizeClass::zapFreeList): Simplified this allocator
    functionality a bit. We now track only one block -- "currentBlock" --
    and rely on its internal state to know whether it has more cells to
    allocate.
    
    * heap/Weak.h:
    (JSC::Weak::set): Can't make the same ASSERT we used to because we just don't
    have the mark bits for it anymore. Perhaps we can bring this ASSERT back
    in a weaker form in the future.
    
    * runtime/JSCell.h:
    (JSC::JSCell::vptr):
    (JSC::JSCell::zap):
    (JSC::JSCell::isZapped):
    (JSC::isZapped): Made zapping a property of JSCell, for a little abstraction.
    In the future, exactly how a JSCell zaps itself will change, as the
    internal representation of JSCell changes.
    
    LayoutTests: 
    
    Reviewed by Oliver Hunt.
            
    Made this flaky test less flaky. (Just enough to make my patch not fail.)
    
    * fast/dom/gc-10.html: Count objects immediately after GC to get an
    exact count. Call 'reload' a few times to improve test coverage. Preload
    properties in case they're lazily instantiated, which would change
    object count numbers. Also, use the 'var' keyword like a good little
    JavaScripter.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95912 268f45cc-cd09-0410-ab3c-d52691b4dbfc
    b94f6ba6