Changeset 144708 in webkit


Ignore:
Timestamp:
Mar 4, 2013 7:05:27 PM (11 years ago)
Author:
akling@apple.com
Message:

Unused Structure property tables waste 14MB on Membuster.
<http://webkit.org/b/110854>
<rdar://problem/13292104>

Reviewed by Geoffrey Garen.

Turn PropertyTable into a GC object and have Structure drop unpinned tables when marking.
14 MB progression on Membuster3.

Added PropertyTable.cpp.

  • runtime/PropertyTable.cpp: Added.

(JSC::PropertyTable::create):
(JSC::PropertyTable::clone):
(JSC::PropertyTable::PropertyTable):
(JSC::PropertyTable::destroy):
(JSC::PropertyTable::~PropertyTable):
(JSC::PropertyTable::visitChildren):

Moved marking of property table values here from Structure::visitChildren().

  • runtime/WriteBarrier.h:

(JSC::WriteBarrierBase::get):

Move m_cell to a local before using it multiple times. This avoids a multiple-access race when
Structure::checkOffsetConsistency() is used in assertions on the main thread while a marking thread
zaps the property table.

  • runtime/Structure.h:

(JSC::Structure::materializePropertyMapIfNecessary):
(JSC::Structure::materializePropertyMapIfNecessaryForPinning):

  • runtime/StructureInlines.h:

(JSC::Structure::propertyTable):

Added a getter for the Structure's PropertyTable that ASSERTs GC currently isn't active.
Because GC can zap an unpinned property table at any time, it's not entirely safe to access it.
Renamed the variable itself to m_propertyTableUnsafe to force call sites into explaining themselves.

(JSC::Structure::putWillGrowOutOfLineStorage):
(JSC::Structure::checkOffsetConsistency):

Moved these out of Structure.h to break header dependency cycle between Structure/PropertyTable.

  • runtime/Structure.cpp:

(JSC::Structure::visitChildren):

Null out m_propertyTable if the table is unpinned. This'll cause the table to get GC'd.

  • runtime/JSGlobalData.h:
  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):

Add a global propertyTableStructure.

  • runtime/PropertyMapHashTable.h:

(PropertyTable):
(JSC::PropertyTable::createStructure):
(JSC::PropertyTable::copy):

Make PropertyTable a GC object.

  • runtime/Structure.cpp:

