Changeset 34867 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Jun 28, 2008, 8:56:04 PM (17 years ago)
Author:
Darin Adler
Message:

2008-06-28 Darin Adler <Darin Adler>

Reviewed by Cameron.

SunSpider says 1.8% faster.

  • kjs/JSArray.cpp: (KJS::JSArray::JSArray): Initialize m_fastAccessCutoff when creating arrays. Also updated for new location of m_vectorLength. (KJS::JSArray::getItem): Updated for new location of m_vectorLength. (KJS::JSArray::getSlowCase): Added. Broke out the non-hot parts of getOwnPropertySlot to make the hot part faster. (KJS::JSArray::getOwnPropertySlot): Added a new faster case for indices lower than m_fastAccessCutoff. We can do theese with no additional checks or branches. (KJS::JSArray::put): Added a new faster case for indices lower than m_fastAccessCutoff. We can do theese with no additional checks or branches. Moved the maxArrayIndex handling out of this function. Added code to set m_fastAccessCutoff when the very last hole in an array is filled; this is how the cutoff gets set for most arrays. (KJS::JSArray::putSlowCase): Moved the rest of the put function logic in here, to make the hot part of the put function faster. (KJS::JSArray::deleteProperty): Added code to lower m_fastAccessCutoff when a delete makes a new hole in the array. (KJS::JSArray::getPropertyNames): Updated for new location of m_vectorLength. (KJS::JSArray::increaseVectorLength): Ditto. (KJS::JSArray::setLength): Added code to lower m_fastAccessCutoff when setLength makes the array smaller. (KJS::JSArray::mark): Updated for new location of m_vectorLength. (KJS::JSArray::sort): Ditto. Set m_fastAccessCutoff after moving all the holes to the end of the array. (KJS::JSArray::compactForSorting): Ditto. (KJS::JSArray::checkConsistency): Added consistency checks fro m_fastAccessCutoff and updated for the new location of m_vectorLength.
  • kjs/JSArray.h: Added declarations for slow case functions. Replaced m_vectorLength with m_fastAccessCutoff.
Location:
trunk/JavaScriptCore/kjs
Files:
2 edited

