Changeset 130303 in webkit for trunk/Source/JavaScriptCore/heap


Ignore:
Timestamp:
Oct 3, 2012, 10:51:28 AM (13 years ago)
Author:
[email protected]
Message:

Delayed structure sweep can leak structures without bound
https://bugs.webkit.org/show_bug.cgi?id=96546

Reviewed by Geoffrey Garen.

This patch gets rid of the separate Structure allocator in the MarkedSpace and adds two new destructor-only
allocators. We now have separate allocators for our three types of objects: those objects with no destructors,
those objects with destructors and with immortal structures, and those objects with destructors that don't have
immortal structures. All of the objects of the third type (destructors without immortal structures) now
inherit from a new class named JSDestructibleObject (which in turn is a subclass of JSNonFinalObject), which stores
the ClassInfo for these classes at a fixed offset for safe retrieval during sweeping/destruction.

Source/JavaScriptCore:

  • API/JSCallbackConstructor.cpp: Use JSDestructibleObject for JSCallbackConstructor.

(JSC):
(JSC::JSCallbackConstructor::JSCallbackConstructor):

  • API/JSCallbackConstructor.h:

(JSCallbackConstructor):

  • API/JSCallbackObject.cpp: Inherit from JSDestructibleObject for normal JSCallbackObjects and use a finalizer for

JSCallbackObject<JSGlobalObject>, since JSGlobalObject also uses a finalizer.
(JSC):
(JSC::::create): We need to move the create function for JSCallbackObject<JSGlobalObject> out of line so we can add
the finalizer for it. We don't want to add the finalizer is something like finishCreation in case somebody decides
to subclass this. We use this same technique for many other subclasses of JSGlobalObject.
(JSC::::createStructure):

  • API/JSCallbackObject.h:

(JSCallbackObject):
(JSC):

  • API/JSClassRef.cpp: Change all the JSCallbackObject<JSNonFinalObject> to use JSDestructibleObject instead.

(OpaqueJSClass::prototype):

  • API/JSObjectRef.cpp: Ditto.

(JSObjectMake):
(JSObjectGetPrivate):
(JSObjectSetPrivate):
(JSObjectGetPrivateProperty):
(JSObjectSetPrivateProperty):
(JSObjectDeletePrivateProperty):

  • API/JSValueRef.cpp: Ditto.

(JSValueIsObjectOfClass):

  • API/JSWeakObjectMapRefPrivate.cpp: Ditto.
  • JSCTypedArrayStubs.h:

(JSC):

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • dfg/DFGSpeculativeJIT.h: Use the proper allocator type when doing inline allocation in the DFG.

(JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
(JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):

  • heap/Heap.cpp:

(JSC):

  • heap/Heap.h: Add accessors for the various types of allocators now. Also remove the isSafeToSweepStructures function

since it's always safe to sweep Structures now.
(JSC::Heap::allocatorForObjectWithNormalDestructor):
(JSC::Heap::allocatorForObjectWithImmortalStructureDestructor):
(Heap):
(JSC::Heap::allocateWithNormalDestructor):
(JSC):
(JSC::Heap::allocateWithImmortalStructureDestructor):

  • heap/IncrementalSweeper.cpp: Remove all the logic to detect when it's safe to sweep Structures from the

IncrementalSweeper since it's always safe to sweep Structures now.
(JSC::IncrementalSweeper::IncrementalSweeper):
(JSC::IncrementalSweeper::sweepNextBlock):
(JSC::IncrementalSweeper::startSweeping):
(JSC::IncrementalSweeper::willFinishSweeping):
(JSC):

  • heap/IncrementalSweeper.h:

(IncrementalSweeper):

  • heap/MarkedAllocator.cpp: Remove the logic that was preventing us from sweeping Structures if it wasn't safe. Add

tracking of the specific destructor type of allocator.
(JSC::MarkedAllocator::tryAllocateHelper):
(JSC::MarkedAllocator::allocateBlock):

  • heap/MarkedAllocator.h:

(JSC::MarkedAllocator::destructorType):
(MarkedAllocator):
(JSC::MarkedAllocator::MarkedAllocator):
(JSC::MarkedAllocator::init):

  • heap/MarkedBlock.cpp: Add all the destructor type stuff to MarkedBlocks so that we do the right thing when sweeping.

We also use the stored destructor type to determine the right thing to do in all JSCell::classInfo() calls.
(JSC::MarkedBlock::create):
(JSC::MarkedBlock::MarkedBlock):
(JSC):
(JSC::MarkedBlock::specializedSweep):
(JSC::MarkedBlock::sweep):
(JSC::MarkedBlock::sweepHelper):

  • heap/MarkedBlock.h:

(JSC):
(JSC::MarkedBlock::allocator):
(JSC::MarkedBlock::destructorType):

  • heap/MarkedSpace.cpp: Add the new destructor allocators to MarkedSpace.

(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::resetAllocators):
(JSC::MarkedSpace::canonicalizeCellLivenessData):
(JSC::MarkedSpace::isPagedOut):
(JSC::MarkedSpace::freeBlock):

  • heap/MarkedSpace.h:

(MarkedSpace):
(JSC::MarkedSpace::immortalStructureDestructorAllocatorFor):
(JSC::MarkedSpace::normalDestructorAllocatorFor):
(JSC::MarkedSpace::allocateWithImmortalStructureDestructor):
(JSC::MarkedSpace::allocateWithNormalDestructor):
(JSC::MarkedSpace::forEachBlock):

  • heap/SlotVisitor.cpp: Add include because the symbol was needed in an inlined function.
  • jit/JIT.h: Make sure we use the correct allocator when doing inline allocations in the baseline JIT.
  • jit/JITInlineMethods.h:

(JSC::JIT::emitAllocateBasicJSObject):
(JSC::JIT::emitAllocateJSFinalObject):
(JSC::JIT::emitAllocateJSArray):

  • jsc.cpp:

(GlobalObject::create): Add finalizer here since JSGlobalObject needs to use a finalizer instead of inheriting from
JSDestructibleObject.

  • runtime/Arguments.cpp: Inherit from JSDestructibleObject.

(JSC):

  • runtime/Arguments.h:

(Arguments):
(JSC::Arguments::Arguments):

  • runtime/ErrorPrototype.cpp: Added an assert to make sure we have a trivial destructor.

(JSC):

  • runtime/Executable.h: Indicate that all of the Executable* classes have immortal Structures.

(JSC):

  • runtime/InternalFunction.cpp: Inherit from JSDestructibleObject.

(JSC):
(JSC::InternalFunction::InternalFunction):

  • runtime/InternalFunction.h:

(InternalFunction):

  • runtime/JSCell.h: Added two static bools, needsDestruction and hasImmortalStructure, that classes can override

to indicate at compile time which part of the heap they should be allocated in.
(JSC::allocateCell): Use the appropriate allocator depending on the destructor type.

  • runtime/JSDestructibleObject.h: Added. New class that stores the ClassInfo of any subclass so that it can be

accessed safely when the object is being destroyed.
(JSC):
(JSDestructibleObject):
(JSC::JSDestructibleObject::classInfo):
(JSC::JSDestructibleObject::JSDestructibleObject):
(JSC::JSCell::classInfo): Checks the current MarkedBlock to see where it should get the ClassInfo from so that it's always safe.

  • runtime/JSGlobalObject.cpp: JSGlobalObject now uses a finalizer instead of a destructor so that it can avoid forcing all

of its relatives in the inheritance hierarchy (e.g. JSScope) to use destructors as well.
(JSC::JSGlobalObject::reset):

  • runtime/JSGlobalObject.h:

(JSGlobalObject):
(JSC::JSGlobalObject::createRareDataIfNeeded): Since we always create a finalizer now, we don't have to worry about adding one
for the m_rareData field when it's created.
(JSC::JSGlobalObject::create):
(JSC):

  • runtime/JSGlobalThis.h: Inherit from JSDestructibleObject.

(JSGlobalThis):
(JSC::JSGlobalThis::JSGlobalThis):

  • runtime/JSPropertyNameIterator.h: Has an immortal Structure.

(JSC):

  • runtime/JSScope.cpp:

(JSC):

  • runtime/JSString.h: Has an immortal Structure.

(JSC):

  • runtime/JSWrapperObject.h: Inherit from JSDestructibleObject.

(JSWrapperObject):
(JSC::JSWrapperObject::JSWrapperObject):

  • runtime/MathObject.cpp: Cleaning up some of the inheritance stuff.

(JSC):

  • runtime/NameInstance.h: Inherit from JSDestructibleObject.

(NameInstance):

  • runtime/RegExp.h: Has immortal Structure.

(JSC):

  • runtime/RegExpObject.cpp: Inheritance cleanup.

(JSC):

  • runtime/SparseArrayValueMap.h: Has immortal Structure.

(JSC):

  • runtime/Structure.h: Has immortal Structure.

(JSC):

  • runtime/StructureChain.h: Ditto.

(JSC):

  • runtime/SymbolTable.h: Ditto.

(SharedSymbolTable):
(JSC):

Source/WebCore:

No new tests.

  • ForwardingHeaders/runtime/JSDestructableObject.h: Added.
  • bindings/js/JSDOMWrapper.h: Inherits from JSDestructibleObject.

(JSDOMWrapper):
(WebCore::JSDOMWrapper::JSDOMWrapper):

  • bindings/scripts/CodeGeneratorJS.pm: Add finalizers to anything that inherits from JSGlobalObject,

e.g. JSDOMWindow and JSWorkerContexts. For those classes we also need to define needsDestruction as true.
(GenerateHeader):

  • bridge/objc/objc_runtime.h: Inherit from JSDestructibleObject.

(ObjcFallbackObjectImp):

  • bridge/objc/objc_runtime.mm:

(Bindings):
(JSC::Bindings::ObjcFallbackObjectImp::ObjcFallbackObjectImp):

  • bridge/runtime_array.cpp: Use a finalizer so that JSArray isn't forced to inherit from JSDestructibleObject.

(JSC):
(JSC::RuntimeArray::destroy):

  • bridge/runtime_array.h:

(JSC::RuntimeArray::create):
(JSC):

  • bridge/runtime_object.cpp: Inherit from JSDestructibleObject.

(Bindings):
(JSC::Bindings::RuntimeObject::RuntimeObject):

  • bridge/runtime_object.h:

(RuntimeObject):

Location:
trunk/Source/JavaScriptCore/heap
Files:
11 edited

Legend:

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

    r129586 r130303  
    943943}
    944944
    945 bool Heap::isSafeToSweepStructures()
    946 {
    947     return !m_sweeper || m_sweeper->structuresCanBeSwept();
    948 }
    949 
    950945void Heap::didStartVMShutdown()
    951946{
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r129586 r130303  
    113113        MarkedAllocator& firstAllocatorWithoutDestructors() { return m_objectSpace.firstAllocator(); }
    114114        MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
    115         MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
     115        MarkedAllocator& allocatorForObjectWithNormalDestructor(size_t bytes) { return m_objectSpace.normalDestructorAllocatorFor(bytes); }
     116        MarkedAllocator& allocatorForObjectWithImmortalStructureDestructor(size_t bytes) { return m_objectSpace.immortalStructureDestructorAllocatorFor(bytes); }
    116117        CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); }
    117118        CheckedBoolean tryAllocateStorage(size_t, void**);
     
    170171
    171172        bool isPagedOut(double deadline);
    172         bool isSafeToSweepStructures();
    173173        void didStartVMShutdown();
    174174
     
    186186        template<typename T> friend void* allocateCell(Heap&, size_t);
    187187
    188         void* allocateWithDestructor(size_t);
    189         void* allocateWithoutDestructor(size_t);
    190         void* allocateStructure(size_t);
     188        void* allocateWithImmortalStructureDestructor(size_t); // For use with special objects whose Structures never die.
     189        void* allocateWithNormalDestructor(size_t); // For use with objects that inherit directly or indirectly from JSDestructibleObject.
     190        void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
    191191
    192192        static const size_t minExtraCost = 256;
     
    364364    }
    365365
    366     inline void* Heap::allocateWithDestructor(size_t bytes)
     366    inline void* Heap::allocateWithNormalDestructor(size_t bytes)
    367367    {
    368368        ASSERT(isValidAllocation(bytes));
    369         return m_objectSpace.allocateWithDestructor(bytes);
     369        return m_objectSpace.allocateWithNormalDestructor(bytes);
     370    }
     371   
     372    inline void* Heap::allocateWithImmortalStructureDestructor(size_t bytes)
     373    {
     374        ASSERT(isValidAllocation(bytes));
     375        return m_objectSpace.allocateWithImmortalStructureDestructor(bytes);
    370376    }
    371377   
     
    376382    }
    377383   
    378     inline void* Heap::allocateStructure(size_t bytes)
    379     {
    380         return m_objectSpace.allocateStructure(bytes);
    381     }
    382  
    383384    inline CheckedBoolean Heap::tryAllocateStorage(size_t bytes, void** outPtr)
    384385    {
  • trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp

    r128851 r130303  
    4949    : HeapTimer(heap->globalData(), runLoop)
    5050    , m_currentBlockToSweepIndex(0)
    51     , m_structuresCanBeSwept(false)
    5251{
    5352}
     
    7372    : HeapTimer(heap->globalData())
    7473    , m_currentBlockToSweepIndex(0)
    75     , m_structuresCanBeSwept(false)
    7674{
    7775}
     
    120118    while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
    121119        MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++];
    122         if (block->onlyContainsStructures())
    123             m_structuresCanBeSwept = true;
    124         else
    125             ASSERT(!m_structuresCanBeSwept);
    126120
    127121        if (!block->needsSweeping())
     
    140134    m_globalData->heap.objectSpace().forEachBlock(functor);
    141135    m_currentBlockToSweepIndex = 0;
    142     m_structuresCanBeSwept = false;
    143136    scheduleTimer();
    144137}
     
    147140{
    148141    m_currentBlockToSweepIndex = 0;
    149     m_structuresCanBeSwept = true;
    150142    m_blocksToSweep.clear();
    151143    if (m_globalData)
     
    157149IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData)
    158150    : HeapTimer(globalData)
    159     , m_structuresCanBeSwept(false)
    160151{
    161152}
     
    172163void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>&)
    173164{
    174     m_structuresCanBeSwept = false;
    175165}
    176166
    177167void IncrementalSweeper::willFinishSweeping()
    178168{
    179     m_structuresCanBeSwept = true;
    180169}
    181170
     
    186175#endif
    187176
    188 bool IncrementalSweeper::structuresCanBeSwept()
    189 {
    190     return m_structuresCanBeSwept;
    191 }
    192 
    193177} // namespace JSC
  • trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h

    r128851 r130303  
    5757    virtual void doWork();
    5858    void sweepNextBlock();
    59     bool structuresCanBeSwept();
    6059    void willFinishSweeping();
    6160
     
    7978   
    8079#endif
    81     bool m_structuresCanBeSwept;
    8280};
    8381
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp

    r128851 r130303  
    3131{
    3232    if (!m_freeList.head) {
    33         if (m_onlyContainsStructures && !m_heap->isSafeToSweepStructures()) {
    34             if (m_currentBlock) {
    35                 m_currentBlock->didConsumeFreeList();
    36                 m_currentBlock = 0;
    37             }
    38             // We sweep another random block here so that we can make progress
    39             // toward being able to sweep Structures.
    40             m_heap->sweeper()->sweepNextBlock();
    41             return 0;
    42         }
    43 
    4433        for (MarkedBlock*& block = m_blocksToSweep; block; block = block->next()) {
    4534            MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
     
    125114    if (blockSize == MarkedBlock::blockSize) {
    126115        PageAllocationAligned allocation = m_heap->blockAllocator().allocate();
    127         return MarkedBlock::create(allocation, m_heap, cellSize, m_cellsNeedDestruction, m_onlyContainsStructures);
     116        return MarkedBlock::create(allocation, this, cellSize, m_destructorType);
    128117    }
    129118
     
    131120    if (!static_cast<bool>(allocation))
    132121        CRASH();
    133     return MarkedBlock::create(allocation, m_heap, cellSize, m_cellsNeedDestruction, m_onlyContainsStructures);
     122    return MarkedBlock::create(allocation, this, cellSize, m_destructorType);
    134123}
    135124
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.h

    r128851 r130303  
    2424    void canonicalizeCellLivenessData();
    2525    size_t cellSize() { return m_cellSize; }
    26     bool cellsNeedDestruction() { return m_cellsNeedDestruction; }
    27     bool onlyContainsStructures() { return m_onlyContainsStructures; }
     26    MarkedBlock::DestructorType destructorType() { return m_destructorType; }
    2827    void* allocate(size_t);
    2928    Heap* heap() { return m_heap; }
     
    3332    void addBlock(MarkedBlock*);
    3433    void removeBlock(MarkedBlock*);
    35     void init(Heap*, MarkedSpace*, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures);
     34    void init(Heap*, MarkedSpace*, size_t cellSize, MarkedBlock::DestructorType);
    3635
    3736    bool isPagedOut(double deadline);
     
    5049    DoublyLinkedList<MarkedBlock> m_blockList;
    5150    size_t m_cellSize;
    52     bool m_cellsNeedDestruction;
    53     bool m_onlyContainsStructures;
     51    MarkedBlock::DestructorType m_destructorType;
    5452    Heap* m_heap;
    5553    MarkedSpace* m_markedSpace;
     
    6058    , m_blocksToSweep(0)
    6159    , m_cellSize(0)
    62     , m_cellsNeedDestruction(true)
    63     , m_onlyContainsStructures(false)
     60    , m_destructorType(MarkedBlock::None)
    6461    , m_heap(0)
    6562    , m_markedSpace(0)
     
    6764}
    6865
    69 inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures)
     66inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, MarkedBlock::DestructorType destructorType)
    7067{
    7168    m_heap = heap;
    7269    m_markedSpace = markedSpace;
    7370    m_cellSize = cellSize;
    74     m_cellsNeedDestruction = cellsNeedDestruction;
    75     m_onlyContainsStructures = onlyContainsStructures;
     71    m_destructorType = destructorType;
    7672}
    7773
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp

    r128851 r130303  
    2929#include "IncrementalSweeper.h"
    3030#include "JSCell.h"
    31 #include "JSObject.h"
     31#include "JSDestructibleObject.h"
    3232
    3333
    3434namespace JSC {
    3535
    36 MarkedBlock* MarkedBlock::create(const PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures)
     36MarkedBlock* MarkedBlock::create(const PageAllocationAligned& allocation, MarkedAllocator* allocator, size_t cellSize, DestructorType destructorType)
    3737{
    38     return new (NotNull, allocation.base()) MarkedBlock(allocation, heap, cellSize, cellsNeedDestruction, onlyContainsStructures);
     38    return new (NotNull, allocation.base()) MarkedBlock(allocation, allocator, cellSize, destructorType);
    3939}
    4040
    41 MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures)
     41MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, MarkedAllocator* allocator, size_t cellSize, DestructorType destructorType)
    4242    : HeapBlock<MarkedBlock>(allocation)
    4343    , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
    4444    , m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
    45     , m_cellsNeedDestruction(cellsNeedDestruction)
    46     , m_onlyContainsStructures(onlyContainsStructures)
     45    , m_destructorType(destructorType)
     46    , m_allocator(allocator)
    4747    , m_state(New) // All cells start out unmarked.
    48     , m_weakSet(heap->globalData())
     48    , m_weakSet(allocator->heap()->globalData())
    4949{
    50     ASSERT(heap);
     50    ASSERT(allocator);
    5151    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
    5252}
     
    6666}
    6767
    68 template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode, bool destructorCallNeeded>
     68template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode, MarkedBlock::DestructorType dtorType>
    6969MarkedBlock::FreeList MarkedBlock::specializedSweep()
    7070{
    7171    ASSERT(blockState != Allocated && blockState != FreeListed);
    72     ASSERT(destructorCallNeeded || sweepMode != SweepOnly);
     72    ASSERT(!(dtorType == MarkedBlock::None && sweepMode == SweepOnly));
    7373
    7474    // This produces a free list that is ordered in reverse through the block.
     
    8383        JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
    8484
    85         if (destructorCallNeeded && blockState != New)
     85        if (dtorType != MarkedBlock::None && blockState != New)
    8686            callDestructor(cell);
    8787
     
    104104    m_weakSet.sweep();
    105105
    106     if (sweepMode == SweepOnly && !m_cellsNeedDestruction)
     106    if (sweepMode == SweepOnly && m_destructorType == MarkedBlock::None)
    107107        return FreeList();
    108108
    109     if (m_cellsNeedDestruction)
    110         return sweepHelper<true>(sweepMode);
    111     return sweepHelper<false>(sweepMode);
     109    if (m_destructorType == MarkedBlock::ImmortalStructure)
     110        return sweepHelper<MarkedBlock::ImmortalStructure>(sweepMode);
     111    if (m_destructorType == MarkedBlock::Normal)
     112        return sweepHelper<MarkedBlock::Normal>(sweepMode);
     113    return sweepHelper<MarkedBlock::None>(sweepMode);
    112114}
    113115
    114 template<bool destructorCallNeeded>
     116template<MarkedBlock::DestructorType dtorType>
    115117MarkedBlock::FreeList MarkedBlock::sweepHelper(SweepMode sweepMode)
    116118{
     
    118120    case New:
    119121        ASSERT(sweepMode == SweepToFreeList);
    120         return specializedSweep<New, SweepToFreeList, destructorCallNeeded>();
     122        return specializedSweep<New, SweepToFreeList, dtorType>();
    121123    case FreeListed:
    122124        // Happens when a block transitions to fully allocated.
     
    127129        return FreeList();
    128130    case Marked:
    129         ASSERT(!m_onlyContainsStructures || heap()->isSafeToSweepStructures());
    130131        return sweepMode == SweepToFreeList
    131             ? specializedSweep<Marked, SweepToFreeList, destructorCallNeeded>()
    132             : specializedSweep<Marked, SweepOnly, destructorCallNeeded>();
     132            ? specializedSweep<Marked, SweepToFreeList, dtorType>()
     133            : specializedSweep<Marked, SweepOnly, dtorType>();
    133134    }
    134135
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.h

    r128851 r130303  
    5353    class Heap;
    5454    class JSCell;
     55    class MarkedAllocator;
    5556
    5657    typedef uintptr_t Bits;
     
    113114        };
    114115
    115         static MarkedBlock* create(const PageAllocationAligned&, Heap*, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures);
     116        enum DestructorType { None, ImmortalStructure, Normal };
     117        static MarkedBlock* create(const PageAllocationAligned&, MarkedAllocator*, size_t cellSize, DestructorType);
    116118
    117119        static bool isAtomAligned(const void*);
     
    121123        void lastChanceToFinalize();
    122124
     125        MarkedAllocator* allocator() const;
    123126        Heap* heap() const;
    124127        JSGlobalData* globalData() const;
     
    144147
    145148        size_t cellSize();
    146         bool cellsNeedDestruction();
    147         bool onlyContainsStructures();
     149        DestructorType destructorType();
    148150
    149151        size_t size();
     
    195197
    196198        enum BlockState { New, FreeListed, Allocated, Marked };
    197         template<bool destructorCallNeeded> FreeList sweepHelper(SweepMode = SweepOnly);
     199        template<DestructorType> FreeList sweepHelper(SweepMode = SweepOnly);
    198200
    199201        typedef char Atom[atomSize];
    200202
    201         MarkedBlock(const PageAllocationAligned&, Heap*, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures);
     203        MarkedBlock(const PageAllocationAligned&, MarkedAllocator*, size_t cellSize, DestructorType);
    202204        Atom* atoms();
    203205        size_t atomNumber(const void*);
    204206        void callDestructor(JSCell*);
    205         template<BlockState, SweepMode, bool destructorCallNeeded> FreeList specializedSweep();
     207        template<BlockState, SweepMode, DestructorType> FreeList specializedSweep();
    206208       
    207209#if ENABLE(GGC)
     
    216218        WTF::Bitmap<atomsPerBlock, WTF::BitmapNotAtomic> m_marks;
    217219#endif
    218         bool m_cellsNeedDestruction;
    219         bool m_onlyContainsStructures;
     220        DestructorType m_destructorType;
     221        MarkedAllocator* m_allocator;
    220222        BlockState m_state;
    221223        WeakSet m_weakSet;
     
    262264    }
    263265
     266    inline MarkedAllocator* MarkedBlock::allocator() const
     267    {
     268        return m_allocator;
     269    }
     270
    264271    inline Heap* MarkedBlock::heap() const
    265272    {
     
    327334    }
    328335
    329     inline bool MarkedBlock::cellsNeedDestruction()
    330     {
    331         return m_cellsNeedDestruction;
    332     }
    333 
    334     inline bool MarkedBlock::onlyContainsStructures()
    335     {
    336         return m_onlyContainsStructures;
     336    inline MarkedBlock::DestructorType MarkedBlock::destructorType()
     337    {
     338        return m_destructorType;
    337339    }
    338340
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp

    r128851 r130303  
    8282{
    8383    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    84         allocatorFor(cellSize).init(heap, this, cellSize, false, false);
    85         destructorAllocatorFor(cellSize).init(heap, this, cellSize, true, false);
    86     }
    87 
    88     for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    89         allocatorFor(cellSize).init(heap, this, cellSize, false, false);
    90         destructorAllocatorFor(cellSize).init(heap, this, cellSize, true, false);
    91     }
    92 
    93     m_largeAllocator.init(heap, this, 0, true, false);
    94     m_structureAllocator.init(heap, this, WTF::roundUpToMultipleOf(32, sizeof(Structure)), true, true);
     84        allocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::None);
     85        normalDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::Normal);
     86        immortalStructureDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::ImmortalStructure);
     87    }
     88
     89    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
     90        allocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::None);
     91        normalDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::Normal);
     92        immortalStructureDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::ImmortalStructure);
     93    }
     94
     95    m_normalSpace.largeAllocator.init(heap, this, 0, MarkedBlock::None);
     96    m_normalDestructorSpace.largeAllocator.init(heap, this, 0, MarkedBlock::Normal);
     97    m_immortalStructureDestructorSpace.largeAllocator.init(heap, this, 0, MarkedBlock::ImmortalStructure);
    9598}
    9699
     
    121124    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    122125        allocatorFor(cellSize).reset();
    123         destructorAllocatorFor(cellSize).reset();
     126        normalDestructorAllocatorFor(cellSize).reset();
     127        immortalStructureDestructorAllocatorFor(cellSize).reset();
    124128    }
    125129
    126130    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    127131        allocatorFor(cellSize).reset();
    128         destructorAllocatorFor(cellSize).reset();
    129     }
    130 
    131     m_largeAllocator.reset();
    132     m_structureAllocator.reset();
     132        normalDestructorAllocatorFor(cellSize).reset();
     133        immortalStructureDestructorAllocatorFor(cellSize).reset();
     134    }
     135
     136    m_normalSpace.largeAllocator.reset();
     137    m_normalDestructorSpace.largeAllocator.reset();
     138    m_immortalStructureDestructorSpace.largeAllocator.reset();
    133139}
    134140
     
    148154    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    149155        allocatorFor(cellSize).canonicalizeCellLivenessData();
    150         destructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
     156        normalDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
     157        immortalStructureDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
    151158    }
    152159
    153160    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    154161        allocatorFor(cellSize).canonicalizeCellLivenessData();
    155         destructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
    156     }
    157 
    158     m_largeAllocator.canonicalizeCellLivenessData();
    159     m_structureAllocator.canonicalizeCellLivenessData();
     162        normalDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
     163        immortalStructureDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
     164    }
     165
     166    m_normalSpace.largeAllocator.canonicalizeCellLivenessData();
     167    m_normalDestructorSpace.largeAllocator.canonicalizeCellLivenessData();
     168    m_immortalStructureDestructorSpace.largeAllocator.canonicalizeCellLivenessData();
    160169}
    161170
     
    163172{
    164173    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    165         if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
     174        if (allocatorFor(cellSize).isPagedOut(deadline)
     175            || normalDestructorAllocatorFor(cellSize).isPagedOut(deadline)
     176            || immortalStructureDestructorAllocatorFor(cellSize).isPagedOut(deadline))
    166177            return true;
    167178    }
    168179
    169180    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    170         if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
     181        if (allocatorFor(cellSize).isPagedOut(deadline)
     182            || normalDestructorAllocatorFor(cellSize).isPagedOut(deadline)
     183            || immortalStructureDestructorAllocatorFor(cellSize).isPagedOut(deadline))
    171184            return true;
    172185    }
    173186
    174     if (m_largeAllocator.isPagedOut(deadline))
     187    if (m_normalSpace.largeAllocator.isPagedOut(deadline)
     188        || m_normalDestructorSpace.largeAllocator.isPagedOut(deadline)
     189        || m_immortalStructureDestructorSpace.largeAllocator.isPagedOut(deadline))
    175190        return true;
    176191
    177     if (m_structureAllocator.isPagedOut(deadline))
    178         return true;
    179 
    180192    return false;
    181193}
     
    183195void MarkedSpace::freeBlock(MarkedBlock* block)
    184196{
    185     allocatorFor(block).removeBlock(block);
     197    block->allocator()->removeBlock(block);
    186198    m_blocks.remove(block);
    187199    if (block->capacity() == MarkedBlock::blockSize) {
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.h

    r129586 r130303  
    7777    MarkedAllocator& firstAllocator();
    7878    MarkedAllocator& allocatorFor(size_t);
    79     MarkedAllocator& allocatorFor(MarkedBlock*);
    80     MarkedAllocator& destructorAllocatorFor(size_t);
    81     void* allocateWithDestructor(size_t);
     79    MarkedAllocator& immortalStructureDestructorAllocatorFor(size_t);
     80    MarkedAllocator& normalDestructorAllocatorFor(size_t);
     81    void* allocateWithNormalDestructor(size_t);
     82    void* allocateWithImmortalStructureDestructor(size_t);
    8283    void* allocateWithoutDestructor(size_t);
    83     void* allocateStructure(size_t);
    8484 
    8585    void resetAllocators();
     
    132132        FixedArray<MarkedAllocator, preciseCount> preciseAllocators;
    133133        FixedArray<MarkedAllocator, impreciseCount> impreciseAllocators;
     134        MarkedAllocator largeAllocator;
    134135    };
    135136
    136     Subspace m_destructorSpace;
     137    Subspace m_normalDestructorSpace;
     138    Subspace m_immortalStructureDestructorSpace;
    137139    Subspace m_normalSpace;
    138     MarkedAllocator m_largeAllocator;
    139     MarkedAllocator m_structureAllocator;
    140140
    141141    Heap* m_heap;
     
    187187    if (bytes <= impreciseCutoff)
    188188        return m_normalSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
    189     return m_largeAllocator;
    190 }
    191 
    192 inline MarkedAllocator& MarkedSpace::allocatorFor(MarkedBlock* block)
    193 {
    194     if (block->onlyContainsStructures())
    195         return m_structureAllocator;
    196 
    197     if (block->cellsNeedDestruction())
    198         return destructorAllocatorFor(block->cellSize());
    199 
    200     return allocatorFor(block->cellSize());
    201 }
    202 
    203 inline MarkedAllocator& MarkedSpace::destructorAllocatorFor(size_t bytes)
     189    return m_normalSpace.largeAllocator;
     190}
     191
     192inline MarkedAllocator& MarkedSpace::immortalStructureDestructorAllocatorFor(size_t bytes)
    204193{
    205194    ASSERT(bytes);
    206195    if (bytes <= preciseCutoff)
    207         return m_destructorSpace.preciseAllocators[(bytes - 1) / preciseStep];
     196        return m_immortalStructureDestructorSpace.preciseAllocators[(bytes - 1) / preciseStep];
    208197    if (bytes <= impreciseCutoff)
    209         return m_normalSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
    210     return m_largeAllocator;
     198        return m_immortalStructureDestructorSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
     199    return m_immortalStructureDestructorSpace.largeAllocator;
     200}
     201
     202inline MarkedAllocator& MarkedSpace::normalDestructorAllocatorFor(size_t bytes)
     203{
     204    ASSERT(bytes);
     205    if (bytes <= preciseCutoff)
     206        return m_normalDestructorSpace.preciseAllocators[(bytes - 1) / preciseStep];
     207    if (bytes <= impreciseCutoff)
     208        return m_normalDestructorSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
     209    return m_normalDestructorSpace.largeAllocator;
    211210}
    212211
     
    216215}
    217216
    218 inline void* MarkedSpace::allocateWithDestructor(size_t bytes)
    219 {
    220     return destructorAllocatorFor(bytes).allocate(bytes);
    221 }
    222 
    223 inline void* MarkedSpace::allocateStructure(size_t bytes)
    224 {
    225     return m_structureAllocator.allocate(bytes);
     217inline void* MarkedSpace::allocateWithImmortalStructureDestructor(size_t bytes)
     218{
     219    return immortalStructureDestructorAllocatorFor(bytes).allocate(bytes);
     220}
     221
     222inline void* MarkedSpace::allocateWithNormalDestructor(size_t bytes)
     223{
     224    return normalDestructorAllocatorFor(bytes).allocate(bytes);
    226225}
    227226
     
    230229    for (size_t i = 0; i < preciseCount; ++i) {
    231230        m_normalSpace.preciseAllocators[i].forEachBlock(functor);
    232         m_destructorSpace.preciseAllocators[i].forEachBlock(functor);
     231        m_normalDestructorSpace.preciseAllocators[i].forEachBlock(functor);
     232        m_immortalStructureDestructorSpace.preciseAllocators[i].forEachBlock(functor);
    233233    }
    234234
    235235    for (size_t i = 0; i < impreciseCount; ++i) {
    236236        m_normalSpace.impreciseAllocators[i].forEachBlock(functor);
    237         m_destructorSpace.impreciseAllocators[i].forEachBlock(functor);
     237        m_normalDestructorSpace.impreciseAllocators[i].forEachBlock(functor);
     238        m_immortalStructureDestructorSpace.impreciseAllocators[i].forEachBlock(functor);
    238239    }
    239240
    240     m_largeAllocator.forEachBlock(functor);
    241     m_structureAllocator.forEachBlock(functor);
     241    m_normalSpace.largeAllocator.forEachBlock(functor);
     242    m_normalDestructorSpace.largeAllocator.forEachBlock(functor);
     243    m_immortalStructureDestructorSpace.largeAllocator.forEachBlock(functor);
    242244
    243245    return functor.returnValue();
  • trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp

    r128851 r130303  
    66#include "CopiedSpaceInlineMethods.h"
    77#include "JSArray.h"
     8#include "JSDestructibleObject.h"
    89#include "JSGlobalData.h"
    910#include "JSObject.h"
Note: See TracChangeset for help on using the changeset viewer.