Changeset 107445 in webkit


Ignore:
Timestamp:
Feb 10, 2012 2:44:09 PM (12 years ago)
Author:
mhahnenberg@apple.com
Message:

Split MarkedSpace into destructor and destructor-free subspaces
https://bugs.webkit.org/show_bug.cgi?id=77761

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject): Switched over to use destructor-free space.

  • heap/Heap.h:

(JSC::Heap::allocatorForObjectWithoutDestructor): Added to give clients (e.g. the JIT) the ability to
pick which subspace they want to allocate out of.
(JSC::Heap::allocatorForObjectWithDestructor): Ditto.
(Heap):
(JSC::Heap::allocateWithDestructor): Added private function for CellAllocator to use.
(JSC):
(JSC::Heap::allocateWithoutDestructor): Ditto.

  • heap/MarkedAllocator.cpp: Added the cellsNeedDestruction flag to allocators so that they can allocate

their MarkedBlocks correctly.
(JSC::MarkedAllocator::allocateBlock):

  • heap/MarkedAllocator.h:

(JSC::MarkedAllocator::cellsNeedDestruction):
(MarkedAllocator):
(JSC::MarkedAllocator::MarkedAllocator):
(JSC):
(JSC::MarkedAllocator::init): Replaced custom set functions, which were only used upon initialization, with
an init function that does all of that stuff in fewer lines.

  • heap/MarkedBlock.cpp:

(JSC::MarkedBlock::create):
(JSC::MarkedBlock::recycle):
(JSC::MarkedBlock::MarkedBlock):
(JSC::MarkedBlock::callDestructor): Templatized, along with specializedSweep and sweepHelper, to make
checking the m_cellsNeedDestructor flag faster and cleaner looking.
(JSC):
(JSC::MarkedBlock::specializedSweep):
(JSC::MarkedBlock::sweep):
(JSC::MarkedBlock::sweepHelper):

  • heap/MarkedBlock.h:

(MarkedBlock):
(JSC::MarkedBlock::cellsNeedDestruction):
(JSC):

  • heap/MarkedSpace.cpp:

(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::resetAllocators):
(JSC::MarkedSpace::canonicalizeCellLivenessData):
(JSC::TakeIfUnmarked::operator()):

  • heap/MarkedSpace.h:

(MarkedSpace):
(Subspace):
(JSC::MarkedSpace::allocatorFor): Needed function to differentiate between the two broad subspaces of
allocators.
(JSC):
(JSC::MarkedSpace::destructorAllocatorFor): Ditto.
(JSC::MarkedSpace::allocateWithoutDestructor): Ditto.
(JSC::MarkedSpace::allocateWithDestructor): Ditto.
(JSC::MarkedSpace::forEachBlock):

  • jit/JIT.h:
  • jit/JITInlineMethods.h: Modified to use the proper allocator for JSFinalObjects and others.

(JSC::JIT::emitAllocateBasicJSObject):
(JSC::JIT::emitAllocateJSFinalObject):
(JSC::JIT::emitAllocateJSFunction):

  • runtime/JSArray.cpp:

(JSC):

  • runtime/JSArray.h:

(JSArray):
(JSC::JSArray::create):
(JSC):
(JSC::JSArray::tryCreateUninitialized):

  • runtime/JSCell.h:

(JSCell):
(JSC):
(NeedsDestructor): Template struct that calculates at compile time whether the class in question requires
destruction or not using the compiler type trait has_trivial_destructor. allocateCell then checks this
constant to decide whether to allocate in the destructor or destructor-free parts of the heap.
(JSC::allocateCell):

  • runtime/JSFunction.cpp:

(JSC):

  • runtime/JSFunction.h:

(JSFunction):

  • runtime/JSObject.cpp:

(JSC):

  • runtime/JSObject.h:

(JSNonFinalObject):
(JSC):
(JSFinalObject):
(JSC::JSFinalObject::create):

Source/WebCore:

No new tests.

  • bindings/js/JSDOMWindowShell.cpp: Removed old operator new, which was just used in the create

function so that we can use allocateCell instead.
(WebCore):

  • bindings/js/JSDOMWindowShell.h:

(WebCore::JSDOMWindowShell::create):
(JSDOMWindowShell):

  • bindings/scripts/CodeGeneratorJS.pm: Added destructor back to root JS DOM nodes (e.g. JSNode, etc)

because their destroy functions need to be called, so we don't want the NeedsDestructor struct to
think they don't need destruction due to having empty/trivial destructors.
Removed ASSERT_HAS_TRIVIAL_DESTRUCTOR from all JS DOM wrapper auto-generated objects because their
ancestors now have non-trivial destructors.
(GenerateHeader):
(GenerateImplementation):
(GenerateConstructorDefinition):

