Changeset 34204 in webkit


Ignore:
Timestamp:
May 29, 2008 10:14:02 AM (16 years ago)
Author:
ap@webkit.org
Message:

Reviewed by Darin.

https://bugs.webkit.org/show_bug.cgi?id=19294
<rdar://problem/5969062> A crash when iterating over a sparse array backwards.

  • kjs/array_instance.cpp: Turned sparseArrayCutoff into a macro, so that using max() on it doesn't cause a PIC branch. (KJS::ArrayInstance::increaseVectorLength): Added a comment about this function not preserving class invariants. (KJS::ArrayInstance::put): Update m_storage after reallocation. Move values that fit to the vector from the map in all code paths.
Location:
trunk
Files:
3 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r34198 r34204  
     12008-05-29  Alexey Proskuryakov  <ap@webkit.org>
     2
     3        Reviewed by Darin.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=19294
     6        <rdar://problem/5969062> A crash when iterating over a sparse array backwards.
     7
     8        * kjs/array_instance.cpp: Turned sparseArrayCutoff into a macro, so that using max() on it
     9        doesn't cause a PIC branch.
     10        (KJS::ArrayInstance::increaseVectorLength): Added a comment about this function not
     11        preserving class invariants.
     12        (KJS::ArrayInstance::put): Update m_storage after reallocation. Move values that fit to
     13        the vector from the map in all code paths.
     14
    1152008-05-29  Thiago Macieira  <tjmaciei@trolltech.com>
    216
  • trunk/JavaScriptCore/kjs/array_instance.cpp

    r34118 r34204  
    4848// When indices greater than sparseArrayCutoff are involved, we use a vector
    4949// as long as it is 1/8 full. If more sparse than that, we use a map.
    50 static const unsigned sparseArrayCutoff = 10000;
     50// This value has to be a macro to be used in max() and min() without introducing
     51// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
     52#define sparseArrayCutoff 10000U
    5153static const unsigned minDensityMultiplier = 8;
    5254
     
    227229    }
    228230
    229     if (i < sparseArrayCutoff) {
     231    SparseArrayValueMap* map = storage->m_sparseValueMap;
     232
     233    if (i >= sparseArrayCutoff) {
     234        // We miss some cases where we could compact the storage, such as a large array that is being filled from the end
     235        // (which will only be compacted as we reach indices that are less than cutoff) - but this makes the check much faster.
     236        if (!isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {
     237            if (!map) {
     238                map = new SparseArrayValueMap;
     239                storage->m_sparseValueMap = map;
     240            }
     241            map->set(i, value);
     242            return;
     243        }
     244    }
     245
     246    // We have decided that we'll put the new item into the vector.
     247    // Fast case is when there is no sparse map, so we can increase the vector size without moving values from it.
     248    if (!map || map->isEmpty()) {
    230249        increaseVectorLength(i + 1);
    231250        storage = m_storage;
     
    235254    }
    236255
    237     SparseArrayValueMap* map = storage->m_sparseValueMap;
    238     if (!map || map->isEmpty()) {
    239         if (isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {
    240             increaseVectorLength(i + 1);
    241             storage = m_storage;
    242             ++storage->m_numValuesInVector;
    243             storage->m_vector[i] = value;
    244             return;
    245         }
    246         if (!map) {
    247             map = new SparseArrayValueMap;
    248             storage->m_sparseValueMap = map;
    249         }
    250         map->set(i, value);
    251         return;
    252     }
    253 
     256    // Decide how many values it would be best to move from the map.
    254257    unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
    255     if (!isDenseEnoughForVector(i + 1, newNumValuesInVector)) {
    256         map->set(i, value);
    257         return;
    258     }
    259 
    260258    unsigned newVectorLength = increasedVectorLength(i + 1);
    261     for (unsigned j = m_vectorLength; j < newVectorLength; ++j)
     259    for (unsigned j = max(m_vectorLength, sparseArrayCutoff); j < newVectorLength; ++j)
    262260        newNumValuesInVector += map->contains(j);
    263     newNumValuesInVector -= map->contains(i);
     261    if (i >= sparseArrayCutoff)
     262        newNumValuesInVector -= map->contains(i);
    264263    if (isDenseEnoughForVector(newVectorLength, newNumValuesInVector)) {
    265264        unsigned proposedNewNumValuesInVector = newNumValuesInVector;
    266265        while (true) {
    267266            unsigned proposedNewVectorLength = increasedVectorLength(newVectorLength + 1);
    268             for (unsigned j = newVectorLength; j < proposedNewVectorLength; ++j)
     267            for (unsigned j = max(newVectorLength, sparseArrayCutoff); j < proposedNewVectorLength; ++j)
    269268                proposedNewNumValuesInVector += map->contains(j);
    270269            if (!isDenseEnoughForVector(proposedNewVectorLength, proposedNewNumValuesInVector))
     
    281280        for (unsigned j = vectorLength; j < newVectorLength; ++j)
    282281            storage->m_vector[j] = 0;
    283         map->remove(i);
     282        if (i > sparseArrayCutoff)
     283            map->remove(i);
    284284    } else {
    285         for (unsigned j = vectorLength; j < newVectorLength; ++j)
     285        for (unsigned j = vectorLength; j < max(vectorLength, sparseArrayCutoff); ++j)
     286            storage->m_vector[j] = 0;
     287        for (unsigned j = max(vectorLength, sparseArrayCutoff); j < newVectorLength; ++j)
    286288            storage->m_vector[j] = map->take(j);
    287289    }
     
    291293    m_vectorLength = newVectorLength;
    292294    storage->m_numValuesInVector = newNumValuesInVector;
     295
     296    m_storage = storage;
    293297}
    294298
     
    358362bool ArrayInstance::increaseVectorLength(unsigned newLength)
    359363{
     364    // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map
     365    // to the vector. Callers have to account for that, because they can do it more efficiently.
     366
    360367    ArrayStorage* storage = m_storage;
    361368
  • trunk/LayoutTests/ChangeLog

    r34197 r34204  
     12008-05-29  Alexey Proskuryakov  <ap@webkit.org>
     2
     3        Reviewed by Darin.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=19294
     6        <rdar://problem/5969062> A crash when iterating over a sparse array backwards.
     7
     8        * fast/js/array-iterate-backwards-expected.txt: Added.
     9        * fast/js/array-iterate-backwards.html: Added.
     10        * fast/js/resources/array-iterate-backwards.js: Added.
     11
    1122008-05-29  Alexey Proskuryakov  <ap@webkit.org>
    213
Note: See TracChangeset for help on using the changeset viewer.