Changeset 79627 in webkit


Ignore:
Timestamp:
Feb 24, 2011 2:58:48 PM (13 years ago)
Author:
ggaren@apple.com
Message:

2011-02-24 Geoffrey Garen <ggaren@apple.com>

Reviewed by Darin Adler.

Variable-sized allocation (but still capped at 64 bytes)
https://bugs.webkit.org/show_bug.cgi?id=55159


SunSpider reports no change.

  • runtime/Heap.cpp: (JSC::Heap::allocateSlowCase): Split allocation into a fast and slow case, so the fast case can inline size class selection and turn it into a compile-time constant.


Changed the collect-on-every allocation debugging switch to collect only
on every slow allocation, so you can still flip the switch without
recompiling the world. This may also be preferable for debugging purposes,
since collecting after every single allocation can be unusably slow,
and can mask problems by running destructors early.

  • runtime/Heap.h: Ditto.
  • runtime/JSCell.h: (JSC::JSCell::MarkedSpace::sizeClassFor): (JSC::JSCell::Heap::allocate): (JSC::JSCell::JSCell::operator new): The inlining mentioned above.
  • runtime/MarkedBlock.h: Dropped the block size from 256KB to 16KB. With multiple size classes, allocating a full 256KB for the first allocation in a given class can be pathologically wasteful. (8KB, or 4KB Mac and 8KB Windows, would be even better, but that seems to be a peformance regression for now.)


  • runtime/MarkedSpace.cpp: (JSC::MarkedSpace::MarkedSpace): (JSC::MarkedSpace::allocateBlock): (JSC::MarkedSpace::reset): There's more than one size class now, and its cell size is not constant.
  • runtime/MarkedSpace.h: (JSC::MarkedSpace::SizeClass::SizeClass): Ditto.
