Changeset 64320 in webkit for trunk/JavaScriptCore/runtime/JSArray.cpp
- Timestamp:
- Jul 29, 2010, 4:29:17 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/JSArray.cpp
r64184 r64320 79 79 #define MAX_ARRAY_INDEX 0xFFFFFFFEU 80 80 81 // The value BASE_VECTOR_LEN is the maximum number of vector elements we'll allocate 82 // for an array that was created with a sepcified length (e.g. a = new Array(123)) 83 #define BASE_VECTOR_LEN 4U 84 85 // The upper bound to the size we'll grow a zero length array when the first element 86 // is added. 87 #define FIRST_VECTOR_GROW 4U 88 81 89 // Our policy for when to use a vector and when to use a sparse map. 82 90 // For all array indices under MIN_SPARSE_ARRAY_INDEX, we always use a vector. … … 86 94 87 95 const ClassInfo JSArray::info = {"Array", 0, 0, 0}; 96 97 // We keep track of the size of the last array after it was grown. We use this 98 // as a simple heuristic for as the value to grow the next array from size 0. 99 // This value is capped by the constant FIRST_VECTOR_GROW defined above. 100 static unsigned lastArraySize = 0; 88 101 89 102 static inline size_t storageSize(unsigned vectorLength) … … 101 114 } 102 115 103 static inline unsigned increasedVectorLength(unsigned newLength)104 {105 ASSERT(newLength <= MAX_STORAGE_VECTOR_LENGTH);106 107 // Mathematically equivalent to:108 // increasedLength = (newLength * 3 + 1) / 2;109 // or:110 // increasedLength = (unsigned)ceil(newLength * 1.5));111 // This form is not prone to internal overflow.112 unsigned increasedLength = newLength + (newLength >> 1) + (newLength & 1);113 ASSERT(increasedLength >= newLength);114 115 return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);116 }117 118 116 static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues) 119 117 { … … 134 132 unsigned initialCapacity = 0; 135 133 136 m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity))); 134 ArrayStorage* storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity))); 135 m_indexBias = 0; 136 setArrayStorage(storage); 137 137 m_vectorLength = initialCapacity; 138 138 … … 147 147 initialCapacity = initialLength; 148 148 else 149 initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX); 150 151 m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity))); 149 initialCapacity = min(BASE_VECTOR_LEN, MIN_SPARSE_ARRAY_INDEX); 150 151 ArrayStorage* storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity))); 152 storage->m_length = initialLength; 153 m_indexBias = 0; 152 154 m_vectorLength = initialCapacity; 153 m_storage->m_sparseValueMap = 0; 154 m_storage->subclassData = 0; 155 m_storage->reportedMapCapacity = 0; 155 setArrayStorage(storage); 156 storage->m_sparseValueMap = 0; 157 storage->subclassData = 0; 158 storage->reportedMapCapacity = 0; 156 159 157 160 if (creationMode == CreateCompact) { 158 161 #if CHECK_ARRAY_CONSISTENCY 159 m_storage->m_inCompactInitialization = !!initialCapacity;162 storage->m_inCompactInitialization = !!initialCapacity; 160 163 #endif 161 m_storage->m_length = 0;162 m_storage->m_numValuesInVector = initialCapacity;164 storage->m_length = 0; 165 storage->m_numValuesInVector = initialCapacity; 163 166 } else { 164 167 #if CHECK_ARRAY_CONSISTENCY 165 m_storage->m_inCompactInitialization = false;168 storage->m_inCompactInitialization = false; 166 169 #endif 167 m_storage->m_length = initialLength;168 m_storage->m_numValuesInVector = 0;169 JSValue* vector = m_ storage->m_vector;170 storage->m_length = initialLength; 171 storage->m_numValuesInVector = 0; 172 JSValue* vector = m_vector; 170 173 for (size_t i = 0; i < initialCapacity; ++i) 171 174 vector[i] = JSValue(); … … 173 176 174 177 checkConsistency(); 175 178 176 179 Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue)); 177 180 } … … 182 185 unsigned initialCapacity = list.size(); 183 186 184 m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity))); 185 m_storage->m_length = initialCapacity; 187 ArrayStorage* storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity))); 188 m_indexBias = 0; 189 storage->m_length = initialCapacity; 186 190 m_vectorLength = initialCapacity; 187 m_storage->m_numValuesInVector = initialCapacity;188 m_storage->m_sparseValueMap = 0;189 m_storage->subclassData = 0;190 m_storage->reportedMapCapacity = 0;191 storage->m_numValuesInVector = initialCapacity; 192 storage->m_sparseValueMap = 0; 193 storage->subclassData = 0; 194 storage->reportedMapCapacity = 0; 191 195 #if CHECK_ARRAY_CONSISTENCY 192 m_storage->m_inCompactInitialization = false;196 storage->m_inCompactInitialization = false; 193 197 #endif 198 setArrayStorage(storage); 194 199 195 200 size_t i = 0; 201 JSValue* vector = m_vector; 196 202 ArgList::const_iterator end = list.end(); 197 203 for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i) 198 m_storage->m_vector[i] = *it;204 vector[i] = *it; 199 205 200 206 checkConsistency(); … … 208 214 checkConsistency(DestructorConsistencyCheck); 209 215 210 delete m_storage->m_sparseValueMap; 211 fastFree(m_storage); 216 ArrayStorage* storage = arrayStorage(); 217 delete storage->m_sparseValueMap; 218 char* realStorage = reinterpret_cast<char*>(storage) - (m_indexBias * sizeof(JSValue)); 219 fastFree(realStorage); 212 220 } 213 221 214 222 bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot) 215 223 { 216 ArrayStorage* storage = m_storage;217 224 ArrayStorage* storage = arrayStorage(); 225 218 226 if (i >= storage->m_length) { 219 227 if (i > MAX_ARRAY_INDEX) … … 223 231 224 232 if (i < m_vectorLength) { 225 JSValue& valueSlot = storage->m_vector[i];233 JSValue& valueSlot = m_vector[i]; 226 234 if (valueSlot) { 227 235 slot.setValueSlot(&valueSlot); … … 262 270 return true; 263 271 } 272 273 ArrayStorage* storage = arrayStorage(); 264 274 265 275 bool isArrayIndex; 266 276 unsigned i = propertyName.toArrayIndex(&isArrayIndex); 267 277 if (isArrayIndex) { 268 if (i >= m_storage->m_length)278 if (i >= storage->m_length) 269 279 return false; 270 280 if (i < m_vectorLength) { 271 JSValue& value = m_ storage->m_vector[i];281 JSValue& value = m_vector[i]; 272 282 if (value) { 273 283 descriptor.setDescriptor(value, 0); 274 284 return true; 275 285 } 276 } else if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {286 } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) { 277 287 if (i >= MIN_SPARSE_ARRAY_INDEX) { 278 288 SparseArrayValueMap::iterator it = map->find(i); … … 314 324 checkConsistency(); 315 325 316 unsigned length = m_storage->m_length; 326 ArrayStorage* storage = arrayStorage(); 327 328 unsigned length = storage->m_length; 317 329 if (i >= length && i <= MAX_ARRAY_INDEX) { 318 330 length = i + 1; 319 m_storage->m_length = length;331 storage->m_length = length; 320 332 } 321 333 322 334 if (i < m_vectorLength) { 323 JSValue& valueSlot = m_ storage->m_vector[i];335 JSValue& valueSlot = m_vector[i]; 324 336 if (valueSlot) { 325 337 valueSlot = value; … … 328 340 } 329 341 valueSlot = value; 330 ++ m_storage->m_numValuesInVector;342 ++storage->m_numValuesInVector; 331 343 checkConsistency(); 332 344 return; … … 338 350 NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue value) 339 351 { 340 ArrayStorage* storage = m_storage; 352 ArrayStorage* storage = arrayStorage(); 353 341 354 SparseArrayValueMap* map = storage->m_sparseValueMap; 342 355 … … 375 388 if (!map || map->isEmpty()) { 376 389 if (increaseVectorLength(i + 1)) { 377 storage = m_storage; 378 storage->m_vector[i] = value; 379 ++storage->m_numValuesInVector; 390 m_vector[i] = value; 391 ++arrayStorage()->m_numValuesInVector; 380 392 checkConsistency(); 381 393 } else … … 386 398 // Decide how many values it would be best to move from the map. 387 399 unsigned newNumValuesInVector = storage->m_numValuesInVector + 1; 388 unsigned newVectorLength = increasedVectorLength(i + 1);400 unsigned newVectorLength = getNewVectorLength(i + 1); 389 401 for (unsigned j = max(m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j) 390 402 newNumValuesInVector += map->contains(j); … … 395 407 // If newVectorLength is already the maximum - MAX_STORAGE_VECTOR_LENGTH - then do not attempt to grow any further. 396 408 while (newVectorLength < MAX_STORAGE_VECTOR_LENGTH) { 397 unsigned proposedNewVectorLength = increasedVectorLength(newVectorLength + 1);409 unsigned proposedNewVectorLength = getNewVectorLength(newVectorLength + 1); 398 410 for (unsigned j = max(newVectorLength, MIN_SPARSE_ARRAY_INDEX); j < proposedNewVectorLength; ++j) 399 411 proposedNewNumValuesInVector += map->contains(j); … … 405 417 } 406 418 407 if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage)) { 419 int baseBias = m_indexBias * sizeof(JSValue); 420 char* baseStorage = reinterpret_cast<char*>(storage - baseBias); 421 422 if (!tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) { 408 423 throwOutOfMemoryError(exec); 409 424 return; 410 425 } 411 426 427 storage = reinterpret_cast<ArrayStorage*>(baseStorage + baseBias); 428 setArrayStorage(storage); 429 412 430 unsigned vectorLength = m_vectorLength; 413 431 414 432 if (newNumValuesInVector == storage->m_numValuesInVector + 1) { 415 433 for (unsigned j = vectorLength; j < newVectorLength; ++j) 416 storage->m_vector[j] = JSValue();434 m_vector[j] = JSValue(); 417 435 if (i > MIN_SPARSE_ARRAY_INDEX) 418 436 map->remove(i); 419 437 } else { 420 438 for (unsigned j = vectorLength; j < max(vectorLength, MIN_SPARSE_ARRAY_INDEX); ++j) 421 storage->m_vector[j] = JSValue();439 m_vector[j] = JSValue(); 422 440 for (unsigned j = max(vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j) 423 storage->m_vector[j] = map->take(j);424 } 425 426 storage->m_vector[i] = value;441 m_vector[j] = map->take(j); 442 } 443 444 ASSERT(i < newVectorLength); 427 445 428 446 m_vectorLength = newVectorLength; 429 447 storage->m_numValuesInVector = newNumValuesInVector; 430 448 431 m_ storage = storage;449 m_vector[i] = value; 432 450 433 451 checkConsistency(); … … 453 471 checkConsistency(); 454 472 455 ArrayStorage* storage = m_storage;456 473 ArrayStorage* storage = arrayStorage(); 474 457 475 if (i < m_vectorLength) { 458 JSValue& valueSlot = storage->m_vector[i];476 JSValue& valueSlot = m_vector[i]; 459 477 if (!valueSlot) { 460 478 checkConsistency(); … … 492 510 // which almost certainly means a different structure for PropertyNameArray. 493 511 494 ArrayStorage* storage = m_storage;495 512 ArrayStorage* storage = arrayStorage(); 513 496 514 unsigned usedVectorLength = min(storage->m_length, m_vectorLength); 497 515 for (unsigned i = 0; i < usedVectorLength; ++i) { 498 if ( storage->m_vector[i])516 if (m_vector[i]) 499 517 propertyNames.add(Identifier::from(exec, i)); 500 518 } … … 512 530 } 513 531 532 ALWAYS_INLINE unsigned JSArray::getNewVectorLength(unsigned desiredLength) 533 { 534 ASSERT(desiredLength <= MAX_STORAGE_VECTOR_LENGTH); 535 536 unsigned increasedLength; 537 unsigned length = arrayStorage()->m_length; 538 539 if (desiredLength < length) 540 increasedLength = length; 541 else if (!m_vectorLength) 542 increasedLength = max(desiredLength, lastArraySize); 543 else { 544 // Mathematically equivalent to: 545 // increasedLength = (newLength * 3 + 1) / 2; 546 // or: 547 // increasedLength = (unsigned)ceil(newLength * 1.5)); 548 // This form is not prone to internal overflow. 549 increasedLength = desiredLength + (desiredLength >> 1) + (desiredLength & 1); 550 } 551 552 ASSERT(increasedLength >= desiredLength); 553 554 lastArraySize = min(increasedLength, FIRST_VECTOR_GROW); 555 556 return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH); 557 } 558 514 559 bool JSArray::increaseVectorLength(unsigned newLength) 515 560 { … … 517 562 // to the vector. Callers have to account for that, because they can do it more efficiently. 518 563 519 ArrayStorage* storage = m_storage;564 ArrayStorage* storage = arrayStorage(); 520 565 521 566 unsigned vectorLength = m_vectorLength; 522 567 ASSERT(newLength > vectorLength); 523 568 ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX); 524 unsigned newVectorLength = increasedVectorLength(newLength); 525 526 if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage)) 569 unsigned newVectorLength = getNewVectorLength(newLength); 570 int baseBias = m_indexBias * sizeof(JSValue); 571 char* baseStorage = reinterpret_cast<char*>(storage) - baseBias; 572 573 if (!tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) 527 574 return false; 575 576 storage = reinterpret_cast<ArrayStorage*>(baseStorage + baseBias); 577 setArrayStorage(storage); 578 579 JSValue* vector = m_vector; 580 for (unsigned i = vectorLength; i < newVectorLength; ++i) 581 vector[i] = JSValue(); 528 582 529 583 m_vectorLength = newVectorLength; 530 531 for (unsigned i = vectorLength; i < newVectorLength; ++i) 532 storage->m_vector[i] = JSValue(); 533 534 m_storage = storage; 535 584 536 585 Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); 537 586 538 587 return true; 539 588 } 589 590 bool JSArray::increaseVectorPrefixLength(unsigned newLength) 591 { 592 // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map 593 // to the vector. Callers have to account for that, because they can do it more efficiently. 594 595 ArrayStorage* storage = arrayStorage(); 596 ArrayStorage* newStorage; 597 598 unsigned vectorLength = m_vectorLength; 599 ASSERT(newLength > vectorLength); 600 ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX); 601 unsigned newVectorLength = getNewVectorLength(newLength); 602 char* baseStorage = reinterpret_cast<char*>(storage) - (m_indexBias * sizeof(JSValue)); 603 604 char* newBaseStorage = reinterpret_cast<char*>(fastMalloc(storageSize(newVectorLength + m_indexBias))); 605 if (!newBaseStorage) 606 return false; 607 608 m_indexBias += newVectorLength - newLength; 609 int newStorageOffset = m_indexBias * sizeof(JSValue); 610 611 newStorage = reinterpret_cast<ArrayStorage*>(newBaseStorage + newStorageOffset); 612 613 memcpy(newStorage, storage, storageSize(0)); 614 memcpy(&newStorage->m_vector[newLength - m_vectorLength], &storage->m_vector[0], storage->m_length * sizeof(JSValue)); 615 616 m_vectorLength = newLength; 617 618 fastFree(baseStorage); 619 620 setArrayStorage(newStorage); 621 622 Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); 623 624 return true; 625 } 626 540 627 541 628 void JSArray::setLength(unsigned newLength) … … 548 635 #endif 549 636 550 ArrayStorage* storage = m_storage;551 552 unsigned length = m_storage->m_length;637 ArrayStorage* storage = arrayStorage(); 638 639 unsigned length = storage->m_length; 553 640 554 641 if (newLength < length) { 555 642 unsigned usedVectorLength = min(length, m_vectorLength); 556 643 for (unsigned i = newLength; i < usedVectorLength; ++i) { 557 JSValue& valueSlot = storage->m_vector[i];644 JSValue& valueSlot = m_vector[i]; 558 645 bool hadValue = valueSlot; 559 646 valueSlot = JSValue(); … … 575 662 } 576 663 577 m_storage->m_length = newLength;664 storage->m_length = newLength; 578 665 579 666 checkConsistency(); … … 584 671 checkConsistency(); 585 672 586 unsigned length = m_storage->m_length; 673 ArrayStorage* storage = arrayStorage(); 674 675 unsigned length = storage->m_length; 587 676 if (!length) 588 677 return jsUndefined(); … … 593 682 594 683 if (length < m_vectorLength) { 595 JSValue& valueSlot = m_ storage->m_vector[length];684 JSValue& valueSlot = m_vector[length]; 596 685 if (valueSlot) { 597 -- m_storage->m_numValuesInVector;686 --storage->m_numValuesInVector; 598 687 result = valueSlot; 599 688 valueSlot = JSValue(); … … 602 691 } else { 603 692 result = jsUndefined(); 604 if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {693 if (SparseArrayValueMap* map = storage->m_sparseValueMap) { 605 694 SparseArrayValueMap::iterator it = map->find(length); 606 695 if (it != map->end()) { … … 609 698 if (map->isEmpty()) { 610 699 delete map; 611 m_storage->m_sparseValueMap = 0;700 storage->m_sparseValueMap = 0; 612 701 } 613 702 } … … 615 704 } 616 705 617 m_storage->m_length = length;706 storage->m_length = length; 618 707 619 708 checkConsistency(); … … 625 714 { 626 715 checkConsistency(); 627 628 if (m_storage->m_length < m_vectorLength) { 629 m_storage->m_vector[m_storage->m_length] = value; 630 ++m_storage->m_numValuesInVector; 631 ++m_storage->m_length; 716 717 ArrayStorage* storage = arrayStorage(); 718 719 if (storage->m_length < m_vectorLength) { 720 m_vector[storage->m_length] = value; 721 ++storage->m_numValuesInVector; 722 ++storage->m_length; 632 723 checkConsistency(); 633 724 return; 634 725 } 635 726 636 if ( m_storage->m_length < MIN_SPARSE_ARRAY_INDEX) {637 SparseArrayValueMap* map = m_storage->m_sparseValueMap;727 if (storage->m_length < MIN_SPARSE_ARRAY_INDEX) { 728 SparseArrayValueMap* map = storage->m_sparseValueMap; 638 729 if (!map || map->isEmpty()) { 639 if (increaseVectorLength(m_storage->m_length + 1)) { 640 m_storage->m_vector[m_storage->m_length] = value; 641 ++m_storage->m_numValuesInVector; 642 ++m_storage->m_length; 730 if (increaseVectorLength(storage->m_length + 1)) { 731 storage = arrayStorage(); 732 m_vector[storage->m_length] = value; 733 ++storage->m_numValuesInVector; 734 ++storage->m_length; 643 735 checkConsistency(); 644 736 return; … … 650 742 } 651 743 652 putSlowCase(exec, m_storage->m_length++, value); 744 putSlowCase(exec, storage->m_length++, value); 745 } 746 747 void JSArray::shiftCount(ExecState* exec, int count) 748 { 749 ASSERT(count > 0); 750 751 ArrayStorage* storage = arrayStorage(); 752 753 unsigned oldLength = storage->m_length; 754 755 if (!oldLength) 756 return; 757 758 if (oldLength != storage->m_numValuesInVector) { 759 // If m_length and m_numValuesInVector aren't the same, we have a sparse vector 760 // which means we need to go through each entry looking for the the "empty" 761 // slots and then fill them with possible properties. See ECMA spec. 762 // 15.4.4.9 steps 11 through 13. 763 for (unsigned i = count; i < oldLength; ++i) { 764 if ((i >= m_vectorLength) || (!m_vector[i])) { 765 PropertySlot slot(this); 766 JSValue p = prototype(); 767 if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot))) 768 put(exec, i, slot.getValue(exec, i)); 769 } 770 } 771 772 storage = arrayStorage(); // The put() above could have grown the vector and realloc'ed storage. 773 774 // Need to decrement numValuesInvector based on number of real entries 775 for (unsigned i = 0; i < (unsigned)count; ++i) 776 if ((i < m_vectorLength) && (m_vector[i])) 777 --storage->m_numValuesInVector; 778 } else 779 storage->m_numValuesInVector -= count; 780 781 storage->m_length -= count; 782 783 if (m_vectorLength) { 784 count = min(m_vectorLength, (unsigned)count); 785 786 m_vectorLength -= count; 787 788 if (m_vectorLength) { 789 char* newBaseStorage = reinterpret_cast<char*>(storage) + count * sizeof(JSValue); 790 memmove(newBaseStorage, storage, storageSize(0)); 791 storage = reinterpret_cast<ArrayStorage*>(newBaseStorage); 792 793 m_indexBias += count; 794 setArrayStorage(storage); 795 } 796 } 797 } 798 799 void JSArray::unshiftCount(ExecState* exec, int count) 800 { 801 ArrayStorage* storage = arrayStorage(); 802 803 ASSERT(m_indexBias >= 0); 804 ASSERT(count >= 0); 805 806 unsigned length = storage->m_length; 807 808 if (length != storage->m_numValuesInVector) { 809 // If m_length and m_numValuesInVector aren't the same, we have a sparse vector 810 // which means we need to go through each entry looking for the the "empty" 811 // slots and then fill them with possible properties. See ECMA spec. 812 // 15.4.4.13 steps 8 through 10. 813 for (unsigned i = 0; i < length; ++i) { 814 if ((i >= m_vectorLength) || (!m_vector[i])) { 815 PropertySlot slot(this); 816 JSValue p = prototype(); 817 if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot))) 818 put(exec, i, slot.getValue(exec, i)); 819 } 820 } 821 } 822 823 storage = arrayStorage(); // The put() above could have grown the vector and realloc'ed storage. 824 825 if (m_indexBias >= count) { 826 m_indexBias -= count; 827 char* newBaseStorage = reinterpret_cast<char*>(storage) - count * sizeof(JSValue); 828 memmove(newBaseStorage, storage, storageSize(0)); 829 storage = reinterpret_cast<ArrayStorage*>(newBaseStorage); 830 setArrayStorage(storage); 831 m_vectorLength += count; 832 } else if ((!m_indexBias) && (!increaseVectorPrefixLength(m_vectorLength + count))) { 833 throwOutOfMemoryError(exec); 834 return; 835 } 653 836 } 654 837 … … 676 859 void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData) 677 860 { 861 ArrayStorage* storage = arrayStorage(); 862 678 863 unsigned lengthNotIncludingUndefined = compactForSorting(); 679 if ( m_storage->m_sparseValueMap) {864 if (storage->m_sparseValueMap) { 680 865 throwOutOfMemoryError(exec); 681 866 return; … … 686 871 687 872 bool allValuesAreNumbers = true; 688 size_t size = m_storage->m_numValuesInVector;873 size_t size = storage->m_numValuesInVector; 689 874 for (size_t i = 0; i < size; ++i) { 690 if (!m_ storage->m_vector[i].isNumber()) {875 if (!m_vector[i].isNumber()) { 691 876 allValuesAreNumbers = false; 692 877 break; … … 700 885 // also don't require mergesort's stability, since there's no user visible 701 886 // side-effect from swapping the order of equal primitive values. 702 qsort(m_ storage->m_vector, size, sizeof(JSValue), compareNumbersForQSort);887 qsort(m_vector, size, sizeof(JSValue), compareNumbersForQSort); 703 888 704 889 checkConsistency(SortConsistencyCheck); … … 707 892 void JSArray::sort(ExecState* exec) 708 893 { 894 ArrayStorage* storage = arrayStorage(); 895 709 896 unsigned lengthNotIncludingUndefined = compactForSorting(); 710 if ( m_storage->m_sparseValueMap) {897 if (storage->m_sparseValueMap) { 711 898 throwOutOfMemoryError(exec); 712 899 return; … … 728 915 729 916 for (size_t i = 0; i < lengthNotIncludingUndefined; i++) { 730 JSValue value = m_ storage->m_vector[i];917 JSValue value = m_vector[i]; 731 918 ASSERT(!value.isUndefined()); 732 919 values[i].first = value; … … 760 947 761 948 for (size_t i = 0; i < lengthNotIncludingUndefined; i++) 762 m_ storage->m_vector[i] = values[i].first;949 m_vector[i] = values[i].first; 763 950 764 951 checkConsistency(SortConsistencyCheck); … … 847 1034 checkConsistency(); 848 1035 1036 ArrayStorage* storage = arrayStorage(); 1037 849 1038 // FIXME: This ignores exceptions raised in the compare function or in toNumber. 850 1039 851 1040 // The maximum tree depth is compiled in - but the caller is clearly up to no good 852 1041 // if a larger array is passed. 853 ASSERT( m_storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));854 if ( m_storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))855 return; 856 857 if (! m_storage->m_length)858 return; 859 860 unsigned usedVectorLength = min( m_storage->m_length, m_vectorLength);1042 ASSERT(storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max())); 1043 if (storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max())) 1044 return; 1045 1046 if (!storage->m_length) 1047 return; 1048 1049 unsigned usedVectorLength = min(storage->m_length, m_vectorLength); 861 1050 862 1051 AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items … … 866 1055 tree.abstractor().m_compareCallData = &callData; 867 1056 tree.abstractor().m_globalThisValue = exec->globalThisValue(); 868 tree.abstractor().m_nodes.resize(usedVectorLength + ( m_storage->m_sparseValueMap ? m_storage->m_sparseValueMap->size() : 0));1057 tree.abstractor().m_nodes.resize(usedVectorLength + (storage->m_sparseValueMap ? storage->m_sparseValueMap->size() : 0)); 869 1058 870 1059 if (callType == CallTypeJS) … … 884 1073 // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree. 885 1074 for (; numDefined < usedVectorLength; ++numDefined) { 886 JSValue v = m_ storage->m_vector[numDefined];1075 JSValue v = m_vector[numDefined]; 887 1076 if (!v || v.isUndefined()) 888 1077 break; … … 891 1080 } 892 1081 for (unsigned i = numDefined; i < usedVectorLength; ++i) { 893 JSValue v = m_ storage->m_vector[i];1082 JSValue v = m_vector[i]; 894 1083 if (v) { 895 1084 if (v.isUndefined()) … … 905 1094 unsigned newUsedVectorLength = numDefined + numUndefined; 906 1095 907 if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {1096 if (SparseArrayValueMap* map = storage->m_sparseValueMap) { 908 1097 newUsedVectorLength += map->size(); 909 1098 if (newUsedVectorLength > m_vectorLength) { … … 914 1103 } 915 1104 } 1105 1106 storage = arrayStorage(); 916 1107 917 1108 SparseArrayValueMap::iterator end = map->end(); … … 923 1114 924 1115 delete map; 925 m_storage->m_sparseValueMap = 0;1116 storage->m_sparseValueMap = 0; 926 1117 } 927 1118 … … 935 1126 iter.start_iter_least(tree); 936 1127 for (unsigned i = 0; i < numDefined; ++i) { 937 m_ storage->m_vector[i] = tree.abstractor().m_nodes[*iter].value;1128 m_vector[i] = tree.abstractor().m_nodes[*iter].value; 938 1129 ++iter; 939 1130 } … … 941 1132 // Put undefined values back in. 942 1133 for (unsigned i = numDefined; i < newUsedVectorLength; ++i) 943 m_ storage->m_vector[i] = jsUndefined();1134 m_vector[i] = jsUndefined(); 944 1135 945 1136 // Ensure that unused values in the vector are zeroed out. 946 1137 for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) 947 m_ storage->m_vector[i] = JSValue();948 949 m_storage->m_numValuesInVector = newUsedVectorLength;1138 m_vector[i] = JSValue(); 1139 1140 storage->m_numValuesInVector = newUsedVectorLength; 950 1141 951 1142 checkConsistency(SortConsistencyCheck); … … 954 1145 void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) 955 1146 { 956 JSValue* vector = m_storage->m_vector; 957 unsigned vectorEnd = min(m_storage->m_length, m_vectorLength); 1147 ArrayStorage* storage = arrayStorage(); 1148 1149 JSValue* vector = storage->m_vector; 1150 unsigned vectorEnd = min(storage->m_length, m_vectorLength); 958 1151 unsigned i = 0; 959 1152 for (; i < vectorEnd; ++i) { … … 964 1157 } 965 1158 966 for (; i < m_storage->m_length; ++i)1159 for (; i < storage->m_length; ++i) 967 1160 args.append(get(exec, i)); 968 1161 } … … 970 1163 void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize) 971 1164 { 972 ASSERT( m_storage->m_length >= maxSize);1165 ASSERT(arrayStorage()->m_length >= maxSize); 973 1166 UNUSED_PARAM(maxSize); 974 JSValue* vector = m_ storage->m_vector;1167 JSValue* vector = m_vector; 975 1168 unsigned vectorEnd = min(maxSize, m_vectorLength); 976 1169 unsigned i = 0; … … 990 1183 checkConsistency(); 991 1184 992 ArrayStorage* storage = m_storage;993 994 unsigned usedVectorLength = min( m_storage->m_length, m_vectorLength);1185 ArrayStorage* storage = arrayStorage(); 1186 1187 unsigned usedVectorLength = min(storage->m_length, m_vectorLength); 995 1188 996 1189 unsigned numDefined = 0; … … 998 1191 999 1192 for (; numDefined < usedVectorLength; ++numDefined) { 1000 JSValue v = storage->m_vector[numDefined];1193 JSValue v = m_vector[numDefined]; 1001 1194 if (!v || v.isUndefined()) 1002 1195 break; 1003 1196 } 1004 1197 for (unsigned i = numDefined; i < usedVectorLength; ++i) { 1005 JSValue v = storage->m_vector[i];1198 JSValue v = m_vector[i]; 1006 1199 if (v) { 1007 1200 if (v.isUndefined()) 1008 1201 ++numUndefined; 1009 1202 else 1010 storage->m_vector[numDefined++] = v;1203 m_vector[numDefined++] = v; 1011 1204 } 1012 1205 } … … 1021 1214 if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) 1022 1215 return 0; 1023 storage = m_storage; 1216 1217 storage = arrayStorage(); 1024 1218 } 1025 1219 1026 1220 SparseArrayValueMap::iterator end = map->end(); 1027 1221 for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) 1028 storage->m_vector[numDefined++] = it->second;1222 m_vector[numDefined++] = it->second; 1029 1223 1030 1224 delete map; … … 1033 1227 1034 1228 for (unsigned i = numDefined; i < newUsedVectorLength; ++i) 1035 storage->m_vector[i] = jsUndefined();1229 m_vector[i] = jsUndefined(); 1036 1230 for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) 1037 storage->m_vector[i] = JSValue();1231 m_vector[i] = JSValue(); 1038 1232 1039 1233 storage->m_numValuesInVector = newUsedVectorLength; … … 1046 1240 void* JSArray::subclassData() const 1047 1241 { 1048 return m_storage->subclassData;1242 return arrayStorage()->subclassData; 1049 1243 } 1050 1244 1051 1245 void JSArray::setSubclassData(void* d) 1052 1246 { 1053 m_storage->subclassData = d;1247 arrayStorage()->subclassData = d; 1054 1248 } 1055 1249 … … 1058 1252 void JSArray::checkConsistency(ConsistencyCheckType type) 1059 1253 { 1060 ASSERT(m_storage); 1254 ArrayStorage* storage = arrayStorage(); 1255 1256 ASSERT(storage); 1061 1257 if (type == SortConsistencyCheck) 1062 ASSERT(! m_storage->m_sparseValueMap);1258 ASSERT(!storage->m_sparseValueMap); 1063 1259 1064 1260 unsigned numValuesInVector = 0; 1065 1261 for (unsigned i = 0; i < m_vectorLength; ++i) { 1066 if (JSValue value = m_ storage->m_vector[i]) {1067 ASSERT(i < m_storage->m_length);1262 if (JSValue value = m_vector[i]) { 1263 ASSERT(i < storage->m_length); 1068 1264 if (type != DestructorConsistencyCheck) 1069 1265 value.isUndefined(); // Likely to crash if the object was deallocated. … … 1071 1267 } else { 1072 1268 if (type == SortConsistencyCheck) 1073 ASSERT(i >= m_storage->m_numValuesInVector);1074 } 1075 } 1076 ASSERT(numValuesInVector == m_storage->m_numValuesInVector);1077 ASSERT(numValuesInVector <= m_storage->m_length);1078 1079 if ( m_storage->m_sparseValueMap) {1080 SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end();1081 for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) {1269 ASSERT(i >= storage->m_numValuesInVector); 1270 } 1271 } 1272 ASSERT(numValuesInVector == storage->m_numValuesInVector); 1273 ASSERT(numValuesInVector <= storage->m_length); 1274 1275 if (storage->m_sparseValueMap) { 1276 SparseArrayValueMap::iterator end = storage->m_sparseValueMap->end(); 1277 for (SparseArrayValueMap::iterator it = storage->m_sparseValueMap->begin(); it != end; ++it) { 1082 1278 unsigned index = it->first; 1083 ASSERT(index < m_storage->m_length);1279 ASSERT(index < storage->m_length); 1084 1280 ASSERT(index >= m_vectorLength); 1085 1281 ASSERT(index <= MAX_ARRAY_INDEX);
Note:
See TracChangeset
for help on using the changeset viewer.