Ignore:
Timestamp:
Oct 3, 2009, 10:01:14 AM (16 years ago)
Author:
[email protected]
Message:

Removed the concept of a "fast access cutoff" in arrays, because it
punished some patterns of array access too much, and made things too
complex for inlining in some cases.

Patch by Geoffrey Garen <[email protected]> on 2009-10-02
Reviewed by Sam Weinig.

1.3% speedup on SunSpider.

  • jit/JITOpcodes.cpp:

(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emitSlow_op_put_by_val):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):

  • jit/JITStubs.cpp:
  • jit/JITStubs.h:

(JSC::): Check m_vectorLength instead of m_fastAccessCutoff when
getting / putting from / to an array. Inline putting past the end of
the array.

  • runtime/JSArray.cpp:

(JSC::JSArray::JSArray):
(JSC::JSArray::getOwnPropertySlot):
(JSC::JSArray::getOwnPropertyDescriptor):
(JSC::JSArray::put):
(JSC::JSArray::putSlowCase):
(JSC::JSArray::deleteProperty):
(JSC::JSArray::getOwnPropertyNames):
(JSC::JSArray::increaseVectorLength):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::push):
(JSC::JSArray::sort):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToRegisters):
(JSC::JSArray::compactForSorting):
(JSC::JSArray::checkConsistency):

  • runtime/JSArray.h:

(JSC::JSArray::canGetIndex):
(JSC::JSArray::canSetIndex):
(JSC::JSArray::setIndex):
(JSC::JSArray::markChildrenDirect): Removed m_fastAccessCutoff, and
replaced with checks for JSValue() to detect reads and writes from / to
uninitialized parts of the array.

File:
1 edited

