Ignore:
Timestamp:
Feb 1, 2010, 1:43:01 AM (15 years ago)
Author:
[email protected]
Message:

2010-01-31 Oliver Hunt <[email protected]>

Reviewed by Maciej Stachowiak.

JSC is failing to propagate anonymous slot count on some transitions
https://bugs.webkit.org/show_bug.cgi?id=34321

Remove secondary Structure constructor, and make Structure store a copy
of the number of anonymous slots directly so saving an immediate allocation
of a property map for all structures with anonymous storage, which also
avoids the leaked property map on new property transition in the original
version of this patch.

We need to propagate the the anonymous slot count otherwise we can end up
with a structure recording incorrect information about the available and
needed space for property storage, or alternatively incorrectly reusing
some slots.

  • JavaScriptCore.exp:
  • runtime/Structure.cpp: (JSC::Structure::Structure): (JSC::Structure::materializePropertyMap): (JSC::Structure::addPropertyTransition): (JSC::Structure::changePrototypeTransition): (JSC::Structure::despecifyFunctionTransition): (JSC::Structure::getterSetterTransition): (JSC::Structure::toDictionaryTransition): (JSC::Structure::flattenDictionaryStructure): (JSC::Structure::copyPropertyTable): (JSC::Structure::put): (JSC::Structure::remove): (JSC::Structure::insertIntoPropertyMapHashTable): (JSC::Structure::createPropertyMapHashTable):
  • runtime/Structure.h: (JSC::Structure::create): (JSC::Structure::hasAnonymousSlots): (JSC::Structure::anonymousSlotCount):

2010-02-01 Oliver Hunt <[email protected]>

Reviewed by Maciej Stachowiak.

JSC is failing to propagate anonymous slot count on some transitions
https://bugs.webkit.org/show_bug.cgi?id=34321

Add test case for modifying DOM objects with anonymous storage.

  • fast/dom/Window/anonymous-slot-with-changes-expected.txt: Added.
  • fast/dom/Window/anonymous-slot-with-changes.html: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/Structure.cpp

    r54100 r54129  
    124124}
    125125
    126 Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
     126Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
    127127    : m_typeInfo(typeInfo)
    128128    , m_prototype(prototype)
     
    136136    , m_attributesInPrevious(0)
    137137    , m_specificFunctionThrashCount(0)
     138    , m_anonymousSlotCount(anonymousSlotCount)
    138139{
    139140    ASSERT(m_prototype);
     
    272273            rehashPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); // This could be made more efficient by combining with the copy above.
    273274    }
    274 
     275   
     276    m_propertyTable->anonymousSlotCount = m_anonymousSlotCount;
    275277    for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
    276278        structure = structures[i];
     
    367369    }
    368370
    369     RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
     371    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount());
    370372
    371373    transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
     
    380382
    381383    if (structure->m_propertyTable) {
     384        ASSERT(structure->m_propertyTable->anonymousSlotCount == structure->m_anonymousSlotCount);
    382385        if (structure->m_isPinnedPropertyTable)
    383386            transition->m_propertyTable = structure->copyPropertyTable();
     
    398401
    399402    transition->m_offset = offset;
    400 
     403    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
    401404    structure->table.add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
    402405    return transition.release();
     
    416419PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
    417420{
    418     RefPtr<Structure> transition = create(prototype, structure->typeInfo());
     421    RefPtr<Structure> transition = create(prototype, structure->typeInfo(), structure->anonymousSlotCount());
    419422
    420423    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     
    428431    transition->m_propertyTable = structure->copyPropertyTable();
    429432    transition->m_isPinnedPropertyTable = true;
    430 
     433   
     434    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
    431435    return transition.release();
    432436}
     
    435439{
    436440    ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount);
    437     RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
     441    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
    438442
    439443    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     
    454458        ASSERT_UNUSED(removed, removed);
    455459    }
    456 
     460   
     461    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
    457462    return transition.release();
    458463}
     
    460465PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
    461466{
    462     RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
     467    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
    463468    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    464469    transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
     
    471476    transition->m_propertyTable = structure->copyPropertyTable();
    472477    transition->m_isPinnedPropertyTable = true;
    473 
     478   
     479    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
    474480    return transition.release();
    475481}
     
    479485    ASSERT(!structure->isUncacheableDictionary());
    480486   
    481     RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
     487    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount());
    482488    transition->m_dictionaryKind = kind;
    483489    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     
    490496    transition->m_isPinnedPropertyTable = true;
    491497   
     498    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
    492499    return transition.release();
    493500}
     
    523530        // reorder the storage, so we have to copy the current values out
    524531        Vector<JSValue> values(propertyCount);
     532        ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount);
    525533        unsigned anonymousSlotCount = m_propertyTable->anonymousSlotCount;
    526534        for (unsigned i = 0; i < propertyCount; i++) {
     
    613621    if (!m_propertyTable)
    614622        return 0;
    615 
     623   
     624    ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount);
    616625    size_t tableSize = PropertyMapHashTable::allocationSize(m_propertyTable->size);
    617626    PropertyMapHashTable* newTable = static_cast<PropertyMapHashTable*>(fastMalloc(tableSize));
     
    755764    if (!m_propertyTable)
    756765        createPropertyMapHashTable();
     766    ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount);
    757767
    758768    // FIXME: Consider a fast case for tables with no deleted sentinels.
     
    849859    if (!m_propertyTable)
    850860        return notFound;
    851 
     861   
     862    ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount);
    852863#if DUMP_PROPERTYMAP_STATS
    853864    ++numProbes;
     
    913924{
    914925    ASSERT(m_propertyTable);
    915 
     926   
     927    ASSERT(m_propertyTable->anonymousSlotCount == m_anonymousSlotCount);
    916928    unsigned i = entry.key->existingHash();
    917929    unsigned k = 0;
     
    963975    m_propertyTable->size = newTableSize;
    964976    m_propertyTable->sizeMask = newTableSize - 1;
     977    m_propertyTable->anonymousSlotCount = m_anonymousSlotCount;
    965978
    966979    checkConsistency();
Note: See TracChangeset for help on using the changeset viewer.