Ignore:
Timestamp:
Nov 9, 2009, 6:19:04 PM (16 years ago)
Author:
[email protected]
Message:

Can cache prototype lookups on uncacheable dictionaries.
https://bugs.webkit.org/show_bug.cgi?id=31198

Reviewed by Gavin Barraclough.

Replace fromDictionaryTransition with flattenDictionaryObject and
flattenDictionaryStructure. This change is necessary as we need to
guarantee that our attempt to convert away from a dictionary structure
will definitely succeed, and in some cases this requires mutating the
object storage itself.

File:
1 edited

Legend:

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

    r50320 r50704  
    7878#endif
    7979
     80static int comparePropertyMapEntryIndices(const void* a, const void* b);
     81
    8082void Structure::dumpStatistics()
    8183{
     
    535537}
    536538
    537 PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
    538 {
    539     ASSERT(structure->isDictionary());
    540 
    541     // Since dictionary Structures are not shared, and no opcodes specialize
    542     // for them, we don't need to allocate a new Structure when transitioning
    543     // to non-dictionary status.
    544 
    545     // FIMXE: We can make this more efficient by canonicalizing the Structure (draining the
    546     // deleted offsets vector) before transitioning from dictionary.
    547     if (!structure->m_propertyTable || !structure->m_propertyTable->deletedOffsets || structure->m_propertyTable->deletedOffsets->isEmpty())
    548         structure->m_dictionaryKind = NoneDictionaryKind;
    549 
    550     return structure;
     539PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object)
     540{
     541    ASSERT(isDictionary());
     542    if (isUncacheableDictionary()) {
     543        ASSERT(m_propertyTable);
     544        Vector<PropertyMapEntry*> sortedPropertyEntries(m_propertyTable->keyCount);
     545        PropertyMapEntry** p = sortedPropertyEntries.data();
     546        unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
     547        for (unsigned i = 1; i <= entryCount; i++) {
     548            if (m_propertyTable->entries()[i].key)
     549                *p++ = &m_propertyTable->entries()[i];
     550        }
     551        size_t propertyCount = p - sortedPropertyEntries.data();
     552        qsort(sortedPropertyEntries.data(), propertyCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
     553        sortedPropertyEntries.resize(propertyCount);
     554
     555        // We now have the properties currently defined on this object
     556        // in the order that they are expected to be in, but we need to
     557        // reorder the storage, so we have to copy the current values out
     558        Vector<JSValue> values(propertyCount);
     559        unsigned anonymousSlotCount = m_propertyTable->anonymousSlotCount;
     560        for (unsigned i = 0; i < propertyCount; i++) {
     561            PropertyMapEntry* entry = sortedPropertyEntries[i];
     562            values[i] = object->getDirectOffset(entry->offset);
     563            // Update property table to have the new property offsets
     564            entry->offset = anonymousSlotCount + i;
     565            entry->index = i;
     566        }
     567       
     568        // Copy the original property values into their final locations
     569        for (unsigned i = 0; i < propertyCount; i++)
     570            object->putDirectOffset(anonymousSlotCount + i, values[i]);
     571
     572        if (m_propertyTable->deletedOffsets) {
     573            delete m_propertyTable->deletedOffsets;
     574            m_propertyTable->deletedOffsets = 0;
     575        }
     576    }
     577
     578    m_dictionaryKind = NoneDictionaryKind;
     579    return this;
    551580}
    552581
     
    10051034}
    10061035
    1007 static int comparePropertyMapEntryIndices(const void* a, const void* b)
     1036int comparePropertyMapEntryIndices(const void* a, const void* b)
    10081037{
    10091038    unsigned ia = static_cast<PropertyMapEntry* const*>(a)[0]->index;
Note: See TracChangeset for help on using the changeset viewer.