Legend:

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

    r34843 r34867  
    3838
    3939struct ArrayStorage {
     40    unsigned m_vectorLength;
    4041    unsigned m_numValuesInVector;
    4142    SparseArrayValueMap* m_sparseValueMap;
     
    8788
    8889    m_length = initialLength;
    89     m_vectorLength = initialCapacity;
     90    m_fastAccessCutoff = 0;
    9091    m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
     92    m_storage->m_vectorLength = initialCapacity;
    9193
    9294    Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue*));
     
    101103
    102104    m_length = length;
    103     m_vectorLength = length;
     105    m_fastAccessCutoff = length;
    104106
    105107    ArrayStorage* storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(length)));
    106108
     109    storage->m_vectorLength = length;
    107110    storage->m_numValuesInVector = length;
    108111    storage->m_sparseValueMap = 0;
     
    135138    ArrayStorage* storage = m_storage;
    136139
    137     if (i < m_vectorLength) {
     140    if (i < storage->m_vectorLength) {
    138141        JSValue* value = storage->m_vector[i];
    139142        return value ? value : jsUndefined();
     
    153156}
    154157
    155 ALWAYS_INLINE bool JSArray::inlineGetOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
     158NEVER_INLINE bool JSArray::getOwnPropertySlotSlowCase(ExecState* exec, unsigned i, PropertySlot& slot)
    156159{
    157160    ArrayStorage* storage = m_storage;
    158161
    159     if (UNLIKELY(i >= m_length)) {
     162    if (i >= m_length) {
    160163        if (i > maxArrayIndex)
    161164            return getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
     
    163166    }
    164167
    165     if (i < m_vectorLength) {
     168    if (i < storage->m_vectorLength) {
    166169        JSValue*& valueSlot = storage->m_vector[i];
    167170        if (valueSlot) {
     
    192195    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
    193196    if (isArrayIndex)
    194         return inlineGetOwnPropertySlot(exec, i, slot);
     197        return JSArray::getOwnPropertySlot(exec, i, slot);
    195198
    196199    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
     
    199202bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
    200203{
    201     return inlineGetOwnPropertySlot(exec, i, slot);
     204    if (i < m_fastAccessCutoff) {
     205        slot.setValueSlot(&m_storage->m_vector[i]);
     206        return true;
     207    }
     208
     209    return getOwnPropertySlotSlowCase(exec, i, slot);
    202210}
    203211
     
    229237    checkConsistency();
    230238
     239    if (i < m_fastAccessCutoff) {
     240        m_storage->m_vector[i] = value;
     241        checkConsistency();
     242        return;
     243    }
     244
    231245    unsigned length = m_length;
    232     if (i >= length) {
     246    if (i >= length && i <= maxArrayIndex) {
     247        length = i + 1;
     248        m_length = length;
     249    }
     250
     251    if (i < m_storage->m_vectorLength) {
     252        JSValue*& valueSlot = m_storage->m_vector[i];
     253        if (valueSlot) {
     254            valueSlot = value;
     255            checkConsistency();
     256            return;
     257        }
     258        valueSlot = value;
     259        if (++m_storage->m_numValuesInVector == m_length)
     260            m_fastAccessCutoff = m_length;
     261        checkConsistency();
     262        return;
     263    }
     264
     265    putSlowCase(exec, i, value);
     266}
     267
     268NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue* value)
     269{
     270    ArrayStorage* storage = m_storage;
     271    SparseArrayValueMap* map = storage->m_sparseValueMap;
     272
     273    if (i >= sparseArrayCutoff) {
    233274        if (i > maxArrayIndex) {
    234275            put(exec, Identifier::from(exec, i), value);
    235276            return;
    236277        }
    237         length = i + 1;
    238         m_length = length;
    239     }
    240 
    241     ArrayStorage* storage = m_storage;
    242 
    243     if (i < m_vectorLength) {
    244         JSValue*& valueSlot = storage->m_vector[i];
    245         storage->m_numValuesInVector += !valueSlot;
    246         valueSlot = value;
    247         checkConsistency();
    248         return;
    249     }
    250 
    251     SparseArrayValueMap* map = storage->m_sparseValueMap;
    252 
    253     if (i >= sparseArrayCutoff) {
     278
    254279        // We miss some cases where we could compact the storage, such as a large array that is being filled from the end
    255280        // (which will only be compacted as we reach indices that are less than cutoff) - but this makes the check much faster.
     
    278303    unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
    279304    unsigned newVectorLength = increasedVectorLength(i + 1);
    280     for (unsigned j = max(m_vectorLength, sparseArrayCutoff); j < newVectorLength; ++j)
     305    for (unsigned j = max(storage->m_vectorLength, sparseArrayCutoff); j < newVectorLength; ++j)
    281306        newNumValuesInVector += map->contains(j);
    282307    if (i >= sparseArrayCutoff)
     
    297322    storage = static_cast<ArrayStorage*>(fastRealloc(storage, storageSize(newVectorLength)));
    298323
    299     unsigned vectorLength = m_vectorLength;
     324    unsigned vectorLength = storage->m_vectorLength;
    300325    if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
    301326        for (unsigned j = vectorLength; j < newVectorLength; ++j)
     
    312337    storage->m_vector[i] = value;
    313338
    314     m_vectorLength = newVectorLength;
     339    storage->m_vectorLength = newVectorLength;
    315340    storage->m_numValuesInVector = newNumValuesInVector;
    316341
     
    339364    ArrayStorage* storage = m_storage;
    340365
    341     if (i < m_vectorLength) {
     366    if (i < storage->m_vectorLength) {
    342367        JSValue*& valueSlot = storage->m_vector[i];
    343         bool hadValue = valueSlot;
     368        if (!valueSlot) {
     369            checkConsistency();
     370            return false;
     371        }
    344372        valueSlot = 0;
    345         storage->m_numValuesInVector -= hadValue;
     373        --storage->m_numValuesInVector;
     374        if (m_fastAccessCutoff > i)
     375            m_fastAccessCutoff = i;
    346376        checkConsistency();
    347         return hadValue;
     377        return true;
    348378    }
    349379
     
    375405    ArrayStorage* storage = m_storage;
    376406
    377     unsigned usedVectorLength = min(m_length, m_vectorLength);
     407    unsigned usedVectorLength = min(m_length, storage->m_vectorLength);
    378408    for (unsigned i = 0; i < usedVectorLength; ++i) {
    379409        if (storage->m_vector[i])
     
    397427    ArrayStorage* storage = m_storage;
    398428
    399     unsigned vectorLength = m_vectorLength;
     429    unsigned vectorLength = storage->m_vectorLength;
    400430    ASSERT(newLength > vectorLength);
    401431    unsigned newVectorLength = increasedVectorLength(newLength);
     
    405435        return false;
    406436
    407     m_vectorLength = newVectorLength;
     437    storage->m_vectorLength = newVectorLength;
    408438
    409439    for (unsigned i = vectorLength; i < newVectorLength; ++i)
     
    423453
    424454    if (newLength < length) {
    425         unsigned usedVectorLength = min(length, m_vectorLength);
     455        if (m_fastAccessCutoff > newLength)
     456            m_fastAccessCutoff = newLength;
     457
     458        unsigned usedVectorLength = min(length, storage->m_vectorLength);
    426459        for (unsigned i = newLength; i < usedVectorLength; ++i) {
    427460            JSValue*& valueSlot = storage->m_vector[i];
     
    456489    ArrayStorage* storage = m_storage;
    457490
    458     unsigned usedVectorLength = min(m_length, m_vectorLength);
     491    unsigned usedVectorLength = min(m_length, storage->m_vectorLength);
    459492    for (unsigned i = 0; i < usedVectorLength; ++i) {
    460493        JSValue* value = storage->m_vector[i];
     
    626659        return;
    627660
    628     unsigned usedVectorLength = min(m_length, m_vectorLength);
     661    unsigned usedVectorLength = min(m_length, m_storage->m_vectorLength);
    629662
    630663    AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items
     
    671704    if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
    672705        newUsedVectorLength += map->size();
    673         if (newUsedVectorLength > m_vectorLength) {
     706        if (newUsedVectorLength > m_storage->m_vectorLength) {
    674707            if (!increaseVectorLength(newUsedVectorLength)) {
    675708                exec->setException(Error::create(exec, GeneralError, "Out of memory"));
     
    710743        m_storage->m_vector[i] = 0;
    711744
     745    m_fastAccessCutoff = newUsedVectorLength;
    712746    m_storage->m_numValuesInVector = newUsedVectorLength;
    713747
     
    721755    ArrayStorage* storage = m_storage;
    722756
    723     unsigned usedVectorLength = min(m_length, m_vectorLength);
     757    unsigned usedVectorLength = min(m_length, storage->m_vectorLength);
    724758
    725759    unsigned numDefined = 0;
     
    744778    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
    745779        newUsedVectorLength += map->size();
    746         if (newUsedVectorLength > m_vectorLength) {
     780        if (newUsedVectorLength > storage->m_vectorLength) {
    747781            if (!increaseVectorLength(newUsedVectorLength))
    748782                return 0;
     
    763797        storage->m_vector[i] = 0;
    764798
     799    m_fastAccessCutoff = newUsedVectorLength;
    765800    storage->m_numValuesInVector = newUsedVectorLength;
    766801
     
    788823        ASSERT(!m_storage->m_sparseValueMap);
    789824
     825    ASSERT(m_fastAccessCutoff <= m_length);
     826    ASSERT(m_fastAccessCutoff <= m_storage->m_numValuesInVector);
     827
    790828    unsigned numValuesInVector = 0;
    791     for (unsigned i = 0; i < m_vectorLength; ++i) {
     829    for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) {
    792830        if (JSValue* value = m_storage->m_vector[i]) {
    793831            ASSERT(i < m_length);
     
    796834            ++numValuesInVector;
    797835        } else {
     836            ASSERT(i >= m_fastAccessCutoff);
    798837            if (type == SortConsistencyCheck)
    799838                ASSERT(i >= m_storage->m_numValuesInVector);
     
    807846            unsigned index = it->first;
    808847            ASSERT(index < m_length);
    809             ASSERT(index >= m_vectorLength);
     848            ASSERT(index >= m_storage->m_vectorLength);
    810849            ASSERT(index <= maxArrayIndex);
    811850            ASSERT(it->second);
  • trunk/JavaScriptCore/kjs/JSArray.h

    r34754 r34867  
    6464
    6565    static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
    66     bool inlineGetOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     66
     67    bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
     68    void putSlowCase(ExecState*, unsigned propertyName, JSValue*);
    6769
    6870    bool increaseVectorLength(unsigned newLength);
     
    7476
    7577    unsigned m_length;
    76     unsigned m_vectorLength;
     78    unsigned m_fastAccessCutoff;
    7779    ArrayStorage* m_storage;
    7880  };
Note: See TracChangeset for help on using the changeset viewer.