Ignore:
Timestamp:
Sep 9, 2013, 3:41:00 PM (12 years ago)
Author:
[email protected]
Message:

JSArray::shiftCountWithArrayStorage doesn't change indexBias when shifting the last element in m_vector
https://bugs.webkit.org/show_bug.cgi?id=120389

Reviewed by Michael Saboff.

Went through and cleaned up shiftCountWithArrayStorage. Gave meaningful variable names
and commented the confusing parts. This led to realizing how to fix this bug, which has
been done. The issue was that we were modifying the vector length unconditionally, even
when we weren't logically changing the length of the vector. Instead, we should only modify
the vector length when we modify the index bias.

  • runtime/JSArray.cpp:

(JSC::JSArray::shiftCountWithArrayStorage):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSArray.cpp

    r155143 r155395  
    701701    unsigned usedVectorLength = min(vectorLength, oldLength);
    702702   
    703     vectorLength -= count;
    704     storage->setVectorLength(vectorLength);
    705    
    706     if (vectorLength) {
    707         if (startIndex < usedVectorLength - (startIndex + count)) {
    708             if (startIndex) {
    709                 memmove(
    710                     storage->m_vector + count,
    711                     storage->m_vector,
    712                     sizeof(JSValue) * startIndex);
    713             }
    714             m_butterfly = m_butterfly->shift(structure(), count);
    715             storage = m_butterfly->arrayStorage();
    716             storage->m_indexBias += count;
    717         } else {
     703    unsigned numElementsBeforeShiftRegion = startIndex;
     704    unsigned firstIndexAfterShiftRegion = startIndex + count;
     705    unsigned numElementsAfterShiftRegion = usedVectorLength - firstIndexAfterShiftRegion;
     706    ASSERT(numElementsBeforeShiftRegion + count + numElementsAfterShiftRegion == usedVectorLength);
     707
     708    // The point of this comparison seems to be to minimize the amount of elements that have to
     709    // be moved during a shift operation.
     710    if (numElementsBeforeShiftRegion < numElementsAfterShiftRegion) {
     711        // The number of elements before the shift region is less than the number of elements
     712        // after the shift region, so we move the elements before to the right.
     713        if (numElementsBeforeShiftRegion) {
     714            RELEASE_ASSERT(count + startIndex <= vectorLength);
    718715            memmove(
    719                 storage->m_vector + startIndex,
    720                 storage->m_vector + startIndex + count,
    721                 sizeof(JSValue) * (usedVectorLength - (startIndex + count)));
    722             for (unsigned i = usedVectorLength - count; i < usedVectorLength; ++i)
    723                 storage->m_vector[i].clear();
    724         }
    725     }
     716                storage->m_vector + count,
     717                storage->m_vector,
     718                sizeof(JSValue) * startIndex);
     719        }
     720        // Adjust the Butterfly and the index bias. We only need to do this here because we're changing
     721        // the start of the Butterfly, which needs to point at the first indexed property in the used
     722        // portion of the vector.
     723        m_butterfly = m_butterfly->shift(structure(), count);
     724        storage = m_butterfly->arrayStorage();
     725        storage->m_indexBias += count;
     726
     727        // Since we're consuming part of the vector by moving its beginning to the left,
     728        // we need to modify the vector length appropriately.
     729        storage->setVectorLength(vectorLength - count);
     730    } else {
     731        // The number of elements before the shift region is greater than or equal to the number
     732        // of elements after the shift region, so we move the elements after the shift region to the left.
     733        memmove(
     734            storage->m_vector + startIndex,
     735            storage->m_vector + firstIndexAfterShiftRegion,
     736            sizeof(JSValue) * numElementsAfterShiftRegion);
     737        // Clear the slots of the elements we just moved.
     738        unsigned startOfEmptyVectorTail = usedVectorLength - count;
     739        for (unsigned i = startOfEmptyVectorTail; i < usedVectorLength; ++i)
     740            storage->m_vector[i].clear();
     741        // We don't modify the index bias or the Butterfly pointer in this case because we're not changing
     742        // the start of the Butterfly, which needs to point at the first indexed property in the used
     743        // portion of the vector. We also don't modify the vector length because we're not actually changing
     744        // its length; we're just using less of it.
     745    }
     746   
    726747    return true;
    727748}
Note: See TracChangeset for help on using the changeset viewer.