Ignore:
Timestamp:
Sep 9, 2008, 4:42:47 PM (17 years ago)
Author:
[email protected]
Message:

2008-09-09 Sam Weinig <[email protected]>

Reviewed by Geoffrey Garen.

Replace uses of PropertyMap::get and PropertyMap::getLocation with
PropertyMap::getOffset.

Sunspider reports this as a .6% improvement.

  • JavaScriptCore.exp:
  • kjs/JSObject.cpp: (JSC::JSObject::put): (JSC::JSObject::deleteProperty): (JSC::JSObject::getPropertyAttributes):
  • kjs/JSObject.h: (JSC::JSObject::getDirect): (JSC::JSObject::getDirectLocation): (JSC::JSObject::locationForOffset):
  • kjs/PropertyMap.cpp: (JSC::PropertyMap::remove): (JSC::PropertyMap::getOffset):
  • kjs/PropertyMap.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/PropertyMap.cpp

    r36285 r36304  
    118118}
    119119
    120 JSValue* PropertyMap::get(const Identifier& propertyName, unsigned& attributes, const PropertyStorage& propertyStorage) const
    121 {
    122     ASSERT(!propertyName.isNull());
    123 
    124     UString::Rep* rep = propertyName._ustring.rep();
    125 
    126     if (!m_table)
    127         return 0;
    128 
    129     unsigned i = rep->computedHash();
    130 
    131 #if DUMP_PROPERTYMAP_STATS
    132     ++numProbes;
    133 #endif
    134 
    135     unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    136     if (entryIndex == emptyEntryIndex)
    137         return 0;
    138 
    139     if (rep == m_table->entries()[entryIndex - 1].key) {
    140         attributes = m_table->entries()[entryIndex - 1].attributes;
    141         return propertyStorage[entryIndex - 1];
    142     }
    143 
    144 #if DUMP_PROPERTYMAP_STATS
    145     ++numCollisions;
    146 #endif
    147 
    148     unsigned k = 1 | doubleHash(rep->computedHash());
    149 
    150     while (1) {
    151         i += k;
    152 
    153 #if DUMP_PROPERTYMAP_STATS
    154         ++numRehashes;
    155 #endif
    156 
    157         entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    158         if (entryIndex == emptyEntryIndex)
    159             return 0;
    160 
    161         if (rep == m_table->entries()[entryIndex - 1].key) {
    162             attributes = m_table->entries()[entryIndex - 1].attributes;
    163             return propertyStorage[entryIndex - 1];
    164         }
    165     }
    166 }
    167 
    168 JSValue* PropertyMap::get(const Identifier& propertyName, const PropertyStorage& propertyStorage) const
    169 {
    170     ASSERT(!propertyName.isNull());
    171 
    172     UString::Rep* rep = propertyName._ustring.rep();
    173 
    174     if (!m_table)
    175         return 0;
    176 
    177     unsigned i = rep->computedHash();
    178 
    179 #if DUMP_PROPERTYMAP_STATS
    180     ++numProbes;
    181 #endif
    182 
    183     unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    184     if (entryIndex == emptyEntryIndex)
    185         return 0;
    186 
    187     if (rep == m_table->entries()[entryIndex - 1].key)
    188         return propertyStorage[entryIndex - 1];
    189 
    190 #if DUMP_PROPERTYMAP_STATS
    191     ++numCollisions;
    192 #endif
    193 
    194     unsigned k = 1 | doubleHash(rep->computedHash());
    195 
    196     while (1) {
    197         i += k;
    198 
    199 #if DUMP_PROPERTYMAP_STATS
    200         ++numRehashes;
    201 #endif
    202 
    203         entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    204         if (entryIndex == emptyEntryIndex)
    205             return 0;
    206 
    207         if (rep == m_table->entries()[entryIndex - 1].key)
    208             return propertyStorage[entryIndex - 1];
    209     }
    210 }
    211 
    212 JSValue** PropertyMap::getLocation(const Identifier& propertyName, const PropertyStorage& propertyStorage)
    213 {
    214     ASSERT(!propertyName.isNull());
    215 
    216     UString::Rep* rep = propertyName._ustring.rep();
    217 
    218     if (!m_table)
    219         return 0;
    220 
    221     unsigned i = rep->computedHash();
    222 
    223 #if DUMP_PROPERTYMAP_STATS
    224     ++numProbes;
    225 #endif
    226 
    227     unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    228     if (entryIndex == emptyEntryIndex)
    229         return 0;
    230 
    231     if (rep == m_table->entries()[entryIndex - 1].key)
    232         return &propertyStorage[entryIndex - 1];
    233 
    234 #if DUMP_PROPERTYMAP_STATS
    235     ++numCollisions;
    236 #endif
    237 
    238     unsigned k = 1 | doubleHash(rep->computedHash());
    239 
    240     while (1) {
    241         i += k;
    242 
    243 #if DUMP_PROPERTYMAP_STATS
    244         ++numRehashes;
    245 #endif
    246 
    247         entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    248         if (entryIndex == emptyEntryIndex)
    249             return 0;
    250 
    251         if (rep == m_table->entries()[entryIndex - 1].key)
    252             return &propertyStorage[entryIndex - 1];
    253     }
    254 }
    255 
    256 JSValue** PropertyMap::getLocation(const Identifier& propertyName, bool& isWriteable, const PropertyStorage& propertyStorage)
    257 {
    258     ASSERT(!propertyName.isNull());
    259 
    260     UString::Rep* rep = propertyName._ustring.rep();
    261 
    262     if (!m_table)
    263         return 0;
    264 
    265     unsigned i = rep->computedHash();
    266 
    267 #if DUMP_PROPERTYMAP_STATS
    268     ++numProbes;
    269 #endif
    270 
    271     unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    272     if (entryIndex == emptyEntryIndex)
    273         return 0;
    274 
    275     if (rep == m_table->entries()[entryIndex - 1].key) {
    276         isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly);
    277         return &propertyStorage[entryIndex - 1];
    278     }
    279 
    280 #if DUMP_PROPERTYMAP_STATS
    281     ++numCollisions;
    282 #endif
    283 
    284     unsigned k = 1 | doubleHash(rep->computedHash());
    285 
    286     while (1) {
    287         i += k;
    288 
    289 #if DUMP_PROPERTYMAP_STATS
    290         ++numRehashes;
    291 #endif
    292 
    293         entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    294         if (entryIndex == emptyEntryIndex)
    295             return 0;
    296 
    297         if (rep == m_table->entries()[entryIndex - 1].key) {
    298             isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly);
    299             return &propertyStorage[entryIndex - 1];
    300         }
    301     }
    302 }
    303 
    304120void PropertyMap::put(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage)
    305121{
     
    392208}
    393209
    394 size_t PropertyMap::getOffset(const Identifier& propertyName)
    395 {
    396     ASSERT(!propertyName.isNull());
    397 
    398     if (!m_table)
    399         return WTF::notFound;
    400 
    401     UString::Rep* rep = propertyName._ustring.rep();
    402 
    403     unsigned i = rep->computedHash();
    404 
    405 #if DUMP_PROPERTYMAP_STATS
    406     ++numProbes;
    407 #endif
    408 
    409     unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    410     if (entryIndex == emptyEntryIndex)
    411         return WTF::notFound;
    412 
    413     if (rep == m_table->entries()[entryIndex - 1].key)
    414         return entryIndex - 1;
    415 
    416 #if DUMP_PROPERTYMAP_STATS
    417     ++numCollisions;
    418 #endif
    419 
    420     unsigned k = 1 | doubleHash(rep->computedHash());
    421 
    422     while (1) {
    423         i += k;
    424 
    425 #if DUMP_PROPERTYMAP_STATS
    426         ++numRehashes;
    427 #endif
    428 
    429         entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    430         if (entryIndex == emptyEntryIndex)
    431             return WTF::notFound;
    432 
    433         if (rep == m_table->entries()[entryIndex - 1].key)
    434             return entryIndex - 1;
    435     }
    436 }
    437 
    438 size_t PropertyMap::getOffset(const Identifier& propertyName, bool& isWriteable)
    439 {
    440     ASSERT(!propertyName.isNull());
    441 
    442     if (!m_table)
    443         return WTF::notFound;
    444 
    445     UString::Rep* rep = propertyName._ustring.rep();
    446 
    447     unsigned i = rep->computedHash();
    448 
    449 #if DUMP_PROPERTYMAP_STATS
    450     ++numProbes;
    451 #endif
    452 
    453     unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    454     if (entryIndex == emptyEntryIndex)
    455         return WTF::notFound;
    456 
    457     if (rep == m_table->entries()[entryIndex - 1].key) {
    458         isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly);
    459         return entryIndex - 1;
    460     }
    461 
    462 #if DUMP_PROPERTYMAP_STATS
    463     ++numCollisions;
    464 #endif
    465 
    466     unsigned k = 1 | doubleHash(rep->computedHash());
    467 
    468     while (1) {
    469         i += k;
    470 
    471 #if DUMP_PROPERTYMAP_STATS
    472         ++numRehashes;
    473 #endif
    474 
    475         entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    476         if (entryIndex == emptyEntryIndex)
    477             return WTF::notFound;
    478 
    479         if (rep == m_table->entries()[entryIndex - 1].key) {
    480             isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly);
    481             return entryIndex - 1;
    482         }
    483     }
    484 }
    485 
    486 void PropertyMap::insert(const Entry& entry, JSValue* value, PropertyStorage& propertyStorage)
    487 {
    488     ASSERT(m_table);
    489 
    490     unsigned i = entry.key->computedHash();
    491     unsigned k = 0;
    492 
    493 #if DUMP_PROPERTYMAP_STATS
    494     ++numProbes;
    495 #endif
    496 
    497     while (1) {
    498         unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    499         if (entryIndex == emptyEntryIndex)
    500             break;
    501 
    502         if (k == 0) {
    503             k = 1 | doubleHash(entry.key->computedHash());
    504 #if DUMP_PROPERTYMAP_STATS
    505             ++numCollisions;
    506 #endif
    507         }
    508 
    509         i += k;
    510 
    511 #if DUMP_PROPERTYMAP_STATS
    512         ++numRehashes;
    513 #endif
    514     }
    515 
    516     unsigned entryIndex = m_table->keyCount + 2;
    517     m_table->entryIndices[i & m_table->sizeMask] = entryIndex;
    518     m_table->entries()[entryIndex - 1] = entry;
    519 
    520     propertyStorage[entryIndex - 1] = value;
    521 
    522     ++m_table->keyCount;
    523 }
    524 
    525 void PropertyMap::expand(PropertyStorage& propertyStorage)
    526 {
    527     if (!m_table)
    528         createTable(propertyStorage);
    529     else
    530         rehash(m_table->size * 2, propertyStorage);
    531 }
    532 
    533 void PropertyMap::rehash(PropertyStorage& propertyStorage)
    534 {
    535     ASSERT(m_table);
    536     ASSERT(m_table->size);
    537     rehash(m_table->size, propertyStorage);
    538 }
    539 
    540 void PropertyMap::createTable(PropertyStorage& propertyStorage)
    541 {
    542     const unsigned newTableSize = 16;
    543 
    544     ASSERT(!m_table);
    545 
    546     checkConsistency(propertyStorage);
    547 
    548     m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
    549     m_table->size = newTableSize;
    550     m_table->sizeMask = newTableSize - 1;
    551 
    552     propertyStorage.set(new JSValue*[m_table->size]);
    553 
    554     checkConsistency(propertyStorage);
    555 }
    556 
    557 void PropertyMap::rehash(unsigned newTableSize, PropertyStorage& propertyStorage)
    558 {
    559     ASSERT(m_table);
    560 
    561     checkConsistency(propertyStorage);
    562 
    563     Table* oldTable = m_table;
    564     JSValue** oldPropertStorage = propertyStorage.release();
    565 
    566     m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
    567     m_table->size = newTableSize;
    568     m_table->sizeMask = newTableSize - 1;
    569 
    570     propertyStorage.set(new JSValue*[m_table->size]);
    571 
    572     unsigned lastIndexUsed = 0;
    573     unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
    574     for (unsigned i = 1; i <= entryCount; ++i) {
    575         if (oldTable->entries()[i].key) {
    576             lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
    577             insert(oldTable->entries()[i], oldPropertStorage[i], propertyStorage);
    578         }
    579     }
    580     m_table->lastIndexUsed = lastIndexUsed;
    581 
    582     fastFree(oldTable);
    583     delete [] oldPropertStorage;
    584 
    585     checkConsistency(propertyStorage);
    586 }
    587 
    588 void PropertyMap::resizePropertyStorage(PropertyStorage& propertyStorage, unsigned oldSize)
    589 {
    590     ASSERT(m_table);
    591 
    592     if (propertyStorage) {
    593         JSValue** oldPropertStorage = propertyStorage.release();
    594         propertyStorage.set(new JSValue*[m_table->size]);
    595 
    596         // FIXME: this can probalby use memcpy
    597         for (unsigned i = 1; i <= oldSize; ++i)
    598             propertyStorage[i] = oldPropertStorage[i];
    599 
    600         delete [] oldPropertStorage;
    601     } else
    602         propertyStorage.set(new JSValue*[m_table->size]);
    603 
    604     checkConsistency(propertyStorage);
    605 }
    606 
    607210void PropertyMap::remove(const Identifier& propertyName, PropertyStorage& propertyStorage)
    608211{
     
    664267    if (m_table->deletedSentinelCount * 4 >= m_table->size)
    665268        rehash(propertyStorage);
     269
     270    checkConsistency(propertyStorage);
     271}
     272
     273size_t PropertyMap::getOffset(const Identifier& propertyName)
     274{
     275    ASSERT(!propertyName.isNull());
     276
     277    if (!m_table)
     278        return WTF::notFound;
     279
     280    UString::Rep* rep = propertyName._ustring.rep();
     281
     282    unsigned i = rep->computedHash();
     283
     284#if DUMP_PROPERTYMAP_STATS
     285    ++numProbes;
     286#endif
     287
     288    unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
     289    if (entryIndex == emptyEntryIndex)
     290        return WTF::notFound;
     291
     292    if (rep == m_table->entries()[entryIndex - 1].key)
     293        return entryIndex - 1;
     294
     295#if DUMP_PROPERTYMAP_STATS
     296    ++numCollisions;
     297#endif
     298
     299    unsigned k = 1 | doubleHash(rep->computedHash());
     300
     301    while (1) {
     302        i += k;
     303
     304#if DUMP_PROPERTYMAP_STATS
     305        ++numRehashes;
     306#endif
     307
     308        entryIndex = m_table->entryIndices[i & m_table->sizeMask];
     309        if (entryIndex == emptyEntryIndex)
     310            return WTF::notFound;
     311
     312        if (rep == m_table->entries()[entryIndex - 1].key)
     313            return entryIndex - 1;
     314    }
     315}
     316
     317size_t PropertyMap::getOffset(const Identifier& propertyName, unsigned& attributes)
     318{
     319    ASSERT(!propertyName.isNull());
     320
     321    if (!m_table)
     322        return WTF::notFound;
     323
     324    UString::Rep* rep = propertyName._ustring.rep();
     325
     326    unsigned i = rep->computedHash();
     327
     328#if DUMP_PROPERTYMAP_STATS
     329    ++numProbes;
     330#endif
     331
     332    unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
     333    if (entryIndex == emptyEntryIndex)
     334        return WTF::notFound;
     335
     336    if (rep == m_table->entries()[entryIndex - 1].key) {
     337        attributes = m_table->entries()[entryIndex - 1].attributes;
     338        return entryIndex - 1;
     339    }
     340
     341#if DUMP_PROPERTYMAP_STATS
     342    ++numCollisions;
     343#endif
     344
     345    unsigned k = 1 | doubleHash(rep->computedHash());
     346
     347    while (1) {
     348        i += k;
     349
     350#if DUMP_PROPERTYMAP_STATS
     351        ++numRehashes;
     352#endif
     353
     354        entryIndex = m_table->entryIndices[i & m_table->sizeMask];
     355        if (entryIndex == emptyEntryIndex)
     356            return WTF::notFound;
     357
     358        if (rep == m_table->entries()[entryIndex - 1].key) {
     359            attributes = m_table->entries()[entryIndex - 1].attributes;
     360            return entryIndex - 1;
     361        }
     362    }
     363}
     364
     365size_t PropertyMap::getOffset(const Identifier& propertyName, bool& isWriteable)
     366{
     367    ASSERT(!propertyName.isNull());
     368
     369    if (!m_table)
     370        return WTF::notFound;
     371
     372    UString::Rep* rep = propertyName._ustring.rep();
     373
     374    unsigned i = rep->computedHash();
     375
     376#if DUMP_PROPERTYMAP_STATS
     377    ++numProbes;
     378#endif
     379
     380    unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
     381    if (entryIndex == emptyEntryIndex)
     382        return WTF::notFound;
     383
     384    if (rep == m_table->entries()[entryIndex - 1].key) {
     385        isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly);
     386        return entryIndex - 1;
     387    }
     388
     389#if DUMP_PROPERTYMAP_STATS
     390    ++numCollisions;
     391#endif
     392
     393    unsigned k = 1 | doubleHash(rep->computedHash());
     394
     395    while (1) {
     396        i += k;
     397
     398#if DUMP_PROPERTYMAP_STATS
     399        ++numRehashes;
     400#endif
     401
     402        entryIndex = m_table->entryIndices[i & m_table->sizeMask];
     403        if (entryIndex == emptyEntryIndex)
     404            return WTF::notFound;
     405
     406        if (rep == m_table->entries()[entryIndex - 1].key) {
     407            isWriteable = !(m_table->entries()[entryIndex - 1].attributes & ReadOnly);
     408            return entryIndex - 1;
     409        }
     410    }
     411}
     412
     413void PropertyMap::insert(const Entry& entry, JSValue* value, PropertyStorage& propertyStorage)
     414{
     415    ASSERT(m_table);
     416
     417    unsigned i = entry.key->computedHash();
     418    unsigned k = 0;
     419
     420#if DUMP_PROPERTYMAP_STATS
     421    ++numProbes;
     422#endif
     423
     424    while (1) {
     425        unsigned entryIndex = m_table->entryIndices[i & m_table->sizeMask];
     426        if (entryIndex == emptyEntryIndex)
     427            break;
     428
     429        if (k == 0) {
     430            k = 1 | doubleHash(entry.key->computedHash());
     431#if DUMP_PROPERTYMAP_STATS
     432            ++numCollisions;
     433#endif
     434        }
     435
     436        i += k;
     437
     438#if DUMP_PROPERTYMAP_STATS
     439        ++numRehashes;
     440#endif
     441    }
     442
     443    unsigned entryIndex = m_table->keyCount + 2;
     444    m_table->entryIndices[i & m_table->sizeMask] = entryIndex;
     445    m_table->entries()[entryIndex - 1] = entry;
     446
     447    propertyStorage[entryIndex - 1] = value;
     448
     449    ++m_table->keyCount;
     450}
     451
     452void PropertyMap::expand(PropertyStorage& propertyStorage)
     453{
     454    if (!m_table)
     455        createTable(propertyStorage);
     456    else
     457        rehash(m_table->size * 2, propertyStorage);
     458}
     459
     460void PropertyMap::rehash(PropertyStorage& propertyStorage)
     461{
     462    ASSERT(m_table);
     463    ASSERT(m_table->size);
     464    rehash(m_table->size, propertyStorage);
     465}
     466
     467void PropertyMap::createTable(PropertyStorage& propertyStorage)
     468{
     469    const unsigned newTableSize = 16;
     470
     471    ASSERT(!m_table);
     472
     473    checkConsistency(propertyStorage);
     474
     475    m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
     476    m_table->size = newTableSize;
     477    m_table->sizeMask = newTableSize - 1;
     478
     479    propertyStorage.set(new JSValue*[m_table->size]);
     480
     481    checkConsistency(propertyStorage);
     482}
     483
     484void PropertyMap::rehash(unsigned newTableSize, PropertyStorage& propertyStorage)
     485{
     486    ASSERT(m_table);
     487
     488    checkConsistency(propertyStorage);
     489
     490    Table* oldTable = m_table;
     491    JSValue** oldPropertStorage = propertyStorage.release();
     492
     493    m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
     494    m_table->size = newTableSize;
     495    m_table->sizeMask = newTableSize - 1;
     496
     497    propertyStorage.set(new JSValue*[m_table->size]);
     498
     499    unsigned lastIndexUsed = 0;
     500    unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
     501    for (unsigned i = 1; i <= entryCount; ++i) {
     502        if (oldTable->entries()[i].key) {
     503            lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
     504            insert(oldTable->entries()[i], oldPropertStorage[i], propertyStorage);
     505        }
     506    }
     507    m_table->lastIndexUsed = lastIndexUsed;
     508
     509    fastFree(oldTable);
     510    delete [] oldPropertStorage;
     511
     512    checkConsistency(propertyStorage);
     513}
     514
     515void PropertyMap::resizePropertyStorage(PropertyStorage& propertyStorage, unsigned oldSize)
     516{
     517    ASSERT(m_table);
     518
     519    if (propertyStorage) {
     520        JSValue** oldPropertStorage = propertyStorage.release();
     521        propertyStorage.set(new JSValue*[m_table->size]);
     522
     523        // FIXME: this can probalby use memcpy
     524        for (unsigned i = 1; i <= oldSize; ++i)
     525            propertyStorage[i] = oldPropertStorage[i];
     526
     527        delete [] oldPropertStorage;
     528    } else
     529        propertyStorage.set(new JSValue*[m_table->size]);
    666530
    667531    checkConsistency(propertyStorage);
Note: See TracChangeset for help on using the changeset viewer.