Location:
trunk/Source/JavaScriptCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r79616 r79627  
     12011-02-24  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        Variable-sized allocation (but still capped at 64 bytes)
     6        https://bugs.webkit.org/show_bug.cgi?id=55159
     7       
     8        SunSpider reports no change.
     9
     10        * JavaScriptCore.exp: Some day, I hope not to have to edit this file.
     11
     12        * runtime/Heap.cpp:
     13        (JSC::Heap::allocateSlowCase): Split allocation into a fast and slow
     14        case, so the fast case can inline size class selection and turn it into
     15        a compile-time constant.
     16       
     17        Changed the collect-on-every allocation debugging switch to collect only
     18        on every slow allocation, so you can still flip the switch without
     19        recompiling the world. This may also be preferable for debugging purposes,
     20        since collecting after every single allocation can be unusably slow,
     21        and can mask problems by running destructors early.
     22
     23        * runtime/Heap.h: Ditto.
     24
     25        * runtime/JSCell.h:
     26        (JSC::JSCell::MarkedSpace::sizeClassFor):
     27        (JSC::JSCell::Heap::allocate):
     28        (JSC::JSCell::JSCell::operator new): The inlining mentioned above.
     29
     30        * runtime/MarkedBlock.h: Dropped the block size from 256KB to 16KB. With
     31        multiple size classes, allocating a full 256KB for the first allocation
     32        in a given class can be pathologically wasteful. (8KB, or 4KB Mac and
     33        8KB Windows, would be even better, but that seems to be a peformance
     34        regression for now.)
     35       
     36        * runtime/MarkedSpace.cpp:
     37        (JSC::MarkedSpace::MarkedSpace):
     38        (JSC::MarkedSpace::allocateBlock):
     39        (JSC::MarkedSpace::reset): There's more than one size class now, and its
     40        cell size is not constant.
     41
     42        * runtime/MarkedSpace.h:
     43        (JSC::MarkedSpace::SizeClass::SizeClass): Ditto.
     44
    1452011-02-23  Oliver Hunt  <oliver@apple.com>
    246
  • trunk/Source/JavaScriptCore/JavaScriptCore.exp

    r79483 r79627  
    116116__ZN3JSC11JSByteArray15createStructureENS_7JSValueEPKNS_9ClassInfoE
    117117__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayE
     118__ZN3JSC11MarkedSpace21allocateFromSizeClassERNS0_9SizeClassE
    118119__ZN3JSC11ParserArena5resetEv
    119120__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
     
    209210__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
    210211__ZN3JSC3NaNE
     212__ZN3JSC4Heap16allocateSlowCaseEm
    211213__ZN3JSC4Heap16objectTypeCountsEv
    212214__ZN3JSC4Heap17collectAllGarbageEv
     
    220222__ZN3JSC4Heap7destroyEv
    221223__ZN3JSC4Heap7protectENS_7JSValueE
    222 __ZN3JSC4Heap8allocateEm
    223224__ZN3JSC4Heap9unprotectENS_7JSValueE
    224225__ZN3JSC4Yarr11YarrPatternC1ERKNS_7UStringEbbPPKc
     
    240241__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
    241242__ZN3JSC6JSLock12DropAllLocksD1Ev
     243__ZN3JSC6JSLock26currentThreadIsHoldingLockEv
    242244__ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
    243245__ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def

    r79431 r79627  
    5353    ?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVExecState@2@PAVStringImpl@4@@Z
    5454    ?allocate@Heap@JSC@@QAEPAXI@Z
     55    ?allocateFromSizeClass@MarkedSpace@JSC@@AAEPAXAAUSizeClass@12@@Z
    5556    ?allocatePropertyStorage@JSObject@JSC@@QAEXII@Z
     57    ?allocateSlowCase@Heap@JSC@@AAEPAXI@Z
    5658    ?allocateStack@MarkStack@JSC@@CAPAXI@Z
    5759    ?append@StringBuilder@WTF@@QAEXPBDI@Z
     
    112114    ?cryptographicallyRandomValues@WTF@@YAXPAXI@Z
    113115    ?currentThread@WTF@@YAIXZ
     116    ?currentThreadIsHoldingLock@JSLock@JSC@@SA_NXZ
    114117    ?currentTime@WTF@@YANXZ
    115118    ?data@CString@WTF@@QBEPBDXZ
     
    226229    ?lock@Mutex@WTF@@QAEXXZ
    227230    ?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
     231    ?lockCount@JSLock@JSC@@SAHXZ
    228232    ?lookupGetter@JSObject@JSC@@UAE?AVJSValue@2@PAVExecState@2@ABVIdentifier@2@@Z
    229233    ?lookupSetter@JSObject@JSC@@UAE?AVJSValue@2@PAVExecState@2@ABVIdentifier@2@@Z
  • trunk/Source/JavaScriptCore/runtime/Heap.cpp

    r79616 r79627  
    3333#include <algorithm>
    3434
    35 #define COLLECT_ON_EVERY_ALLOCATION 0
     35#define COLLECT_ON_EVERY_SLOW_ALLOCATION 0
    3636
    3737using namespace std;
     
    103103}
    104104
    105 void* Heap::allocate(size_t s)
     105void* Heap::allocateSlowCase(size_t bytes)
    106106{
    107107    ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
    108108    ASSERT(JSLock::lockCount() > 0);
    109109    ASSERT(JSLock::currentThreadIsHoldingLock());
    110     ASSERT_UNUSED(s, s <= MarkedSpace::cellSize);
     110    ASSERT(bytes <= MarkedSpace::maxCellSize);
    111111    ASSERT(m_operationInProgress == NoOperation);
    112112
    113 #if COLLECT_ON_EVERY_ALLOCATION
     113#if COLLECT_ON_EVERY_SLOW_ALLOCATION
    114114    collectAllGarbage();
    115115    ASSERT(m_operationInProgress == NoOperation);
    116116#endif
    117117
     118    reset(DoNotSweep);
     119
    118120    m_operationInProgress = Allocation;
    119     void* result = m_markedSpace.allocate(s);
     121    void* result = m_markedSpace.allocate(bytes);
    120122    m_operationInProgress = NoOperation;
    121     if (!result) {
    122         reset(DoNotSweep);
    123 
    124         m_operationInProgress = Allocation;
    125         result = m_markedSpace.allocate(s);
    126         m_operationInProgress = NoOperation;
    127     }
    128123
    129124    ASSERT(result);
  • trunk/Source/JavaScriptCore/runtime/Heap.h

    r79017 r79627  
    108108        static const size_t maxExtraCost = 1024 * 1024;
    109109
     110        void* allocateSlowCase(size_t);
    110111        void reportExtraMemoryCostSlowCase(size_t);
    111112
  • trunk/Source/JavaScriptCore/runtime/JSCell.h

    r79512 r79627  
    2828#include "Heap.h"
    2929#include "JSImmediate.h"
     30#include "JSLock.h"
    3031#include "JSValue.h"
    3132#include "MarkStack.h"
     
    175176    }
    176177
    177     inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
    178     {
    179         return globalData->heap.allocate(size);
    180     }
    181 
    182     inline void* JSCell::operator new(size_t size, ExecState* exec)
    183     {
    184         return exec->heap()->allocate(size);
    185     }
    186 
    187178    // --- JSValue inlines ----------------------------
    188179
     
    418409    }
    419410   
    420     inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t)
    421     {
    422         return m_sizeClass;
     411    inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes)
     412    {
     413        ASSERT(bytes && bytes <= preciseCutoff);
     414        return m_preciseSizeClasses[(bytes - 1) / preciseStep];
    423415    }
    424416
     
    428420        return allocateFromSizeClass(sizeClass);
    429421    }
     422   
     423    inline void* Heap::allocate(size_t bytes)
     424    {
     425        ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
     426        ASSERT(JSLock::lockCount() > 0);
     427        ASSERT(JSLock::currentThreadIsHoldingLock());
     428        ASSERT(bytes <= MarkedSpace::maxCellSize);
     429        ASSERT(m_operationInProgress == NoOperation);
     430
     431        m_operationInProgress = Allocation;
     432        void* result = m_markedSpace.allocate(bytes);
     433        m_operationInProgress = NoOperation;
     434        if (result)
     435            return result;
     436
     437        return allocateSlowCase(bytes);
     438    }
     439
     440    inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
     441    {
     442        return globalData->heap.allocate(size);
     443    }
     444
     445    inline void* JSCell::operator new(size_t size, ExecState* exec)
     446    {
     447        return exec->heap()->allocate(size);
     448    }
    430449
    431450} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/MarkedBlock.h

    r79512 r79627  
    4747    class MarkedBlock {
    4848    public:
     49        static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types.
     50
    4951        static MarkedBlock* create(JSGlobalData*, size_t cellSize);
    5052        static void destroy(MarkedBlock*);
     
    8486
    8587    private:
    86 #if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP)
    87         static const size_t blockSize = 64 * KB;
    88 #else
    89         static const size_t blockSize = 256 * KB;
    90 #endif
     88        static const size_t blockSize = 16 * KB;
    9189        static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two.
    9290
    93         static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types.
    9491        static const size_t atomMask = ~(atomSize - 1); // atomSize must be a power of two.
    9592       
  • trunk/Source/JavaScriptCore/runtime/MarkedSpace.cpp

    r79512 r79627  
    3535    , m_globalData(globalData)
    3636{
     37    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep)
     38        sizeClassFor(cellSize).cellSize = cellSize;
    3739}
    3840
     
    4648MarkedBlock* MarkedSpace::allocateBlock(SizeClass& sizeClass)
    4749{
    48     MarkedBlock* block = MarkedBlock::create(globalData(), cellSize);
     50    MarkedBlock* block = MarkedBlock::create(globalData(), sizeClass.cellSize);
    4951    sizeClass.blockList.append(block);
    5052    sizeClass.nextBlock = block;
     
    144146void MarkedSpace::reset()
    145147{
    146     m_sizeClass.reset();
    147148    m_waterMark = 0;
     149
     150    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep)
     151        sizeClassFor(cellSize).reset();
    148152
    149153    BlockIterator end = m_blocks.end();
  • trunk/Source/JavaScriptCore/runtime/MarkedSpace.h

    r79512 r79627  
    3333#include <wtf/Vector.h>
    3434
    35 #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedSpace::cellSize, class_fits_in_cell)
    36 #define ASSERT_CLASS_FILLS_CELL(class) COMPILE_ASSERT(sizeof(class) == MarkedSpace::cellSize, class_fills_cell)
     35#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedSpace::maxCellSize, class_fits_in_cell)
     36#define ASSERT_CLASS_FILLS_CELL(class) COMPILE_ASSERT(sizeof(class) == MarkedSpace::maxCellSize, class_fills_cell)
    3737
    3838namespace JSC {
     
    4949    public:
    5050        // Currently public for use in assertions.
    51         static const size_t cellSize = 64;
     51        static const size_t maxCellSize = 64;
    5252
    5353        static Heap* heap(JSCell*);
     
    8282
    8383    private:
     84        // [ 8, 16... 64 ]
     85        static const size_t preciseStep = MarkedBlock::atomSize;
     86        static const size_t preciseCutoff = maxCellSize;
     87        static const size_t preciseCount = preciseCutoff / preciseStep;
     88
    8489        typedef HashSet<MarkedBlock*>::iterator BlockIterator;
    8590
     
    9095            MarkedBlock* nextBlock;
    9196            DoublyLinkedList<MarkedBlock> blockList;
     97            size_t cellSize;
    9298        };
    9399
     
    100106        void clearMarks(MarkedBlock*);
    101107
    102         SizeClass m_sizeClass;
     108        SizeClass m_preciseSizeClasses[preciseCount];
    103109        HashSet<MarkedBlock*> m_blocks;
    104110        size_t m_waterMark;
     
    148154    inline MarkedSpace::SizeClass::SizeClass()
    149155        : nextBlock(0)
     156        , cellSize(0)
    150157    {
    151158    }
Note: See TracChangeset for help on using the changeset viewer.