Legend:

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

    r48836 r49065  
    137137
    138138    m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
    139     m_storage->m_vectorLength = initialCapacity;
    140 
    141     m_fastAccessCutoff = 0;
     139    m_vectorLength = initialCapacity;
    142140
    143141    checkConsistency();
     
    151149    m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
    152150    m_storage->m_length = initialLength;
    153     m_storage->m_vectorLength = initialCapacity;
     151    m_vectorLength = initialCapacity;
    154152    m_storage->m_numValuesInVector = 0;
    155153    m_storage->m_sparseValueMap = 0;
     
    160158        vector[i] = JSValue();
    161159
    162     m_fastAccessCutoff = 0;
    163 
    164160    checkConsistency();
    165161
     
    174170    m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
    175171    m_storage->m_length = initialCapacity;
    176     m_storage->m_vectorLength = initialCapacity;
     172    m_vectorLength = initialCapacity;
    177173    m_storage->m_numValuesInVector = initialCapacity;
    178174    m_storage->m_sparseValueMap = 0;
     
    183179        m_storage->m_vector[i] = *it;
    184180
    185     m_fastAccessCutoff = initialCapacity;
    186 
    187181    checkConsistency();
    188182
     
    208202    }
    209203
    210     if (i < storage->m_vectorLength) {
     204    if (i < m_vectorLength) {
    211205        JSValue& valueSlot = storage->m_vector[i];
    212206        if (valueSlot) {
     
    254248        if (i >= m_storage->m_length)
    255249            return false;
    256         if (i < m_storage->m_vectorLength) {
    257             JSValue value = m_storage->m_vector[i];
     250        if (i < m_vectorLength) {
     251            JSValue& value = m_storage->m_vector[i];
    258252            if (value) {
    259253                descriptor.setDescriptor(value, 0);
     
    306300    }
    307301
    308     if (i < m_storage->m_vectorLength) {
     302    if (i < m_vectorLength) {
    309303        JSValue& valueSlot = m_storage->m_vector[i];
    310304        if (valueSlot) {
     
    314308        }
    315309        valueSlot = value;
    316         if (++m_storage->m_numValuesInVector == m_storage->m_length)
    317             m_fastAccessCutoff = m_storage->m_length;
     310        ++m_storage->m_numValuesInVector;
    318311        checkConsistency();
    319312        return;
     
    353346            storage = m_storage;
    354347            storage->m_vector[i] = value;
    355             if (++storage->m_numValuesInVector == storage->m_length)
    356                 m_fastAccessCutoff = storage->m_length;
     348            ++storage->m_numValuesInVector;
    357349            checkConsistency();
    358350        } else
     
    364356    unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
    365357    unsigned newVectorLength = increasedVectorLength(i + 1);
    366     for (unsigned j = max(storage->m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
     358    for (unsigned j = max(m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
    367359        newNumValuesInVector += map->contains(j);
    368360    if (i >= MIN_SPARSE_ARRAY_INDEX)
     
    387379    }
    388380
    389     unsigned vectorLength = storage->m_vectorLength;
     381    unsigned vectorLength = m_vectorLength;
    390382
    391383    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
     
    405397    storage->m_vector[i] = value;
    406398
    407     storage->m_vectorLength = newVectorLength;
     399    m_vectorLength = newVectorLength;
    408400    storage->m_numValuesInVector = newNumValuesInVector;
    409401
     
    432424    ArrayStorage* storage = m_storage;
    433425
    434     if (i < storage->m_vectorLength) {
     426    if (i < m_vectorLength) {
    435427        JSValue& valueSlot = storage->m_vector[i];
    436428        if (!valueSlot) {
     
    440432        valueSlot = JSValue();
    441433        --storage->m_numValuesInVector;
    442         if (m_fastAccessCutoff > i)
    443             m_fastAccessCutoff = i;
    444434        checkConsistency();
    445435        return true;
     
    473463    ArrayStorage* storage = m_storage;
    474464
    475     unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
     465    unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
    476466    for (unsigned i = 0; i < usedVectorLength; ++i) {
    477467        if (storage->m_vector[i])
     
    495485    ArrayStorage* storage = m_storage;
    496486
    497     unsigned vectorLength = storage->m_vectorLength;
     487    unsigned vectorLength = m_vectorLength;
    498488    ASSERT(newLength > vectorLength);
    499489    ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
     
    504494
    505495    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
    506     storage->m_vectorLength = newVectorLength;
     496    m_vectorLength = newVectorLength;
    507497
    508498    for (unsigned i = vectorLength; i < newVectorLength; ++i)
     
    522512
    523513    if (newLength < length) {
    524         if (m_fastAccessCutoff > newLength)
    525             m_fastAccessCutoff = newLength;
    526 
    527         unsigned usedVectorLength = min(length, storage->m_vectorLength);
     514        unsigned usedVectorLength = min(length, m_vectorLength);
    528515        for (unsigned i = newLength; i < usedVectorLength; ++i) {
    529516            JSValue& valueSlot = storage->m_vector[i];
     
    564551    JSValue result;
    565552
    566     if (m_fastAccessCutoff > length) {
     553    if (length < m_vectorLength) {
    567554        JSValue& valueSlot = m_storage->m_vector[length];
    568         result = valueSlot;
    569         ASSERT(result);
    570         valueSlot = JSValue();
    571         --m_storage->m_numValuesInVector;
    572         m_fastAccessCutoff = length;
    573     } else if (length < m_storage->m_vectorLength) {
    574         JSValue& valueSlot = m_storage->m_vector[length];
    575         result = valueSlot;
    576         valueSlot = JSValue();
    577         if (result)
     555        if (valueSlot) {
    578556            --m_storage->m_numValuesInVector;
    579         else
     557            result = valueSlot;
     558            valueSlot = JSValue();
     559        } else
    580560            result = jsUndefined();
    581561    } else {
     
    605585    checkConsistency();
    606586
    607     if (m_storage->m_length < m_storage->m_vectorLength) {
    608         ASSERT(!m_storage->m_vector[m_storage->m_length]);
     587    if (m_storage->m_length < m_vectorLength) {
    609588        m_storage->m_vector[m_storage->m_length] = value;
    610         if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
    611             m_fastAccessCutoff = m_storage->m_length;
     589        ++m_storage->m_numValuesInVector;
     590        ++m_storage->m_length;
    612591        checkConsistency();
    613592        return;
     
    619598            if (increaseVectorLength(m_storage->m_length + 1)) {
    620599                m_storage->m_vector[m_storage->m_length] = value;
    621                 if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
    622                     m_fastAccessCutoff = m_storage->m_length;
     600                ++m_storage->m_numValuesInVector;
     601                ++m_storage->m_length;
    623602                checkConsistency();
    624603                return;
     
    838817        return;
    839818
    840     unsigned usedVectorLength = min(m_storage->m_length, m_storage->m_vectorLength);
     819    unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
    841820
    842821    AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items
     
    887866    if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
    888867        newUsedVectorLength += map->size();
    889         if (newUsedVectorLength > m_storage->m_vectorLength) {
     868        if (newUsedVectorLength > m_vectorLength) {
    890869            // Check that it is possible to allocate an array large enough to hold all the entries.
    891870            if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {
     
    927906        m_storage->m_vector[i] = JSValue();
    928907
    929     m_fastAccessCutoff = newUsedVectorLength;
    930908    m_storage->m_numValuesInVector = newUsedVectorLength;
    931909
     
    935913void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
    936914{
    937     unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
     915    JSValue* vector = m_storage->m_vector;
     916    unsigned vectorEnd = min(m_storage->m_length, m_vectorLength);
    938917    unsigned i = 0;
    939     for (; i < fastAccessLength; ++i)
    940         args.append(getIndex(i));
     918    for (; i < vectorEnd; ++i) {
     919        JSValue& v = vector[i];
     920        if (!v)
     921            break;
     922        args.append(v);
     923    }
     924
    941925    for (; i < m_storage->m_length; ++i)
    942926        args.append(get(exec, i));
     
    947931    ASSERT(m_storage->m_length == maxSize);
    948932    UNUSED_PARAM(maxSize);
    949     unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
     933    JSValue* vector = m_storage->m_vector;
     934    unsigned vectorEnd = min(m_storage->m_length, m_vectorLength);
    950935    unsigned i = 0;
    951     for (; i < fastAccessLength; ++i)
    952         buffer[i] = getIndex(i);
    953     uint32_t size = m_storage->m_length;
    954     for (; i < size; ++i)
     936    for (; i < vectorEnd; ++i) {
     937        JSValue& v = vector[i];
     938        if (!v)
     939            break;
     940        buffer[i] = v;
     941    }
     942
     943    for (; i < m_storage->m_length; ++i)
    955944        buffer[i] = get(exec, i);
    956945}
     
    962951    ArrayStorage* storage = m_storage;
    963952
    964     unsigned usedVectorLength = min(m_storage->m_length, storage->m_vectorLength);
     953    unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
    965954
    966955    unsigned numDefined = 0;
     
    986975    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
    987976        newUsedVectorLength += map->size();
    988         if (newUsedVectorLength > storage->m_vectorLength) {
     977        if (newUsedVectorLength > m_vectorLength) {
    989978            // Check that it is possible to allocate an array large enough to hold all the entries - if not,
    990979            // exception is thrown by caller.
     
    1007996        storage->m_vector[i] = JSValue();
    1008997
    1009     m_fastAccessCutoff = newUsedVectorLength;
    1010998    storage->m_numValuesInVector = newUsedVectorLength;
    1011999
     
    10331021        ASSERT(!m_storage->m_sparseValueMap);
    10341022
    1035     ASSERT(m_fastAccessCutoff <= m_storage->m_length);
    1036     ASSERT(m_fastAccessCutoff <= m_storage->m_numValuesInVector);
    1037 
    10381023    unsigned numValuesInVector = 0;
    1039     for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) {
     1024    for (unsigned i = 0; i < m_vectorLength; ++i) {
    10401025        if (JSValue value = m_storage->m_vector[i]) {
    10411026            ASSERT(i < m_storage->m_length);
     
    10441029            ++numValuesInVector;
    10451030        } else {
    1046             ASSERT(i >= m_fastAccessCutoff);
    10471031            if (type == SortConsistencyCheck)
    10481032                ASSERT(i >= m_storage->m_numValuesInVector);
     
    10501034    }
    10511035    ASSERT(numValuesInVector == m_storage->m_numValuesInVector);
     1036    ASSERT(numValuesInVector <= m_storage->m_length);
    10521037
    10531038    if (m_storage->m_sparseValueMap) {
     
    10561041            unsigned index = it->first;
    10571042            ASSERT(index < m_storage->m_length);
    1058             ASSERT(index >= m_storage->m_vectorLength);
     1043            ASSERT(index >= m_vectorLength);
    10591044            ASSERT(index <= MAX_ARRAY_INDEX);
    10601045            ASSERT(it->second);
Note: See TracChangeset for help on using the changeset viewer.