Location:
trunk/Source
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r107421 r107445  
     12012-02-10  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        Split MarkedSpace into destructor and destructor-free subspaces
     4        https://bugs.webkit.org/show_bug.cgi?id=77761
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * dfg/DFGSpeculativeJIT.h:
     9        (JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject): Switched over to use destructor-free space.
     10        * heap/Heap.h:
     11        (JSC::Heap::allocatorForObjectWithoutDestructor): Added to give clients (e.g. the JIT) the ability to
     12        pick which subspace they want to allocate out of.
     13        (JSC::Heap::allocatorForObjectWithDestructor): Ditto.
     14        (Heap):
     15        (JSC::Heap::allocateWithDestructor): Added private function for CellAllocator to use.
     16        (JSC):
     17        (JSC::Heap::allocateWithoutDestructor): Ditto.
     18        * heap/MarkedAllocator.cpp: Added the cellsNeedDestruction flag to allocators so that they can allocate
     19        their MarkedBlocks correctly.
     20        (JSC::MarkedAllocator::allocateBlock):
     21        * heap/MarkedAllocator.h:
     22        (JSC::MarkedAllocator::cellsNeedDestruction):
     23        (MarkedAllocator):
     24        (JSC::MarkedAllocator::MarkedAllocator):
     25        (JSC):
     26        (JSC::MarkedAllocator::init): Replaced custom set functions, which were only used upon initialization, with
     27        an init function that does all of that stuff in fewer lines.
     28        * heap/MarkedBlock.cpp:
     29        (JSC::MarkedBlock::create):
     30        (JSC::MarkedBlock::recycle):
     31        (JSC::MarkedBlock::MarkedBlock):
     32        (JSC::MarkedBlock::callDestructor): Templatized, along with specializedSweep and sweepHelper, to make
     33        checking the m_cellsNeedDestructor flag faster and cleaner looking.
     34        (JSC):
     35        (JSC::MarkedBlock::specializedSweep):
     36        (JSC::MarkedBlock::sweep):
     37        (JSC::MarkedBlock::sweepHelper):
     38        * heap/MarkedBlock.h:
     39        (MarkedBlock):
     40        (JSC::MarkedBlock::cellsNeedDestruction):
     41        (JSC):
     42        * heap/MarkedSpace.cpp:
     43        (JSC::MarkedSpace::MarkedSpace):
     44        (JSC::MarkedSpace::resetAllocators):
     45        (JSC::MarkedSpace::canonicalizeCellLivenessData):
     46        (JSC::TakeIfUnmarked::operator()):
     47        * heap/MarkedSpace.h:
     48        (MarkedSpace):
     49        (Subspace):
     50        (JSC::MarkedSpace::allocatorFor): Needed function to differentiate between the two broad subspaces of
     51        allocators.
     52        (JSC):
     53        (JSC::MarkedSpace::destructorAllocatorFor): Ditto.
     54        (JSC::MarkedSpace::allocateWithoutDestructor): Ditto.
     55        (JSC::MarkedSpace::allocateWithDestructor): Ditto.
     56        (JSC::MarkedSpace::forEachBlock):
     57        * jit/JIT.h:
     58        * jit/JITInlineMethods.h: Modified to use the proper allocator for JSFinalObjects and others.
     59        (JSC::JIT::emitAllocateBasicJSObject):
     60        (JSC::JIT::emitAllocateJSFinalObject):
     61        (JSC::JIT::emitAllocateJSFunction):
     62        * runtime/JSArray.cpp:
     63        (JSC):
     64        * runtime/JSArray.h:
     65        (JSArray):
     66        (JSC::JSArray::create):
     67        (JSC):
     68        (JSC::JSArray::tryCreateUninitialized):
     69        * runtime/JSCell.h:
     70        (JSCell):
     71        (JSC):
     72        (NeedsDestructor): Template struct that calculates at compile time whether the class in question requires
     73        destruction or not using the compiler type trait __has_trivial_destructor. allocateCell then checks this
     74        constant to decide whether to allocate in the destructor or destructor-free parts of the heap.
     75        (JSC::allocateCell):
     76        * runtime/JSFunction.cpp:
     77        (JSC):
     78        * runtime/JSFunction.h:
     79        (JSFunction):
     80        * runtime/JSObject.cpp:
     81        (JSC):
     82        * runtime/JSObject.h:
     83        (JSNonFinalObject):
     84        (JSC):
     85        (JSFinalObject):
     86        (JSC::JSFinalObject::create):
     87
    1882012-02-10  Adrienne Walker  <enne@google.com>
    289
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r106775 r107445  
    15661566    void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
    15671567    {
    1568         MarkedAllocator* allocator = &m_jit.globalData()->heap.allocatorForObject(sizeof(JSFinalObject));
     1568        MarkedAllocator* allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(JSFinalObject));
    15691569       
    15701570        m_jit.loadPtr(&allocator->m_firstFreeCell, resultGPR);
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r106676 r107445  
    9696        inline bool isBusy();
    9797       
    98         MarkedAllocator& allocatorForObject(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
    99         void* allocate(size_t);
     98        MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
     99        MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
    100100        CheckedBoolean tryAllocateStorage(size_t, void**);
    101101        CheckedBoolean tryReallocateStorage(void**, size_t, size_t);
     
    143143        friend class SlotVisitor;
    144144        friend class CodeBlock;
     145        template<typename T> friend void* allocateCell(Heap&);
     146
     147        void* allocateWithDestructor(size_t);
     148        void* allocateWithoutDestructor(size_t);
    145149
    146150        size_t waterMark();
     
    335339    }
    336340
    337     inline void* Heap::allocate(size_t bytes)
     341    inline void* Heap::allocateWithDestructor(size_t bytes)
    338342    {
    339343        ASSERT(isValidAllocation(bytes));
    340         return m_objectSpace.allocate(bytes);
     344        return m_objectSpace.allocateWithDestructor(bytes);
     345    }
     346   
     347    inline void* Heap::allocateWithoutDestructor(size_t bytes)
     348    {
     349        ASSERT(isValidAllocation(bytes));
     350        return m_objectSpace.allocateWithoutDestructor(bytes);
    341351    }
    342352   
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp

    r106677 r107445  
    9898    }
    9999    if (block)
    100         block = MarkedBlock::recycle(block, m_heap, m_cellSize);
     100        block = MarkedBlock::recycle(block, m_heap, m_cellSize, m_cellsNeedDestruction);
    101101    else if (allocationEffort == AllocationCanFail)
    102102        return 0;
    103103    else
    104         block = MarkedBlock::create(m_heap, m_cellSize);
     104        block = MarkedBlock::create(m_heap, m_cellSize, m_cellsNeedDestruction);
    105105   
    106106    m_markedSpace->didAddBlock(block);
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.h

    r106677 r107445  
    2323    void zapFreeList();
    2424    size_t cellSize() { return m_cellSize; }
     25    bool cellsNeedDestruction() { return m_cellsNeedDestruction; }
    2526    void* allocate();
    2627    Heap* heap() { return m_heap; }
     
    3031    void addBlock(MarkedBlock*);
    3132    void removeBlock(MarkedBlock*);
    32     void setHeap(Heap* heap) { m_heap = heap; }
    33     void setCellSize(size_t cellSize) { m_cellSize = cellSize; }
    34     void setMarkedSpace(MarkedSpace* space) { m_markedSpace = space; }
     33    void init(Heap*, MarkedSpace*, size_t cellSize, bool cellsNeedDestruction);
    3534   
    3635private:
     
    4443    DoublyLinkedList<HeapBlock> m_blockList;
    4544    size_t m_cellSize;
     45    bool m_cellsNeedDestruction;
    4646    Heap* m_heap;
    4747    MarkedSpace* m_markedSpace;
     
    5252    , m_currentBlock(0)
    5353    , m_cellSize(0)
     54    , m_cellsNeedDestruction(true)
    5455    , m_heap(0)
    5556    , m_markedSpace(0)
    5657{
    5758}
    58    
     59
     60inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, bool cellsNeedDestruction)
     61{
     62    m_heap = heap;
     63    m_markedSpace = markedSpace;
     64    m_cellSize = cellSize;
     65    m_cellsNeedDestruction = cellsNeedDestruction;
     66}
     67
    5968inline void* MarkedAllocator::allocate()
    6069{
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp

    r106686 r107445  
    3333namespace JSC {
    3434
    35 MarkedBlock* MarkedBlock::create(Heap* heap, size_t cellSize)
     35MarkedBlock* MarkedBlock::create(Heap* heap, size_t cellSize, bool cellsNeedDestruction)
    3636{
    3737    PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockSize, OSAllocator::JSGCHeapPages);
    3838    if (!static_cast<bool>(allocation))
    3939        CRASH();
    40     return new (NotNull, allocation.base()) MarkedBlock(allocation, heap, cellSize);
    41 }
    42 
    43 MarkedBlock* MarkedBlock::recycle(MarkedBlock* block, Heap* heap, size_t cellSize)
    44 {
    45     return new (NotNull, block) MarkedBlock(block->m_allocation, heap, cellSize);
     40    return new (NotNull, allocation.base()) MarkedBlock(allocation, heap, cellSize, cellsNeedDestruction);
     41}
     42
     43MarkedBlock* MarkedBlock::recycle(MarkedBlock* block, Heap* heap, size_t cellSize, bool cellsNeedDestruction)
     44{
     45    return new (NotNull, block) MarkedBlock(block->m_allocation, heap, cellSize, cellsNeedDestruction);
    4646}
    4747
     
    5151}
    5252
    53 MarkedBlock::MarkedBlock(PageAllocationAligned& allocation, Heap* heap, size_t cellSize)
     53MarkedBlock::MarkedBlock(PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction)
    5454    : HeapBlock(allocation)
    5555    , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
    5656    , m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
     57    , m_cellsNeedDestruction(cellsNeedDestruction)
    5758    , m_state(New) // All cells start out unmarked.
    5859    , m_heap(heap)
     
    7172    m_heap->m_destroyedTypeCounts.countVPtr(vptr);
    7273#endif
    73     if (cell->classInfo() != &JSFinalObject::s_info)
    74         cell->methodTable()->destroy(cell);
     74    ASSERT(cell->classInfo() != &JSFinalObject::s_info);
     75    cell->methodTable()->destroy(cell);
    7576
    7677    cell->zap();
    7778}
    7879
    79 template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode>
     80template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode, bool destructorCallNeeded>
    8081MarkedBlock::FreeCell* MarkedBlock::specializedSweep()
    8182{
    8283    ASSERT(blockState != Allocated && blockState != FreeListed);
     84    ASSERT(destructorCallNeeded || sweepMode != SweepOnly);
    8385
    8486    // This produces a free list that is ordered in reverse through the block.
     
    9496            continue;
    9597
    96         if (blockState != New)
     98        if (destructorCallNeeded && blockState != New)
    9799            callDestructor(cell);
    98100
     
    112114    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
    113115
     116    if (sweepMode == SweepOnly && !m_cellsNeedDestruction)
     117        return 0;
     118
     119    if (m_cellsNeedDestruction)
     120        return sweepHelper<true>(sweepMode);
     121    return sweepHelper<false>(sweepMode);
     122}
     123
     124template<bool destructorCallNeeded>
     125MarkedBlock::FreeCell* MarkedBlock::sweepHelper(SweepMode sweepMode)
     126{
    114127    switch (m_state) {
    115128    case New:
    116129        ASSERT(sweepMode == SweepToFreeList);
    117         return specializedSweep<New, SweepToFreeList>();
     130        return specializedSweep<New, SweepToFreeList, destructorCallNeeded>();
    118131    case FreeListed:
    119132        // Happens when a block transitions to fully allocated.
     
    125138    case Marked:
    126139        return sweepMode == SweepToFreeList
    127             ? specializedSweep<Marked, SweepToFreeList>()
    128             : specializedSweep<Marked, SweepOnly>();
     140            ? specializedSweep<Marked, SweepToFreeList, destructorCallNeeded>()
     141            : specializedSweep<Marked, SweepOnly, destructorCallNeeded>();
    129142    case Zapped:
    130143        return sweepMode == SweepToFreeList
    131             ? specializedSweep<Zapped, SweepToFreeList>()
    132             : specializedSweep<Zapped, SweepOnly>();
     144            ? specializedSweep<Zapped, SweepToFreeList, destructorCallNeeded>()
     145            : specializedSweep<Zapped, SweepOnly, destructorCallNeeded>();
    133146    }
    134147
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.h

    r106686 r107445  
    9090        };
    9191
    92         static MarkedBlock* create(Heap*, size_t cellSize);
    93         static MarkedBlock* recycle(MarkedBlock*, Heap*, size_t cellSize);
     92        static MarkedBlock* create(Heap*, size_t cellSize, bool cellsNeedDestruction);
     93        static MarkedBlock* recycle(MarkedBlock*, Heap*, size_t cellSize, bool cellsNeedDestruction);
    9494        static void destroy(MarkedBlock*);
    9595
     
    116116
    117117        size_t cellSize();
     118        bool cellsNeedDestruction();
    118119
    119120        size_t size();
     
    160161
    161162        enum BlockState { New, FreeListed, Allocated, Marked, Zapped };
     163        template<bool destructorCallNeeded> FreeCell* sweepHelper(SweepMode = SweepOnly);
    162164
    163165        typedef char Atom[atomSize];
    164166
    165         MarkedBlock(PageAllocationAligned&, Heap*, size_t cellSize);
     167        MarkedBlock(PageAllocationAligned&, Heap*, size_t cellSize, bool cellsNeedDestruction);
    166168        Atom* atoms();
    167169        size_t atomNumber(const void*);
    168170        void callDestructor(JSCell*);
    169         template<BlockState, SweepMode> FreeCell* specializedSweep();
     171        template<BlockState, SweepMode, bool destructorCallNeeded> FreeCell* specializedSweep();
    170172       
    171173#if ENABLE(GGC)
     
    180182        WTF::Bitmap<atomsPerBlock, WTF::BitmapNotAtomic> m_marks;
    181183#endif
     184        bool m_cellsNeedDestruction;
    182185        BlockState m_state;
    183186        Heap* m_heap;
     
    242245    {
    243246        return m_atomsPerCell * atomSize;
     247    }
     248
     249    inline bool MarkedBlock::cellsNeedDestruction()
     250    {
     251        return m_cellsNeedDestruction;
    244252    }
    245253
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp

    r106676 r107445  
    3737{
    3838    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    39         allocatorFor(cellSize).setCellSize(cellSize);
    40         allocatorFor(cellSize).setHeap(heap);
    41         allocatorFor(cellSize).setMarkedSpace(this);
     39        allocatorFor(cellSize).init(heap, this, cellSize, false);
     40        destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
    4241    }
    4342
    4443    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    45         allocatorFor(cellSize).setCellSize(cellSize);
    46         allocatorFor(cellSize).setHeap(heap);
    47         allocatorFor(cellSize).setMarkedSpace(this);
     44        allocatorFor(cellSize).init(heap, this, cellSize, false);
     45        destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
    4846    }
    4947}
     
    5452    m_nurseryWaterMark = 0;
    5553
    56     for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep)
     54    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    5755        allocatorFor(cellSize).reset();
     56        destructorAllocatorFor(cellSize).reset();
     57    }
    5858
    59     for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep)
     59    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    6060        allocatorFor(cellSize).reset();
     61        destructorAllocatorFor(cellSize).reset();
     62    }
    6163}
    6264
    6365void MarkedSpace::canonicalizeCellLivenessData()
    6466{
    65     for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep)
     67    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    6668        allocatorFor(cellSize).zapFreeList();
     69        destructorAllocatorFor(cellSize).zapFreeList();
     70    }
    6771
    68     for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep)
     72    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    6973        allocatorFor(cellSize).zapFreeList();
     74        destructorAllocatorFor(cellSize).zapFreeList();
     75    }
    7076}
    7177
     
    108114        return;
    109115   
    110     m_markedSpace->allocatorFor(block->cellSize()).removeBlock(block);
     116    m_markedSpace->allocatorFor(block).removeBlock(block);
    111117    m_empties.append(block);
    112118}
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.h

    r106676 r107445  
    5353
    5454    MarkedAllocator& allocatorFor(size_t);
    55     void* allocate(size_t);
     55    MarkedAllocator& allocatorFor(MarkedBlock*);
     56    MarkedAllocator& destructorAllocatorFor(size_t);
     57    void* allocateWithDestructor(size_t);
     58    void* allocateWithoutDestructor(size_t);
    5659   
    5760    void resetAllocators();
     
    8790    static const size_t impreciseCount = impreciseCutoff / impreciseStep;
    8891
    89     FixedArray<MarkedAllocator, preciseCount> m_preciseSizeClasses;
    90     FixedArray<MarkedAllocator, impreciseCount> m_impreciseSizeClasses;
     92    struct Subspace {
     93        FixedArray<MarkedAllocator, preciseCount> preciseAllocators;
     94        FixedArray<MarkedAllocator, impreciseCount> impreciseAllocators;
     95    };
     96
     97    Subspace m_destructorSpace;
     98    Subspace m_normalSpace;
     99
    91100    size_t m_waterMark;
    92101    size_t m_nurseryWaterMark;
     
    125134    ASSERT(bytes && bytes <= maxCellSize);
    126135    if (bytes <= preciseCutoff)
    127         return m_preciseSizeClasses[(bytes - 1) / preciseStep];
    128     return m_impreciseSizeClasses[(bytes - 1) / impreciseStep];
     136        return m_normalSpace.preciseAllocators[(bytes - 1) / preciseStep];
     137    return m_normalSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
    129138}
    130139
    131 inline void* MarkedSpace::allocate(size_t bytes)
     140inline MarkedAllocator& MarkedSpace::allocatorFor(MarkedBlock* block)
     141{
     142    if (block->cellsNeedDestruction())
     143        return destructorAllocatorFor(block->cellSize());
     144    return allocatorFor(block->cellSize());
     145}
     146
     147inline MarkedAllocator& MarkedSpace::destructorAllocatorFor(size_t bytes)
     148{
     149    ASSERT(bytes && bytes <= maxCellSize);
     150    if (bytes <= preciseCutoff)
     151        return m_destructorSpace.preciseAllocators[(bytes - 1) / preciseStep];
     152    return m_destructorSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
     153}
     154
     155inline void* MarkedSpace::allocateWithoutDestructor(size_t bytes)
    132156{
    133157    return allocatorFor(bytes).allocate();
     158}
     159
     160inline void* MarkedSpace::allocateWithDestructor(size_t bytes)
     161{
     162    return destructorAllocatorFor(bytes).allocate();
    134163}
    135164
     
    137166{
    138167    for (size_t i = 0; i < preciseCount; ++i) {
    139         m_preciseSizeClasses[i].forEachBlock(functor);
     168        m_normalSpace.preciseAllocators[i].forEachBlock(functor);
     169        m_destructorSpace.preciseAllocators[i].forEachBlock(functor);
    140170    }
    141171
    142172    for (size_t i = 0; i < impreciseCount; ++i) {
    143         m_impreciseSizeClasses[i].forEachBlock(functor);
     173        m_normalSpace.impreciseAllocators[i].forEachBlock(functor);
     174        m_destructorSpace.impreciseAllocators[i].forEachBlock(functor);
    144175    }
    145176
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r107126 r107445  
    336336        void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind);
    337337
    338         template<typename ClassType, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr);
     338        template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr);
    339339        template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
    340340        void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr);
  • trunk/Source/JavaScriptCore/jit/JITInlineMethods.h

    r107126 r107445  
    403403}
    404404
    405 template <typename ClassType, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, RegisterID result, RegisterID storagePtr)
    406 {
    407     MarkedAllocator* allocator = &m_globalData->heap.allocatorForObject(sizeof(ClassType));
     405template <typename ClassType, bool destructor, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, RegisterID result, RegisterID storagePtr)
     406{
     407    MarkedAllocator* allocator = 0;
     408    if (destructor)
     409        allocator = &m_globalData->heap.allocatorForObjectWithDestructor(sizeof(ClassType));
     410    else
     411        allocator = &m_globalData->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
    408412    loadPtr(&allocator->m_firstFreeCell, result);
    409413    addSlowCase(branchTestPtr(Zero, result));
     
    429433template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
    430434{
    431     emitAllocateBasicJSObject<JSFinalObject>(structure, result, scratch);
     435    emitAllocateBasicJSObject<JSFinalObject, false, T>(structure, result, scratch);
    432436}
    433437
    434438inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, RegisterID scopeChain, RegisterID result, RegisterID storagePtr)
    435439{
    436     emitAllocateBasicJSObject<JSFunction>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), result, storagePtr);
     440    emitAllocateBasicJSObject<JSFunction, true>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), result, storagePtr);
    437441
    438442    // store the function's scope chain
  • trunk/Source/JavaScriptCore/runtime/JSArray.cpp

    r106496 r107445  
    4343
    4444ASSERT_CLASS_FITS_IN_CELL(JSArray);
     45ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSArray);
    4546
    4647// Overview of JSArray
  • trunk/Source/JavaScriptCore/runtime/JSArray.h

    r106496 r107445  
    136136        static void finalize(JSCell*);
    137137
    138         static JSArray* create(JSGlobalData& globalData, Structure* structure, unsigned initialLength = 0)
    139         {
    140             JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
    141             array->finishCreation(globalData, initialLength);
    142             return array;
    143         }
     138        static JSArray* create(JSGlobalData&, Structure*, unsigned initialLength = 0);
    144139
    145140        // tryCreateUninitialized is used for fast construction of arrays whose size and
     
    148143        //   - call 'initializeIndex' for all properties in sequence, for 0 <= i < initialLength.
    149144        //   - called 'completeInitialization' after all properties have been initialized.
    150         static JSArray* tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
    151         {
    152             JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
    153             return array->tryFinishCreationUninitialized(globalData, initialLength);
    154         }
     145        static JSArray* tryCreateUninitialized(JSGlobalData&, Structure*, unsigned initialLength);
    155146
    156147        JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool throwException);
     
    300291    };
    301292
     293    inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
     294    {
     295        JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
     296        array->finishCreation(globalData, initialLength);
     297        return array;
     298    }
     299
     300    inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
     301    {
     302        JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
     303        return array->tryFinishCreationUninitialized(globalData, initialLength);
     304    }
     305
    302306    JSArray* asArray(JSValue);
    303307
  • trunk/Source/JavaScriptCore/runtime/JSCell.h

    r106783 r107445  
    6262        friend class JSValue;
    6363        friend class MarkedBlock;
     64        template<typename T> friend void* allocateCell(Heap&);
    6465
    6566    public:
     
    308309    }
    309310
    310     template <typename T> void* allocateCell(Heap& heap)
     311#if COMPILER(CLANG)
     312    template<class T>
     313    struct NeedsDestructor {
     314        static const bool value = !__has_trivial_destructor(T);
     315    };
     316#else
     317    // Write manual specializations for this struct template if you care about non-clang compilers.
     318    template<class T>
     319    struct NeedsDestructor {
     320        static const bool value = true;
     321    };
     322#endif
     323
     324    template<typename T>
     325    void* allocateCell(Heap& heap)
    311326    {
    312327#if ENABLE(GC_VALIDATION)
     
    315330        heap.globalData()->setInitializingObject(true);
    316331#endif
    317         JSCell* result = static_cast<JSCell*>(heap.allocate(sizeof(T)));
     332        JSCell* result = 0;
     333        if (NeedsDestructor<T>::value)
     334            result = static_cast<JSCell*>(heap.allocateWithDestructor(sizeof(T)));
     335        else {
     336            ASSERT(T::s_info.methodTable.destroy == JSCell::destroy);
     337            result = static_cast<JSCell*>(heap.allocateWithoutDestructor(sizeof(T)));
     338        }
    318339        result->clearStructure();
    319340        return result;
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r107128 r107445  
    5151
    5252ASSERT_CLASS_FITS_IN_CELL(JSFunction);
     53ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSFunction);
    5354
    5455const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFunction) };
     
    107108    setStructure(exec->globalData(), scopeChainNode->globalObject->namedFunctionStructure());
    108109    putDirectOffset(exec->globalData(), scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
    109 }
    110 
    111 void JSFunction::destroy(JSCell* cell)
    112 {
    113     JSFunction* thisObject = jsCast<JSFunction*>(cell);
    114     ASSERT(thisObject->classInfo()->isSubClassOf(&JSFunction::s_info));
    115     thisObject->JSFunction::~JSFunction();
    116110}
    117111
  • trunk/Source/JavaScriptCore/runtime/JSFunction.h

    r106504 r107445  
    6565        }
    6666       
    67         static void destroy(JSCell*);
    68 
    6967        JS_EXPORT_PRIVATE const UString& name(ExecState*);
    7068        JS_EXPORT_PRIVATE const UString displayName(ExecState*);
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r106783 r107445  
    4949
    5050ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSObject);
     51ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSFinalObject);
    5152
    5253const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
     
    5556
    5657const ClassInfo JSFinalObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFinalObject) };
    57 
    58 void JSFinalObject::destroy(JSCell* cell)
    59 {
    60     jsCast<JSFinalObject*>(cell)->JSFinalObject::~JSFinalObject();
    61 }
    62 
    63 void JSNonFinalObject::destroy(JSCell* cell)
    64 {
    65     jsCast<JSNonFinalObject*>(cell)->JSNonFinalObject::~JSNonFinalObject();
    66 }
    6758
    6859static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
     
    8374        }
    8475    }
    85 }
    86 
    87 void JSObject::destroy(JSCell* cell)
    88 {
    89     jsCast<JSObject*>(cell)->JSObject::~JSObject();
    9076}
    9177
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r106783 r107445  
    8585        typedef JSCell Base;
    8686
    87         JS_EXPORT_PRIVATE static void destroy(JSCell*);
    88 
    8987        JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
    9088
     
    324322        }
    325323
    326         JS_EXPORT_PRIVATE static void destroy(JSCell*);
    327 
    328324    protected:
    329325        explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
     
    344340    };
    345341
     342    class JSFinalObject;
     343
    346344    // JSFinalObject is a type of JSObject that contains sufficent internal
    347345    // storage to fully make use of the colloctor cell containing it.
     
    352350        typedef JSObject Base;
    353351
    354         static JSFinalObject* create(ExecState* exec, Structure* structure)
    355         {
    356             JSFinalObject* finalObject = new (NotNull, allocateCell<JSFinalObject>(*exec->heap())) JSFinalObject(exec->globalData(), structure);
    357             finalObject->finishCreation(exec->globalData());
    358             return finalObject;
    359         }
    360 
     352        static JSFinalObject* create(ExecState*, Structure*);
    361353        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
    362354        {
     
    375367        }
    376368
    377         static void destroy(JSCell*);
    378 
    379369    private:
    380370        explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
     
    387377        WriteBarrierBase<Unknown> m_inlineStorage[JSFinalObject_inlineStorageCapacity];
    388378    };
     379
     380inline JSFinalObject* JSFinalObject::create(ExecState* exec, Structure* structure)
     381{
     382    JSFinalObject* finalObject = new (NotNull, allocateCell<JSFinalObject>(*exec->heap())) JSFinalObject(exec->globalData(), structure);
     383    finalObject->finishCreation(exec->globalData());
     384    return finalObject;
     385}
    389386
    390387inline bool isJSFinalObject(JSCell* cell)
  • trunk/Source/WebCore/ChangeLog

    r107443 r107445  
     12012-02-10  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        Split MarkedSpace into destructor and destructor-free subspaces
     4        https://bugs.webkit.org/show_bug.cgi?id=77761
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        No new tests.
     9
     10        * bindings/js/JSDOMWindowShell.cpp: Removed old operator new, which was just used in the create
     11        function so that we can use allocateCell instead.
     12        (WebCore):
     13        * bindings/js/JSDOMWindowShell.h:
     14        (WebCore::JSDOMWindowShell::create):
     15        (JSDOMWindowShell):
     16        * bindings/scripts/CodeGeneratorJS.pm: Added destructor back to root JS DOM nodes (e.g. JSNode, etc)
     17        because their destroy functions need to be called, so we don't want the NeedsDestructor struct to
     18        think they don't need destruction due to having empty/trivial destructors.
     19        Removed ASSERT_HAS_TRIVIAL_DESTRUCTOR from all JS DOM wrapper auto-generated objects because their
     20        ancestors now have non-trivial destructors.
     21        (GenerateHeader):
     22        (GenerateImplementation):
     23        (GenerateConstructorDefinition):
     24
    1252012-02-10  Anders Carlsson  <andersca@apple.com>
    226
  • trunk/Source/WebCore/bindings/js/JSDOMWindowShell.cpp

    r106783 r107445  
    150150}
    151151
    152 void* JSDOMWindowShell::operator new(size_t size)
    153 {
    154     Heap& heap = JSDOMWindow::commonJSGlobalData()->heap;
    155 #if ENABLE(GC_VALIDATION)
    156     ASSERT(!heap.globalData()->isInitializingObject());
    157     heap.globalData()->setInitializingObject(true);
    158 #endif
    159     return heap.allocate(size);
    160 }
    161 
    162152// ----
    163153// Conversion methods
  • trunk/Source/WebCore/bindings/js/JSDOMWindowShell.h

    r106783 r107445  
    5959        static JSDOMWindowShell* create(PassRefPtr<DOMWindow> window, JSC::Structure* structure, DOMWrapperWorld* world)
    6060        {
    61             JSDOMWindowShell* shell = new JSDOMWindowShell(structure, world);
     61            JSC::Heap& heap = JSDOMWindow::commonJSGlobalData()->heap;
     62            JSDOMWindowShell* shell = new (NotNull, JSC::allocateCell<JSDOMWindowShell>(heap)) JSDOMWindowShell(structure, world);
    6263            shell->finishCreation(*world->globalData(), window);
    6364            return shell;
     
    7677
    7778    private:
    78         void* operator new(size_t);
    7979        static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetPropertyNames | Base::StructureFlags;
    8080
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r107436 r107445  
    795795    if (!$hasParent) {
    796796        push(@headerContent, "    static void destroy(JSC::JSCell*);\n");
     797        push(@headerContent, "    ~${className}();\n");
    797798    }
    798799
     
    13411342
    13421343    push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n");
    1343     if ($interfaceName ne "DOMWindow" && !$dataNode->extendedAttributes->{"IsWorkerContext"}) {
    1344         push(@implContent, "ASSERT_HAS_TRIVIAL_DESTRUCTOR($className);\n\n");
    1345     }
    13461344
    13471345    my $numAttributes = GenerateAttributesHashTable($object, $dataNode);
     
    16161614        push(@implContent, "{\n");
    16171615        push(@implContent, "    ${className}* thisObject = jsCast<${className}*>(cell);\n");
    1618         push(@implContent, "    thisObject->releaseImplIfNotNull();\n");
     1616        push(@implContent, "    thisObject->${className}::~${className}();\n");
     1617        push(@implContent, "}\n\n");
     1618
     1619        # We also need a destructor for the allocateCell to work properly with the destructor-free part of the heap.
     1620        # Otherwise, these destroy functions/destructors won't get called.
     1621        push(@implContent, "${className}::~${className}()\n");
     1622        push(@implContent, "{\n");
     1623        push(@implContent, "    releaseImplIfNotNull();\n");
    16191624        push(@implContent, "}\n\n");
    16201625    }
     
    33713376        push(@$outputArray, "}\n\n");
    33723377    } else {
    3373         push(@$outputArray, "ASSERT_HAS_TRIVIAL_DESTRUCTOR(${constructorClassName});\n\n");
    3374 
    33753378        push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &Base::s_info, &${constructorClassName}Table, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n");
    33763379        push(@$outputArray, "${constructorClassName}::${constructorClassName}(Structure* structure, JSDOMGlobalObject* globalObject)\n");
Note: See TracChangeset for help on using the changeset viewer.