Changeset 227718 in webkit


Ignore:
Timestamp:
Jan 28, 2018 11:08:08 AM (6 years ago)
Author:
fpizlo@apple.com
Message:

Make MarkedBlock::Footer bigger
https://bugs.webkit.org/show_bug.cgi?id=182220

Reviewed by JF Bastien.

This makes the block footer larger by moving the newlyAllocated bits from the handle into
the footer.

It used to be profitable to put anything we could into the handle because that would free up
payload space inside the block. But now that we want to use the footer for padding, it's
profitable to put GC state information - especially data that is used by the GC itself and so
is not useful for a Spectre attack - into the footer to increase object distancing.

  • heap/CellContainer.cpp:

(JSC::CellContainer::isNewlyAllocated const):

  • heap/IsoCellSet.cpp:

(JSC::IsoCellSet::sweepToFreeList):

  • heap/MarkedBlock.cpp:

(JSC::MarkedBlock::Handle::Handle):
(JSC::MarkedBlock::Footer::Footer):
(JSC::MarkedBlock::Handle::stopAllocating):
(JSC::MarkedBlock::Handle::lastChanceToFinalize):
(JSC::MarkedBlock::Handle::resumeAllocating):
(JSC::MarkedBlock::aboutToMarkSlow):
(JSC::MarkedBlock::resetAllocated):
(JSC::MarkedBlock::Handle::resetAllocated): Deleted.

  • heap/MarkedBlock.h:

(JSC::MarkedBlock::newlyAllocatedVersion const):
(JSC::MarkedBlock::isNewlyAllocated):
(JSC::MarkedBlock::setNewlyAllocated):
(JSC::MarkedBlock::clearNewlyAllocated):
(JSC::MarkedBlock::newlyAllocated const):
(JSC::MarkedBlock::Handle::newlyAllocatedVersion const): Deleted.
(JSC::MarkedBlock::Handle::isNewlyAllocated): Deleted.
(JSC::MarkedBlock::Handle::setNewlyAllocated): Deleted.
(JSC::MarkedBlock::Handle::clearNewlyAllocated): Deleted.
(JSC::MarkedBlock::Handle::newlyAllocated const): Deleted.

  • heap/MarkedBlockInlines.h:

(JSC::MarkedBlock::isNewlyAllocatedStale const):
(JSC::MarkedBlock::hasAnyNewlyAllocated):
(JSC::MarkedBlock::Handle::isLive):
(JSC::MarkedBlock::Handle::specializedSweep):
(JSC::MarkedBlock::Handle::newlyAllocatedMode):
(JSC::MarkedBlock::Handle::isNewlyAllocatedStale const): Deleted.
(JSC::MarkedBlock::Handle::hasAnyNewlyAllocated): Deleted.

  • heap/MarkedSpace.cpp:

(JSC::MarkedSpace::endMarking):

  • heap/SlotVisitor.cpp:

(JSC::SlotVisitor::appendJSCellOrAuxiliary):

Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r227717 r227718  
     12018-01-27  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Make MarkedBlock::Footer bigger
     4        https://bugs.webkit.org/show_bug.cgi?id=182220
     5
     6        Reviewed by JF Bastien.
     7       
     8        This makes the block footer larger by moving the newlyAllocated bits from the handle into
     9        the footer.
     10       
     11        It used to be profitable to put anything we could into the handle because that would free up
     12        payload space inside the block. But now that we want to use the footer for padding, it's
     13        profitable to put GC state information - especially data that is used by the GC itself and so
     14        is not useful for a Spectre attack - into the footer to increase object distancing.
     15
     16        * heap/CellContainer.cpp:
     17        (JSC::CellContainer::isNewlyAllocated const):
     18        * heap/IsoCellSet.cpp:
     19        (JSC::IsoCellSet::sweepToFreeList):
     20        * heap/MarkedBlock.cpp:
     21        (JSC::MarkedBlock::Handle::Handle):
     22        (JSC::MarkedBlock::Footer::Footer):
     23        (JSC::MarkedBlock::Handle::stopAllocating):
     24        (JSC::MarkedBlock::Handle::lastChanceToFinalize):
     25        (JSC::MarkedBlock::Handle::resumeAllocating):
     26        (JSC::MarkedBlock::aboutToMarkSlow):
     27        (JSC::MarkedBlock::resetAllocated):
     28        (JSC::MarkedBlock::Handle::resetAllocated): Deleted.
     29        * heap/MarkedBlock.h:
     30        (JSC::MarkedBlock::newlyAllocatedVersion const):
     31        (JSC::MarkedBlock::isNewlyAllocated):
     32        (JSC::MarkedBlock::setNewlyAllocated):
     33        (JSC::MarkedBlock::clearNewlyAllocated):
     34        (JSC::MarkedBlock::newlyAllocated const):
     35        (JSC::MarkedBlock::Handle::newlyAllocatedVersion const): Deleted.
     36        (JSC::MarkedBlock::Handle::isNewlyAllocated): Deleted.
     37        (JSC::MarkedBlock::Handle::setNewlyAllocated): Deleted.
     38        (JSC::MarkedBlock::Handle::clearNewlyAllocated): Deleted.
     39        (JSC::MarkedBlock::Handle::newlyAllocated const): Deleted.
     40        * heap/MarkedBlockInlines.h:
     41        (JSC::MarkedBlock::isNewlyAllocatedStale const):
     42        (JSC::MarkedBlock::hasAnyNewlyAllocated):
     43        (JSC::MarkedBlock::Handle::isLive):
     44        (JSC::MarkedBlock::Handle::specializedSweep):
     45        (JSC::MarkedBlock::Handle::newlyAllocatedMode):
     46        (JSC::MarkedBlock::Handle::isNewlyAllocatedStale const): Deleted.
     47        (JSC::MarkedBlock::Handle::hasAnyNewlyAllocated): Deleted.
     48        * heap/MarkedSpace.cpp:
     49        (JSC::MarkedSpace::endMarking):
     50        * heap/SlotVisitor.cpp:
     51        (JSC::SlotVisitor::appendJSCellOrAuxiliary):
     52
    1532018-01-27  Filip Pizlo  <fpizlo@apple.com>
    254
  • trunk/Source/JavaScriptCore/heap/CellContainer.cpp

    r209808 r227718  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535    if (isLargeAllocation())
    3636        return largeAllocation().isNewlyAllocated();
    37     MarkedBlock::Handle& handle = markedBlock().handle();
    38     return !handle.isNewlyAllocatedStale()
    39         && handle.isNewlyAllocated(cell);
     37    MarkedBlock& block = markedBlock();
     38    return !block.isNewlyAllocatedStale()
     39        && block.isNewlyAllocated(cell);
    4040}
    4141
  • trunk/Source/JavaScriptCore/heap/IsoCellSet.cpp

    r226822 r227718  
    127127    }
    128128   
    129     if (block->hasAnyNewlyAllocated()) {
    130         m_bits[block->index()]->concurrentFilter(block->newlyAllocated());
     129    if (block->block().hasAnyNewlyAllocated()) {
     130        m_bits[block->index()]->concurrentFilter(block->block().newlyAllocated());
    131131        return;
    132132    }
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp

    r227717 r227718  
    6363    : m_alignedMemoryAllocator(alignedMemoryAllocator)
    6464    , m_weakSet(heap.vm(), CellContainer())
    65     , m_newlyAllocatedVersion(MarkedSpace::nullVersion)
    6665{
    6766    m_block = new (NotNull, blockSpace) MarkedBlock(*heap.vm(), *this);
     
    102101    , m_vm(&vm)
    103102    , m_markingVersion(MarkedSpace::nullVersion)
     103    , m_newlyAllocatedVersion(MarkedSpace::nullVersion)
    104104{
    105105}
     
    145145    // way to tell what's live vs dead.
    146146   
    147     m_newlyAllocated.clearAll();
    148     m_newlyAllocatedVersion = heap()->objectSpace().newlyAllocatedVersion();
     147    blockFooter().m_newlyAllocated.clearAll();
     148    blockFooter().m_newlyAllocatedVersion = heap()->objectSpace().newlyAllocatedVersion();
    149149
    150150    forEachCell(
    151151        [&] (HeapCell* cell, HeapCell::Kind) -> IterationStatus {
    152             setNewlyAllocated(cell);
     152            block().setNewlyAllocated(cell);
    153153            return IterationStatus::Continue;
    154154        });
     
    160160            if (m_attributes.destruction == NeedsDestruction)
    161161                cell->zap();
    162             clearNewlyAllocated(cell);
     162            block().clearNewlyAllocated(cell);
    163163        });
    164164   
     
    174174    blockFooter().m_markingVersion = heap()->objectSpace().markingVersion();
    175175    m_weakSet.lastChanceToFinalize();
    176     m_newlyAllocated.clearAll();
    177     m_newlyAllocatedVersion = heap()->objectSpace().newlyAllocatedVersion();
     176    blockFooter().m_newlyAllocated.clearAll();
     177    blockFooter().m_newlyAllocatedVersion = heap()->objectSpace().newlyAllocatedVersion();
    178178    sweep(nullptr);
    179179}
     
    189189        ASSERT(!isFreeListed());
    190190       
    191         if (!hasAnyNewlyAllocated()) {
     191        if (!block().hasAnyNewlyAllocated()) {
    192192            if (false)
    193193                dataLog("There ain't no newly allocated.\n");
     
    237237            dataLog(RawPointer(this), ": Doing things.\n");
    238238        HeapVersion newlyAllocatedVersion = space()->newlyAllocatedVersion();
    239         if (handle().m_newlyAllocatedVersion == newlyAllocatedVersion) {
     239        if (footer().m_newlyAllocatedVersion == newlyAllocatedVersion) {
    240240            // When do we get here? The block could not have been filled up. The newlyAllocated bits would
    241241            // have had to be created since the end of the last collection. The only things that create
     
    245245            // computed the newlyAllocated bits just before the start of an increment. When we are in that
    246246            // mode, it seems as if newlyAllocated should subsume marks.
    247             ASSERT(handle().m_newlyAllocated.subsumes(footer().m_marks));
     247            ASSERT(footer().m_newlyAllocated.subsumes(footer().m_marks));
    248248            footer().m_marks.clearAll();
    249249        } else {
    250             handle().m_newlyAllocated.setAndClear(footer().m_marks);
    251             handle().m_newlyAllocatedVersion = newlyAllocatedVersion;
     250            footer().m_newlyAllocated.setAndClear(footer().m_marks);
     251            footer().m_newlyAllocatedVersion = newlyAllocatedVersion;
    252252        }
    253253    }
     
    260260}
    261261
    262 void MarkedBlock::Handle::resetAllocated()
    263 {
    264     m_newlyAllocated.clearAll();
    265     m_newlyAllocatedVersion = MarkedSpace::nullVersion;
     262void MarkedBlock::resetAllocated()
     263{
     264    footer().m_newlyAllocated.clearAll();
     265    footer().m_newlyAllocatedVersion = MarkedSpace::nullVersion;
    266266}
    267267
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.h

    r227717 r227718  
    175175        bool isFreeListedCell(const void* target) const;
    176176
    177         bool isNewlyAllocated(const void*);
    178         void setNewlyAllocated(const void*);
    179         void clearNewlyAllocated(const void*);
    180         const Bitmap<atomsPerBlock>& newlyAllocated() const;
    181        
    182         HeapVersion newlyAllocatedVersion() const { return m_newlyAllocatedVersion; }
    183        
    184         inline bool isNewlyAllocatedStale() const;
    185        
    186         inline bool hasAnyNewlyAllocated();
    187         void resetAllocated();
    188        
    189177        template <typename Functor> IterationStatus forEachCell(const Functor&);
    190178        template <typename Functor> inline IterationStatus forEachLiveCell(const Functor&);
     
    233221        size_t m_endAtom { std::numeric_limits<size_t>::max() }; // This is a fuzzy end. Always test for < m_endAtom.
    234222           
    235         Bitmap<atomsPerBlock> m_newlyAllocated;
    236            
    237223        CellAttributes m_attributes;
    238224        bool m_isFreeListed { false };
     
    243229        WeakSet m_weakSet;
    244230       
    245         HeapVersion m_newlyAllocatedVersion;
    246            
    247231        MarkedBlock* m_block { nullptr };
    248232    };
     
    297281
    298282        HeapVersion m_markingVersion;
     283        HeapVersion m_newlyAllocatedVersion;
    299284
    300285        Bitmap<atomsPerBlock> m_marks;
     286        Bitmap<atomsPerBlock> m_newlyAllocated;
    301287    };
    302288       
     
    331317    void clearMarked(const void*);
    332318   
     319    bool isNewlyAllocated(const void*);
     320    void setNewlyAllocated(const void*);
     321    void clearNewlyAllocated(const void*);
     322    const Bitmap<atomsPerBlock>& newlyAllocated() const;
     323   
     324    HeapVersion newlyAllocatedVersion() const { return footer().m_newlyAllocatedVersion; }
     325   
     326    inline bool isNewlyAllocatedStale() const;
     327   
     328    inline bool hasAnyNewlyAllocated();
     329    void resetAllocated();
     330       
    333331    size_t cellSize();
    334332    const CellAttributes& attributes() const;
     
    585583}
    586584
    587 inline bool MarkedBlock::Handle::isNewlyAllocated(const void* p)
    588 {
    589     return m_newlyAllocated.get(m_block->atomNumber(p));
    590 }
    591 
    592 inline void MarkedBlock::Handle::setNewlyAllocated(const void* p)
    593 {
    594     m_newlyAllocated.set(m_block->atomNumber(p));
    595 }
    596 
    597 inline void MarkedBlock::Handle::clearNewlyAllocated(const void* p)
    598 {
    599     m_newlyAllocated.clear(m_block->atomNumber(p));
    600 }
    601 
    602 inline const Bitmap<MarkedBlock::atomsPerBlock>& MarkedBlock::Handle::newlyAllocated() const
    603 {
    604     return m_newlyAllocated;
     585inline bool MarkedBlock::isNewlyAllocated(const void* p)
     586{
     587    return footer().m_newlyAllocated.get(atomNumber(p));
     588}
     589
     590inline void MarkedBlock::setNewlyAllocated(const void* p)
     591{
     592    footer().m_newlyAllocated.set(atomNumber(p));
     593}
     594
     595inline void MarkedBlock::clearNewlyAllocated(const void* p)
     596{
     597    footer().m_newlyAllocated.clear(atomNumber(p));
     598}
     599
     600inline const Bitmap<MarkedBlock::atomsPerBlock>& MarkedBlock::newlyAllocated() const
     601{
     602    return footer().m_newlyAllocated;
    605603}
    606604
  • trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h

    r227717 r227718  
    4141}
    4242
    43 inline bool MarkedBlock::Handle::isNewlyAllocatedStale() const
    44 {
    45     return m_newlyAllocatedVersion != space()->newlyAllocatedVersion();
    46 }
    47 
    48 inline bool MarkedBlock::Handle::hasAnyNewlyAllocated()
     43inline bool MarkedBlock::isNewlyAllocatedStale() const
     44{
     45    return footer().m_newlyAllocatedVersion != space()->newlyAllocatedVersion();
     46}
     47
     48inline bool MarkedBlock::hasAnyNewlyAllocated()
    4949{
    5050    return !isNewlyAllocatedStale();
     
    144144    if (count.value) {
    145145        Dependency fenceBefore = Dependency::fence(count.input);
     146        MarkedBlock& fencedBlock = *fenceBefore.consume(&block);
     147        MarkedBlock::Footer& fencedFooter = fencedBlock.footer();
    146148        MarkedBlock::Handle* fencedThis = fenceBefore.consume(this);
    147149       
    148         ASSERT(!fencedThis->isFreeListed());
    149        
    150         HeapVersion myNewlyAllocatedVersion = fencedThis->m_newlyAllocatedVersion;
     150        ASSERT_UNUSED(fencedThis, !fencedThis->isFreeListed());
     151       
     152        HeapVersion myNewlyAllocatedVersion = fencedFooter.m_newlyAllocatedVersion;
    151153        if (myNewlyAllocatedVersion == newlyAllocatedVersion) {
    152             bool result = fencedThis->isNewlyAllocated(cell);
     154            bool result = fencedBlock.isNewlyAllocated(cell);
    153155            if (footer.m_lock.fencelessValidate(count.value, Dependency::fence(result)))
    154156                return result;
    155157        } else {
    156             MarkedBlock& fencedBlock = *fenceBefore.consume(&block);
    157             MarkedBlock::Footer& fencedFooter = fencedBlock.footer();
    158            
    159158            HeapVersion myMarkingVersion = fencedFooter.m_markingVersion;
    160159            if (myMarkingVersion != markingVersion
     
    174173    ASSERT(!isFreeListed());
    175174   
    176     HeapVersion myNewlyAllocatedVersion = m_newlyAllocatedVersion;
     175    HeapVersion myNewlyAllocatedVersion = footer.m_newlyAllocatedVersion;
    177176    if (myNewlyAllocatedVersion == newlyAllocatedVersion)
    178         return isNewlyAllocated(cell);
     177        return block.isNewlyAllocated(cell);
    179178   
    180179    if (block.areMarksStale(markingVersion)) {
     
    327326        if (emptyMode == NotEmpty
    328327            && ((marksMode == MarksNotStale && footer.m_marks.get(i))
    329                 || (newlyAllocatedMode == HasNewlyAllocated && m_newlyAllocated.get(i)))) {
     328                || (newlyAllocatedMode == HasNewlyAllocated && footer.m_newlyAllocated.get(i)))) {
    330329            isEmpty = false;
    331330            continue;
     
    341340    // otherwise we would lose information on what's currently alive.
    342341    if (sweepMode == SweepToFreeList && newlyAllocatedMode == HasNewlyAllocated)
    343         m_newlyAllocatedVersion = MarkedSpace::nullVersion;
     342        footer.m_newlyAllocatedVersion = MarkedSpace::nullVersion;
    344343   
    345344    if (space()->isMarking())
     
    465464inline MarkedBlock::Handle::NewlyAllocatedMode MarkedBlock::Handle::newlyAllocatedMode()
    466465{
    467     return hasAnyNewlyAllocated() ? HasNewlyAllocated : DoesNotHaveNewlyAllocated;
     466    return block().hasAnyNewlyAllocated() ? HasNewlyAllocated : DoesNotHaveNewlyAllocated;
    468467}
    469468
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp

    r227717 r227718  
    4545            result = new Vector<size_t>();
    4646           
     47            if (Options::dumpSizeClasses()) {
     48                dataLog("Block size: ", MarkedBlock::blockSize, "\n");
     49                dataLog("Footer size: ", sizeof(MarkedBlock::Footer), "\n");
     50            }
     51           
    4752            auto add = [&] (size_t sizeClass) {
    4853                sizeClass = WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(sizeClass);
     
    425430        forEachBlock(
    426431            [&] (MarkedBlock::Handle* handle) {
    427                 handle->resetAllocated();
     432                handle->block().resetAllocated();
    428433            });
    429434    }
  • trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp

    r227617 r227718  
    11/*
    2  * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    171171                        out.print("Marking version: ", block.markingVersion(), "\n");
    172172                        out.print("Heap marking version: ", heap()->objectSpace().markingVersion(), "\n");
    173                         out.print("Is newly allocated raw: ", block.handle().isNewlyAllocated(jsCell), "\n");
    174                         out.print("Newly allocated version: ", block.handle().newlyAllocatedVersion(), "\n");
     173                        out.print("Is newly allocated raw: ", block.isNewlyAllocated(jsCell), "\n");
     174                        out.print("Newly allocated version: ", block.newlyAllocatedVersion(), "\n");
    175175                        out.print("Heap newly allocated version: ", heap()->objectSpace().newlyAllocatedVersion(), "\n");
    176176                    }
Note: See TracChangeset for help on using the changeset viewer.