(JSC::Structure::dumpStatistics):
(JSC::Structure::materializePropertyMap):
(JSC::Structure::despecifyDictionaryFunction):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::changePrototypeTransition):
(JSC::Structure::despecifyFunctionTransition):
(JSC::Structure::attributeChangeTransition):
(JSC::Structure::toDictionaryTransition):
(JSC::Structure::sealTransition):
(JSC::Structure::freezeTransition):
(JSC::Structure::preventExtensionsTransition):
(JSC::Structure::nonPropertyTransition):
(JSC::Structure::isSealed):
(JSC::Structure::isFrozen):
(JSC::Structure::flattenDictionaryStructure):
(JSC::Structure::pin):
(JSC::Structure::copyPropertyTable):
(JSC::Structure::copyPropertyTableForPinning):
(JSC::Structure::get):
(JSC::Structure::despecifyFunction):
(JSC::Structure::despecifyAllFunctions):
(JSC::Structure::putSpecificValue):
(JSC::Structure::remove):
(JSC::Structure::createPropertyMap):
(JSC::Structure::getPropertyNamesFromStructure):
(JSC::Structure::checkConsistency):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r144113 r144708  
    281281    runtime/PropertyNameArray.cpp
    282282    runtime/PropertySlot.cpp
     283    runtime/PropertyTable.cpp
    283284    runtime/PrototypeMap.cpp
    284285    runtime/RegExp.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r144698 r144708  
     12013-03-04  Andreas Kling  <akling@apple.com>
     2
     3        Unused Structure property tables waste 14MB on Membuster.
     4        <http://webkit.org/b/110854>
     5        <rdar://problem/13292104>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        Turn PropertyTable into a GC object and have Structure drop unpinned tables when marking.
     10        14 MB progression on Membuster3.
     11
     12        * CMakeLists.txt:
     13        * GNUmakefile.list.am:
     14        * JavaScriptCore.gypi:
     15        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     16        * JavaScriptCore.xcodeproj/project.pbxproj:
     17        * Target.pri:
     18
     19            Added PropertyTable.cpp.
     20
     21        * runtime/PropertyTable.cpp: Added.
     22        (JSC::PropertyTable::create):
     23        (JSC::PropertyTable::clone):
     24        (JSC::PropertyTable::PropertyTable):
     25        (JSC::PropertyTable::destroy):
     26        (JSC::PropertyTable::~PropertyTable):
     27        (JSC::PropertyTable::visitChildren):
     28
     29            Moved marking of property table values here from Structure::visitChildren().
     30
     31        * runtime/WriteBarrier.h:
     32        (JSC::WriteBarrierBase::get):
     33
     34            Move m_cell to a local before using it multiple times. This avoids a multiple-access race when
     35            Structure::checkOffsetConsistency() is used in assertions on the main thread while a marking thread
     36            zaps the property table.
     37
     38        * runtime/Structure.h:
     39        (JSC::Structure::materializePropertyMapIfNecessary):
     40        (JSC::Structure::materializePropertyMapIfNecessaryForPinning):
     41        * runtime/StructureInlines.h:
     42        (JSC::Structure::propertyTable):
     43
     44            Added a getter for the Structure's PropertyTable that ASSERTs GC currently isn't active.
     45            Because GC can zap an unpinned property table at any time, it's not entirely safe to access it.
     46            Renamed the variable itself to m_propertyTableUnsafe to force call sites into explaining themselves.
     47
     48        (JSC::Structure::putWillGrowOutOfLineStorage):
     49        (JSC::Structure::checkOffsetConsistency):
     50
     51            Moved these out of Structure.h to break header dependency cycle between Structure/PropertyTable.
     52
     53        * runtime/Structure.cpp:
     54        (JSC::Structure::visitChildren):
     55
     56            Null out m_propertyTable if the table is unpinned. This'll cause the table to get GC'd.
     57
     58        * runtime/JSGlobalData.h:
     59        * runtime/JSGlobalData.cpp:
     60        (JSC::JSGlobalData::JSGlobalData):
     61
     62            Add a global propertyTableStructure.
     63
     64        * runtime/PropertyMapHashTable.h:
     65        (PropertyTable):
     66        (JSC::PropertyTable::createStructure):
     67        (JSC::PropertyTable::copy):
     68
     69            Make PropertyTable a GC object.
     70
     71        * runtime/Structure.cpp:
     72        (JSC::Structure::dumpStatistics):
     73        (JSC::Structure::materializePropertyMap):
     74        (JSC::Structure::despecifyDictionaryFunction):
     75        (JSC::Structure::addPropertyTransition):
     76        (JSC::Structure::changePrototypeTransition):
     77        (JSC::Structure::despecifyFunctionTransition):
     78        (JSC::Structure::attributeChangeTransition):
     79        (JSC::Structure::toDictionaryTransition):
     80        (JSC::Structure::sealTransition):
     81        (JSC::Structure::freezeTransition):
     82        (JSC::Structure::preventExtensionsTransition):
     83        (JSC::Structure::nonPropertyTransition):
     84        (JSC::Structure::isSealed):
     85        (JSC::Structure::isFrozen):
     86        (JSC::Structure::flattenDictionaryStructure):
     87        (JSC::Structure::pin):
     88        (JSC::Structure::copyPropertyTable):
     89        (JSC::Structure::copyPropertyTableForPinning):
     90        (JSC::Structure::get):
     91        (JSC::Structure::despecifyFunction):
     92        (JSC::Structure::despecifyAllFunctions):
     93        (JSC::Structure::putSpecificValue):
     94        (JSC::Structure::remove):
     95        (JSC::Structure::createPropertyMap):
     96        (JSC::Structure::getPropertyNamesFromStructure):
     97        (JSC::Structure::checkConsistency):
     98
    1992013-03-04  Chris Fleizach  <cfleizach@apple.com>
    2100
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r144113 r144708  
    723723        Source/JavaScriptCore/runtime/PropertySlot.cpp \
    724724        Source/JavaScriptCore/runtime/PropertySlot.h \
     725        Source/JavaScriptCore/runtime/PropertyTable.cpp \
    725726        Source/JavaScriptCore/runtime/PrototypeMap.cpp \
    726727        Source/JavaScriptCore/runtime/PrototypeMap.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.gypi

    r144489 r144708  
    759759            'runtime/PropertySlot.cpp',
    760760            'runtime/PropertySlot.h',
     761            'runtime/PropertyTable.cpp',
    761762            'runtime/PropertyStorage.h',
    762763            'runtime/Protect.h',
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r144113 r144708  
    306306    <ClCompile Include="..\runtime\PropertyNameArray.cpp" />
    307307    <ClCompile Include="..\runtime\PropertySlot.cpp" />
     308    <ClCompile Include="..\runtime\PropertyTable.cpp" />
    308309    <ClCompile Include="..\runtime\PrototypeMap.cpp" />
    309310    <ClCompile Include="..\runtime\RegExp.cpp" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r144521 r144708  
    704704                A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; };
    705705                A8A4748E151A8306004123FF /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A4748D151A8306004123FF /* libWTF.a */; };
     706                ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */; };
    706707                BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; };
    707708                BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9070E1839DB000F9297 /* ErrorPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    16191620                A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; };
    16201621                A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; };
     1622                AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyTable.cpp; sourceTree = "<group>"; };
    16211623                BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ToolExecutable.xcconfig; sourceTree = "<group>"; };
    16221624                BC02E9040E1839DB000F9297 /* ErrorConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorConstructor.cpp; sourceTree = "<group>"; };
     
    25072509                                65621E6C089E859700760F35 /* PropertySlot.h */,
    25082510                                0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */,
     2511                                AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */,
    25092512                                65C02FBB0637462A003E7EE6 /* Protect.h */,
    25102513                                14D844A216AA2C7000A65AF0 /* PrototypeMap.cpp */,
     
    40244027                                0FBE0F7616C1DB0F0082C5E8 /* DFGUnificationPhase.cpp in Sources */,
    40254028                                0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */,
     4029                                ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */,
    40264030                        );
    40274031                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/JavaScriptCore/Target.pri

    r144113 r144708  
    299299    runtime/PropertyNameArray.cpp \
    300300    runtime/PropertySlot.cpp \
     301    runtime/PropertyTable.cpp \
    301302    runtime/PrototypeMap.cpp \
    302303    runtime/RegExpConstructor.cpp \
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.cpp

    r144113 r144708  
    233233    unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
    234234    unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
     235    propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
    235236    smallStrings.initializeCommonStrings(*this);
    236237
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.h

    r144113 r144708  
    257257        Strong<Structure> unlinkedEvalCodeBlockStructure;
    258258        Strong<Structure> unlinkedFunctionCodeBlockStructure;
     259        Strong<Structure> propertyTableStructure;
    259260
    260261        IdentifierTable* identifierTable;
  • trunk/Source/JavaScriptCore/runtime/PropertyMapHashTable.h

    r144113 r144708  
    2323
    2424#include "PropertyOffset.h"
     25#include "Structure.h"
    2526#include "WriteBarrier.h"
    2627#include <wtf/HashTable.h>
     
    8687};
    8788
    88 class PropertyTable {
    89     WTF_MAKE_FAST_ALLOCATED;
     89class PropertyTable : public JSCell {
    9090
    9191    // This is the implementation for 'iterator' and 'const_iterator',
     
    130130
    131131public:
     132    static const bool needsDestruction = true;
     133    static const bool hasImmortalStructure = true;
     134    static void destroy(JSCell*);
     135
     136    static JS_EXPORTDATA const ClassInfo s_info;
     137
     138    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
     139    {
     140        return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info);
     141    }
     142
     143    static void visitChildren(JSCell*, SlotVisitor&);
     144
    132145    typedef StringImpl* KeyType;
    133146    typedef PropertyMapEntry ValueType;
     
    143156
    144157    // Constructor is passed an initial capacity, a PropertyTable to copy, or both.
    145     explicit PropertyTable(unsigned initialCapacity);
    146     PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&);
    147     PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&);
     158    static PropertyTable* create(JSGlobalData&, unsigned initialCapacity);
     159    static PropertyTable* clone(JSGlobalData&, JSCell* owner, const PropertyTable&);
     160    static PropertyTable* clone(JSGlobalData&, JSCell* owner, unsigned initialCapacity, const PropertyTable&);
    148161    ~PropertyTable();
    149162
     
    182195
    183196    // Copy this PropertyTable, ensuring the copy has at least the capacity provided.
    184     PassOwnPtr<PropertyTable> copy(JSGlobalData&, JSCell* owner, unsigned newCapacity);
     197    PropertyTable* copy(JSGlobalData&, JSCell* owner, unsigned newCapacity);
    185198
    186199#ifndef NDEBUG
     
    190203
    191204private:
     205    PropertyTable(JSGlobalData&, unsigned initialCapacity);
     206    PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&);
     207    PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&);
     208
    192209    PropertyTable(const PropertyTable&);
    193210    // Used to insert a value known not to be in the table, and where we know capacity to be available.
     
    240257};
    241258
    242 inline PropertyTable::PropertyTable(unsigned initialCapacity)
    243     : m_indexSize(sizeForCapacity(initialCapacity))
    244     , m_indexMask(m_indexSize - 1)
    245     , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
    246     , m_keyCount(0)
    247     , m_deletedCount(0)
    248 {
    249     ASSERT(isPowerOf2(m_indexSize));
    250 }
    251 
    252 inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, const PropertyTable& other)
    253     : m_indexSize(other.m_indexSize)
    254     , m_indexMask(other.m_indexMask)
    255     , m_index(static_cast<unsigned*>(fastMalloc(dataSize())))
    256     , m_keyCount(other.m_keyCount)
    257     , m_deletedCount(other.m_deletedCount)
    258 {
    259     ASSERT(isPowerOf2(m_indexSize));
    260 
    261     memcpy(m_index, other.m_index, dataSize());
    262 
    263     iterator end = this->end();
    264     for (iterator iter = begin(); iter != end; ++iter) {
    265         iter->key->ref();
    266         Heap::writeBarrier(owner, iter->specificValue.get());
    267     }
    268 
    269     // Copy the m_deletedOffsets vector.
    270     Vector<PropertyOffset>* otherDeletedOffsets = other.m_deletedOffsets.get();
    271     if (otherDeletedOffsets)
    272         m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>(*otherDeletedOffsets));
    273 }
    274 
    275 inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, unsigned initialCapacity, const PropertyTable& other)
    276     : m_indexSize(sizeForCapacity(initialCapacity))
    277     , m_indexMask(m_indexSize - 1)
    278     , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
    279     , m_keyCount(0)
    280     , m_deletedCount(0)
    281 {
    282     ASSERT(isPowerOf2(m_indexSize));
    283     ASSERT(initialCapacity >= other.m_keyCount);
    284 
    285     const_iterator end = other.end();
    286     for (const_iterator iter = other.begin(); iter != end; ++iter) {
    287         ASSERT(canInsert());
    288         reinsert(*iter);
    289         iter->key->ref();
    290         Heap::writeBarrier(owner, iter->specificValue.get());
    291     }
    292 
    293     // Copy the m_deletedOffsets vector.
    294     Vector<PropertyOffset>* otherDeletedOffsets = other.m_deletedOffsets.get();
    295     if (otherDeletedOffsets)
    296         m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>(*otherDeletedOffsets));
    297 }
    298 
    299 inline PropertyTable::~PropertyTable()
    300 {
    301     iterator end = this->end();
    302     for (iterator iter = begin(); iter != end; ++iter)
    303         iter->key->deref();
    304 
    305     fastFree(m_index);
    306 }
    307 
    308259inline PropertyTable::iterator PropertyTable::begin()
    309260{
     
    503454}
    504455
    505 inline PassOwnPtr<PropertyTable> PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity)
     456inline PropertyTable* PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity)
    506457{
    507458    ASSERT(newCapacity >= m_keyCount);
     
    510461    // save rehashing all keys.
    511462    if (sizeForCapacity(newCapacity) == m_indexSize)
    512         return adoptPtr(new PropertyTable(globalData, owner, *this));
    513     return adoptPtr(new PropertyTable(globalData, owner, newCapacity, *this));
     463        return PropertyTable::clone(globalData, owner, *this);
     464    return PropertyTable::clone(globalData, owner, newCapacity, *this);
    514465}
    515466
  • trunk/Source/JavaScriptCore/runtime/Structure.cpp

    r144113 r144708  
    132132        }
    133133
    134         if (structure->m_propertyTable) {
     134        if (structure->propertyTable()) {
    135135            ++numberWithPropertyMaps;
    136             totalPropertyMapsSize += structure->m_propertyTable->sizeInMemory();
     136            totalPropertyMapsSize += structure->propertyTable()->sizeInMemory();
    137137        }
    138138    }
     
    235235{
    236236    ASSERT(structure()->classInfo() == &s_info);
    237     ASSERT(!m_propertyTable);
     237    ASSERT(!propertyTable());
    238238
    239239    Vector<Structure*, 8> structures;
     
    245245    while ((structure = structure->previousID())) {
    246246        if (structure->m_isPinnedPropertyTable) {
    247             ASSERT(structure->m_propertyTable);
     247            ASSERT(structure->propertyTable());
    248248            ASSERT(!structure->previousID());
    249249
    250             m_propertyTable = structure->m_propertyTable->copy(globalData, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
     250            propertyTable().set(globalData, this, structure->propertyTable()->copy(globalData, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity)));
    251251            break;
    252252        }
     
    255255    }
    256256
    257     if (!m_propertyTable)
    258         createPropertyMap(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
     257    if (!propertyTable())
     258        createPropertyMap(globalData, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
    259259
    260260    for (ptrdiff_t i = structures.size() - 1; i >= 0; --i) {
     
    263263            continue;
    264264        PropertyMapEntry entry(globalData, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get());
    265         m_propertyTable->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
     265        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
    266266    }
    267267   
     
    288288
    289289    ASSERT(isDictionary());
    290     ASSERT(m_propertyTable);
    291 
    292     PropertyMapEntry* entry = m_propertyTable->find(rep).first;
     290    ASSERT(propertyTable());
     291
     292    PropertyMapEntry* entry = propertyTable()->find(rep).first;
    293293    ASSERT(entry);
    294294    entry->specificValue.clear();
     
    374374    transition->m_specificValueInPrevious.setMayBeNull(globalData, transition, specificValue);
    375375
    376     if (structure->m_propertyTable) {
     376    if (structure->propertyTable()) {
    377377        structure->checkOffsetConsistency();
    378378        if (structure->m_isPinnedPropertyTable)
    379             transition->m_propertyTable = structure->m_propertyTable->copy(globalData, transition, structure->m_propertyTable->size() + 1);
    380         else
    381             transition->m_propertyTable = structure->m_propertyTable.release();
     379            transition->propertyTable().set(globalData, transition, structure->propertyTable()->copy(globalData, transition, structure->propertyTable()->size() + 1));
     380        else {
     381            transition->propertyTable().set(globalData, transition, structure->propertyTable().get());
     382            structure->propertyTable().clear();
     383        }
    382384    } else {
    383385        if (structure->previousID())
    384386            transition->materializePropertyMap(globalData);
    385387        else
    386             transition->createPropertyMap();
     388            transition->createPropertyMap(globalData);
    387389    }
    388390    transition->m_offset = structure->m_offset;
     
    416418
    417419    structure->materializePropertyMapIfNecessary(globalData);
    418     transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
     420    transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition));
    419421    transition->m_offset = structure->m_offset;
    420422    transition->pin();
     
    432434
    433435    structure->materializePropertyMapIfNecessary(globalData);
    434     transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
     436    transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition));
    435437    transition->m_offset = structure->m_offset;
    436438    transition->pin();
     
    453455
    454456        structure->materializePropertyMapIfNecessary(globalData);
    455         transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
     457        transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition));
    456458        transition->m_offset = structure->m_offset;
    457459        transition->pin();
     
    460462    }
    461463
    462     ASSERT(structure->m_propertyTable);
    463     PropertyMapEntry* entry = structure->m_propertyTable->find(propertyName.uid()).first;
     464    ASSERT(structure->propertyTable());
     465    PropertyMapEntry* entry = structure->propertyTable()->find(propertyName.uid()).first;
    464466    ASSERT(entry);
    465467    entry->attributes = attributes;
     
    476478
    477479    structure->materializePropertyMapIfNecessary(globalData);
    478     transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
     480    transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition));
    479481    transition->m_offset = structure->m_offset;
    480482    transition->m_dictionaryKind = kind;
     
    500502    Structure* transition = preventExtensionsTransition(globalData, structure);
    501503
    502     if (transition->m_propertyTable) {
    503         PropertyTable::iterator end = transition->m_propertyTable->end();
    504         for (PropertyTable::iterator iter = transition->m_propertyTable->begin(); iter != end; ++iter)
     504    if (transition->propertyTable()) {
     505        PropertyTable::iterator end = transition->propertyTable()->end();
     506        for (PropertyTable::iterator iter = transition->propertyTable()->begin(); iter != end; ++iter)
    505507            iter->attributes |= DontDelete;
    506508    }
     
    515517    Structure* transition = preventExtensionsTransition(globalData, structure);
    516518
    517     if (transition->m_propertyTable) {
    518         PropertyTable::iterator iter = transition->m_propertyTable->begin();
    519         PropertyTable::iterator end = transition->m_propertyTable->end();
     519    if (transition->propertyTable()) {
     520        PropertyTable::iterator iter = transition->propertyTable()->begin();
     521        PropertyTable::iterator end = transition->propertyTable()->end();
    520522        if (iter != end)
    521523            transition->m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
     
    536538
    537539    structure->materializePropertyMapIfNecessary(globalData);
    538     transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
     540    transition->propertyTable().set(globalData, transition, structure->copyPropertyTableForPinning(globalData, transition));
    539541    transition->m_offset = structure->m_offset;
    540542    transition->m_preventExtensions = true;
     
    573575    checkOffset(transition->m_offset, transition->inlineCapacity());
    574576   
    575     if (structure->m_propertyTable) {
     577    if (structure->propertyTable()) {
    576578        structure->checkOffsetConsistency();
    577579        if (structure->m_isPinnedPropertyTable)
    578             transition->m_propertyTable = structure->m_propertyTable->copy(globalData, transition, structure->m_propertyTable->size() + 1);
    579         else
    580             transition->m_propertyTable = structure->m_propertyTable.release();
     580            transition->propertyTable().set(globalData, transition, structure->propertyTable()->copy(globalData, transition, structure->propertyTable()->size() + 1));
     581        else {
     582            transition->propertyTable().set(globalData, transition, structure->propertyTable().get());
     583            structure->propertyTable().clear();
     584        }
    581585    } else {
    582586        if (structure->previousID())
    583587            transition->materializePropertyMap(globalData);
    584588        else
    585             transition->createPropertyMap();
     589            transition->createPropertyMap(globalData);
    586590    }
    587591   
     
    598602
    599603    materializePropertyMapIfNecessary(globalData);
    600     if (!m_propertyTable)
     604    if (!propertyTable())
    601605        return true;
    602606
    603     PropertyTable::iterator end = m_propertyTable->end();
    604     for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
     607    PropertyTable::iterator end = propertyTable()->end();
     608    for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
    605609        if ((iter->attributes & DontDelete) != DontDelete)
    606610            return false;
     
    616620
    617621    materializePropertyMapIfNecessary(globalData);
    618     if (!m_propertyTable)
     622    if (!propertyTable())
    619623        return true;
    620624
    621     PropertyTable::iterator end = m_propertyTable->end();
    622     for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
     625    PropertyTable::iterator end = propertyTable()->end();
     626    for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
    623627        if (!(iter->attributes & DontDelete))
    624628            return false;
     
    634638    ASSERT(isDictionary());
    635639    if (isUncacheableDictionary()) {
    636         ASSERT(m_propertyTable);
    637 
    638         size_t propertyCount = m_propertyTable->size();
     640        ASSERT(propertyTable());
     641
     642        size_t propertyCount = propertyTable()->size();
    639643
    640644        // Holds our values compacted by insertion order.
     
    643647        // Copies out our values from their hashed locations, compacting property table offsets as we go.
    644648        unsigned i = 0;
    645         PropertyTable::iterator end = m_propertyTable->end();
     649        PropertyTable::iterator end = propertyTable()->end();
    646650        m_offset = invalidOffset;
    647         for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter, ++i) {
     651        for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter, ++i) {
    648652            values[i] = object->getDirect(iter->offset);
    649653            m_offset = iter->offset = offsetForPropertyNumber(i, m_inlineCapacity);
     
    654658            object->putDirect(globalData, offsetForPropertyNumber(i, m_inlineCapacity), values[i]);
    655659
    656         m_propertyTable->clearDeletedOffsets();
     660        propertyTable()->clearDeletedOffsets();
    657661        checkOffsetConsistency();
    658662    }
     
    689693void Structure::pin()
    690694{
    691     ASSERT(m_propertyTable);
     695    ASSERT(propertyTable());
    692696    m_isPinnedPropertyTable = true;
    693697    clearPreviousID();
     
    738742#endif
    739743
    740 PassOwnPtr<PropertyTable> Structure::copyPropertyTable(JSGlobalData& globalData, Structure* owner)
    741 {
    742     return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : 0);
    743 }
    744 
    745 PassOwnPtr<PropertyTable> Structure::copyPropertyTableForPinning(JSGlobalData& globalData, Structure* owner)
    746 {
    747     return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : new PropertyTable(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity)));
     744PropertyTable* Structure::copyPropertyTable(JSGlobalData& globalData, Structure* owner)
     745{
     746    if (!propertyTable())
     747        return 0;
     748    return PropertyTable::clone(globalData, owner, *propertyTable().get());
     749}
     750
     751PropertyTable* Structure::copyPropertyTableForPinning(JSGlobalData& globalData, Structure* owner)
     752{
     753    if (propertyTable())
     754        return PropertyTable::clone(globalData, owner, *propertyTable().get());
     755    return PropertyTable::create(globalData, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
    748756}
    749757
     
    753761
    754762    materializePropertyMapIfNecessary(globalData);
    755     if (!m_propertyTable)
     763    if (!propertyTable())
    756764        return invalidOffset;
    757765
    758     PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;
     766    PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
    759767    if (!entry)
    760768        return invalidOffset;
     
    768776{
    769777    materializePropertyMapIfNecessary(globalData);
    770     if (!m_propertyTable)
     778    if (!propertyTable())
    771779        return false;
    772780
    773     PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;
     781    PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
    774782    if (!entry)
    775783        return false;
     
    783791{
    784792    materializePropertyMapIfNecessary(globalData);
    785     if (!m_propertyTable)
     793    if (!propertyTable())
    786794        return;
    787795
    788     PropertyTable::iterator end = m_propertyTable->end();
    789     for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter)
     796    PropertyTable::iterator end = propertyTable()->end();
     797    for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter)
    790798        iter->specificValue.clear();
    791799}
     
    801809    StringImpl* rep = propertyName.uid();
    802810
    803     if (!m_propertyTable)
    804         createPropertyMap();
    805 
    806     PropertyOffset newOffset = m_propertyTable->nextOffset(m_inlineCapacity);
    807 
    808     m_propertyTable->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue), m_offset, PropertyTable::PropertyOffsetMayChange);
     811    if (!propertyTable())
     812        createPropertyMap(globalData);
     813
     814    PropertyOffset newOffset = propertyTable()->nextOffset(m_inlineCapacity);
     815
     816    propertyTable()->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue), m_offset, PropertyTable::PropertyOffsetMayChange);
    809817   
    810818    checkConsistency();
     
    818826    StringImpl* rep = propertyName.uid();
    819827
    820     if (!m_propertyTable)
     828    if (!propertyTable())
    821829        return invalidOffset;
    822830
    823     PropertyTable::find_iterator position = m_propertyTable->find(rep);
     831    PropertyTable::find_iterator position = propertyTable()->find(rep);
    824832    if (!position.first)
    825833        return invalidOffset;
     
    827835    PropertyOffset offset = position.first->offset;
    828836
    829     m_propertyTable->remove(position);
    830     m_propertyTable->addDeletedOffset(offset);
     837    propertyTable()->remove(position);
     838    propertyTable()->addDeletedOffset(offset);
    831839
    832840    checkConsistency();
     
    834842}
    835843
    836 void Structure::createPropertyMap(unsigned capacity)
    837 {
    838     ASSERT(!m_propertyTable);
     844void Structure::createPropertyMap(JSGlobalData& globalData, unsigned capacity)
     845{
     846    ASSERT(!propertyTable());
    839847
    840848    checkConsistency();
    841     m_propertyTable = adoptPtr(new PropertyTable(capacity));
     849    propertyTable().set(globalData, this, PropertyTable::create(globalData, capacity));
    842850}
    843851
     
    845853{
    846854    materializePropertyMapIfNecessary(globalData);
    847     if (!m_propertyTable)
     855    if (!propertyTable())
    848856        return;
    849857
    850858    bool knownUnique = !propertyNames.size();
    851859
    852     PropertyTable::iterator end = m_propertyTable->end();
    853     for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
     860    PropertyTable::iterator end = propertyTable()->end();
     861    for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
    854862        ASSERT(m_hasNonEnumerableProperties || !(iter->attributes & DontEnum));
    855863        if (iter->key->isIdentifier() && (!(iter->attributes & DontEnum) || mode == IncludeDontEnumProperties)) {
     
    883891    visitor.append(&thisObject->m_previousOrRareData);
    884892    visitor.append(&thisObject->m_specificValueInPrevious);
    885     if (thisObject->m_propertyTable) {
    886         PropertyTable::iterator end = thisObject->m_propertyTable->end();
    887         for (PropertyTable::iterator ptr = thisObject->m_propertyTable->begin(); ptr != end; ++ptr)
    888             visitor.append(&ptr->specificValue);
    889     }
     893
     894    if (thisObject->m_isPinnedPropertyTable) {
     895        ASSERT(thisObject->m_propertyTableUnsafe);
     896        visitor.append(&thisObject->m_propertyTableUnsafe);
     897    } else if (thisObject->m_propertyTableUnsafe)
     898        thisObject->m_propertyTableUnsafe.clear();
    890899}
    891900
     
    978987void Structure::checkConsistency()
    979988{
    980     if (!m_propertyTable)
     989    if (!propertyTable())
    981990        return;
    982991
    983992    if (!m_hasNonEnumerableProperties) {
    984         PropertyTable::iterator end = m_propertyTable->end();
    985         for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
     993        PropertyTable::iterator end = propertyTable()->end();
     994        for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
    986995            ASSERT(!(iter->attributes & DontEnum));
    987996        }
    988997    }
    989998
    990     m_propertyTable->checkConsistency();
     999    propertyTable()->checkConsistency();
    9911000}
    9921001
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r144113 r144708  
    3232#include "JSCell.h"
    3333#include "JSType.h"
    34 #include "PropertyMapHashTable.h"
    3534#include "PropertyName.h"
    3635#include "PropertyNameArray.h"
     36#include "PropertyOffset.h"
    3737#include "Protect.h"
    3838#include "StructureRareData.h"
     
    4141#include "Watchpoint.h"
    4242#include "Weak.h"
    43 #include <wtf/PassOwnPtr.h>
    4443#include <wtf/PassRefPtr.h>
    4544#include <wtf/RefCounted.h>
     
    5251class PropertyNameArray;
    5352class PropertyNameArrayData;
     53class PropertyTable;
    5454class StructureChain;
    5555class SlotVisitor;
     
    109109    bool isExtensible() const { return !m_preventExtensions; }
    110110    bool didTransition() const { return m_didTransition; }
    111     bool putWillGrowOutOfLineStorage()
    112     {
    113         checkOffsetConsistency();
    114            
    115         ASSERT(outOfLineCapacity() >= outOfLineSize());
    116            
    117         if (!m_propertyTable) {
    118             unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset);
    119             ASSERT(outOfLineCapacity() >= currentSize);
    120             return currentSize == outOfLineCapacity();
    121         }
    122            
    123         ASSERT(totalStorageCapacity() >= m_propertyTable->propertyStorageSize());
    124         if (m_propertyTable->hasDeletedOffset())
    125             return false;
    126            
    127         ASSERT(totalStorageCapacity() >= m_propertyTable->size());
    128         return m_propertyTable->size() == totalStorageCapacity();
    129     }
     111    bool putWillGrowOutOfLineStorage();
    130112    JS_EXPORT_PRIVATE size_t suggestedNewOutOfLineStorageCapacity();
    131113
     
    383365    PropertyOffset remove(PropertyName);
    384366
    385     void createPropertyMap(unsigned keyCount = 0);
     367    void createPropertyMap(JSGlobalData&, unsigned keyCount = 0);
    386368    void checkConsistency();
    387369
     
    389371    void despecifyAllFunctions(JSGlobalData&);
    390372
    391     PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner);
    392     PassOwnPtr<PropertyTable> copyPropertyTableForPinning(JSGlobalData&, Structure* owner);
     373    WriteBarrier<PropertyTable>& propertyTable();
     374
     375    PropertyTable* copyPropertyTable(JSGlobalData&, Structure* owner);
     376    PropertyTable* copyPropertyTableForPinning(JSGlobalData&, Structure* owner);
    393377    JS_EXPORT_PRIVATE void materializePropertyMap(JSGlobalData&);
    394378    void materializePropertyMapIfNecessary(JSGlobalData& globalData)
     
    396380        ASSERT(structure()->classInfo() == &s_info);
    397381        ASSERT(checkOffsetConsistency());
    398         if (!m_propertyTable && previousID())
     382        if (!propertyTable() && previousID())
    399383            materializePropertyMap(globalData);
    400384    }
     
    403387        ASSERT(structure()->classInfo() == &s_info);
    404388        checkOffsetConsistency();
    405         if (!m_propertyTable)
     389        if (!propertyTable())
    406390            materializePropertyMap(globalData);
    407391    }
     
    446430    }
    447431       
    448     ALWAYS_INLINE bool checkOffsetConsistency() const
    449     {
    450         if (!m_propertyTable) {
    451             ASSERT(!m_isPinnedPropertyTable);
    452             return true;
    453         }
    454            
    455         RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == m_propertyTable->propertyStorageSize());
    456         unsigned totalSize = m_propertyTable->propertyStorageSize();
    457         RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset));
    458            
    459         return true;
    460     }
     432    bool checkOffsetConsistency() const;
    461433
    462434    void allocateRareData(JSGlobalData&);
     
    483455    StructureTransitionTable m_transitionTable;
    484456
    485     OwnPtr<PropertyTable> m_propertyTable;
     457    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
     458    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
    486459
    487460    mutable InlineWatchpointSet m_transitionWatchpointSet;
  • trunk/Source/JavaScriptCore/runtime/StructureInlines.h

    r144113 r144708  
    2727#define StructureInlines_h
    2828
     29#include "PropertyMapHashTable.h"
    2930#include "Structure.h"
    3031
     
    6263    ASSERT(structure()->classInfo() == &s_info);
    6364    materializePropertyMapIfNecessary(globalData);
    64     if (!m_propertyTable)
     65    if (!propertyTable())
    6566        return invalidOffset;
    6667
    67     PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;
     68    PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
    6869    return entry ? entry->offset : invalidOffset;
    6970}
     
    7374    ASSERT(structure()->classInfo() == &s_info);
    7475    materializePropertyMapIfNecessary(globalData);
    75     if (!m_propertyTable)
     76    if (!propertyTable())
    7677        return invalidOffset;
    7778
    78     PropertyMapEntry* entry = m_propertyTable->findWithString(name.impl()).first;
     79    PropertyMapEntry* entry = propertyTable()->findWithString(name.impl()).first;
    7980    return entry ? entry->offset : invalidOffset;
    8081}
     
    180181}
    181182
     183inline bool Structure::putWillGrowOutOfLineStorage()
     184{
     185    checkOffsetConsistency();
     186
     187    ASSERT(outOfLineCapacity() >= outOfLineSize());
     188
     189    if (!propertyTable()) {
     190        unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset);
     191        ASSERT(outOfLineCapacity() >= currentSize);
     192        return currentSize == outOfLineCapacity();
     193    }
     194
     195    ASSERT(totalStorageCapacity() >= propertyTable()->propertyStorageSize());
     196    if (propertyTable()->hasDeletedOffset())
     197        return false;
     198
     199    ASSERT(totalStorageCapacity() >= propertyTable()->size());
     200    return propertyTable()->size() == totalStorageCapacity();
     201}
     202
     203ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable()
     204{
     205    ASSERT(!globalObject() || !globalObject()->globalData().heap.isBusy());
     206    return m_propertyTableUnsafe;
     207}
     208
     209ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
     210{
     211    PropertyTable* propertyTable = m_propertyTableUnsafe.get();
     212
     213    if (!propertyTable) {
     214        ASSERT(!m_isPinnedPropertyTable);
     215        return true;
     216    }
     217
     218    RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize());
     219    unsigned totalSize = propertyTable->propertyStorageSize();
     220    RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset));
     221
     222    return true;
     223}
     224
    182225} // namespace JSC
    183226
  • trunk/Source/JavaScriptCore/runtime/WriteBarrier.h

    r128084 r144708  
    100100    T* get() const
    101101    {
    102         if (m_cell)
    103             validateCell(m_cell);
    104         return reinterpret_cast<T*>(static_cast<void*>(m_cell));
     102        // Copy m_cell to a local to avoid multiple-read issues. (See <http://webkit.org/b/110854>)
     103        JSCell* cell = m_cell;
     104        if (cell)
     105            validateCell(cell);
     106        return reinterpret_cast<T*>(static_cast<void*>(cell));
    105107    }
    106108
Note: See TracChangeset for help on using the changeset viewer.