Changeset 34496 in webkit for trunk/JavaScriptCore/kjs/array_instance.cpp
- Timestamp:
- Jun 11, 2008, 12:37:44 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/array_instance.cpp
r34355 r34496 28 28 #include <wtf/AVLTree.h> 29 29 30 #define CHECK_ARRAY_CONSISTENCY 0 31 30 32 using namespace std; 31 33 … … 41 43 }; 42 44 43 // 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer 45 // 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer. 44 46 static const unsigned maxArrayIndex = 0xFFFFFFFEU; 45 47 … … 70 72 } 71 73 74 #if !CHECK_ARRAY_CONSISTENCY 75 76 inline void ArrayInstance::checkConsistency(ConsistencyCheckType) 77 { 78 } 79 80 #endif 81 72 82 ArrayInstance::ArrayInstance(JSObject* prototype, unsigned initialLength) 73 83 : JSObject(prototype) … … 80 90 81 91 Collector::reportExtraMemoryCost(initialCapacity * sizeof(JSValue*)); 92 93 checkConsistency(); 82 94 } 83 95 … … 104 116 // When the array is created non-empty, its cells are filled, so it's really no worse than 105 117 // a property map. Therefore don't report extra memory cost. 118 119 checkConsistency(); 106 120 } 107 121 108 122 ArrayInstance::~ArrayInstance() 109 123 { 124 checkConsistency(DestructorConsistencyCheck); 125 110 126 delete m_storage->m_sparseValueMap; 111 127 fastFree(m_storage); … … 210 226 void ArrayInstance::put(ExecState* exec, unsigned i, JSValue* value) 211 227 { 228 checkConsistency(); 229 212 230 unsigned length = m_length; 213 231 if (i >= length) { … … 226 244 storage->m_numValuesInVector += !valueSlot; 227 245 valueSlot = value; 246 checkConsistency(); 228 247 return; 229 248 } … … 251 270 ++storage->m_numValuesInVector; 252 271 storage->m_vector[i] = value; 272 checkConsistency(); 253 273 return; 254 274 } … … 295 315 296 316 m_storage = storage; 317 318 checkConsistency(); 297 319 } 298 320 … … 312 334 bool ArrayInstance::deleteProperty(ExecState* exec, unsigned i) 313 335 { 336 checkConsistency(); 337 314 338 ArrayStorage* storage = m_storage; 315 339 … … 319 343 valueSlot = 0; 320 344 storage->m_numValuesInVector -= hadValue; 345 checkConsistency(); 321 346 return hadValue; 322 347 } … … 327 352 if (it != map->end()) { 328 353 map->remove(it); 354 checkConsistency(); 329 355 return true; 330 356 } … … 332 358 } 333 359 360 checkConsistency(); 361 334 362 if (i > maxArrayIndex) 335 363 return deleteProperty(exec, Identifier::from(i)); … … 341 369 { 342 370 // FIXME: Filling PropertyNameArray with an identifier for every integer 343 // is incredibly inefficient for large arrays. We need a different approach. 371 // is incredibly inefficient for large arrays. We need a different approach, 372 // which almost certainly means a different structure for PropertyNameArray. 344 373 345 374 ArrayStorage* storage = m_storage; … … 386 415 void ArrayInstance::setLength(unsigned newLength) 387 416 { 417 checkConsistency(); 418 388 419 ArrayStorage* storage = m_storage; 389 420 … … 414 445 415 446 m_length = newLength; 447 448 checkConsistency(); 416 449 } 417 450 … … 439 472 } 440 473 474 typedef std::pair<JSValue*, UString> ArrayQSortPair; 475 441 476 static int compareByStringPairForQSort(const void* a, const void* b) 442 477 { 443 const std::pair<JSValue*, UString>* va = static_cast<const std::pair<JSValue*, UString>*>(a);444 const std::pair<JSValue*, UString>* vb = static_cast<const std::pair<JSValue*, UString>*>(b);478 const ArrayQSortPair* va = static_cast<const ArrayQSortPair*>(a); 479 const ArrayQSortPair* vb = static_cast<const ArrayQSortPair*>(b); 445 480 return compare(va->second, vb->second); 446 481 } … … 462 497 // random or otherwise changing results, effectively making compare function inconsistent. 463 498 464 Vector< std::pair<JSValue*, UString>> values(lengthNotIncludingUndefined);499 Vector<ArrayQSortPair> values(lengthNotIncludingUndefined); 465 500 if (!values.begin()) { 466 501 exec->setException(Error::create(exec, GeneralError, "Out of memory")); … … 472 507 ASSERT(!value->isUndefined()); 473 508 values[i].first = value; 474 values[i].second = value->toString(exec); 475 } 509 } 510 511 // FIXME: While calling these toString functions, the array could be mutated. 512 // In that case, objects pointed to by values in this vector might get garbage-collected! 513 514 // FIXME: The following loop continues to call toString on subsequent values even after 515 // a toString call raises an exception. 516 517 for (size_t i = 0; i < lengthNotIncludingUndefined; i++) 518 values[i].second = values[i].first->toString(exec); 476 519 477 520 if (exec->hadException()) … … 482 525 483 526 #if HAVE(MERGESORT) 484 mergesort(values.begin(), values.size(), sizeof( std::pair<JSValue*, UString>), compareByStringPairForQSort);527 mergesort(values.begin(), values.size(), sizeof(ArrayQSortPair), compareByStringPairForQSort); 485 528 #else 486 // FIXME: QSort may not be stable in some implementations. ECMAScript-262 does not require this, but in practice, browsers perform stable sort. 487 qsort(values.begin(), values.size(), sizeof(std::pair<JSValue*, UString>), compareByStringPairForQSort); 529 // FIXME: The qsort library function is likely to not be a stable sort. 530 // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort. 531 qsort(values.begin(), values.size(), sizeof(ArrayQSortPair), compareByStringPairForQSort); 488 532 #endif 533 534 // FIXME: If the toString function changed the length of the array, this might be 535 // modifying the vector incorrectly. 489 536 490 537 for (size_t i = 0; i < lengthNotIncludingUndefined; i++) 491 538 m_storage->m_vector[i] = values[i].first; 539 540 checkConsistency(SortConsistencyCheck); 492 541 } 493 542 … … 559 608 void ArrayInstance::sort(ExecState* exec, JSObject* compareFunction) 560 609 { 610 checkConsistency(); 611 612 // FIXME: This ignores exceptions raised in the compare function or in toNumber. 613 561 614 // The maximum tree depth is compiled in - but the caller is clearly up to no good 562 615 // if a larger array is passed. … … 580 633 return; 581 634 } 635 636 // FIXME: If the compare function modifies the array, the vector, map, etc. could be modified 637 // right out from under us while we're building the tree here. 582 638 583 639 unsigned numDefined = 0; … … 628 684 ASSERT(tree.abstractor().m_nodes.size() >= numDefined); 629 685 686 // FIXME: If the compare function changed the length of the array, the following might be 687 // modifying the vector incorrectly. 688 630 689 // Copy the values back into m_storage. 631 690 AVLTree<AVLTreeAbstractorForArrayCompare, 44>::Iterator iter; … … 643 702 for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) 644 703 m_storage->m_vector[i] = 0; 704 705 m_storage->m_numValuesInVector = newUsedVectorLength; 706 707 checkConsistency(SortConsistencyCheck); 645 708 } 646 709 647 710 unsigned ArrayInstance::compactForSorting() 648 711 { 712 checkConsistency(); 713 649 714 ArrayStorage* storage = m_storage; 650 715 … … 691 756 storage->m_vector[i] = 0; 692 757 758 storage->m_numValuesInVector = newUsedVectorLength; 759 760 checkConsistency(SortConsistencyCheck); 761 693 762 return numDefined; 694 763 } … … 704 773 } 705 774 706 } 775 #if CHECK_ARRAY_CONSISTENCY 776 777 void ArrayInstance::checkConsistency(ConsistencyCheckType type) 778 { 779 ASSERT(m_storage); 780 if (type == SortConsistencyCheck) 781 ASSERT(!m_storage->m_sparseValueMap); 782 783 unsigned numValuesInVector = 0; 784 for (unsigned i = 0; i < m_vectorLength; ++i) { 785 if (JSValue* value = m_storage->m_vector[i]) { 786 ASSERT(i < m_length); 787 if (type != DestructorConsistencyCheck) 788 value->type(); // Likely to crash if the object was deallocated. 789 ++numValuesInVector; 790 } else { 791 if (type == SortConsistencyCheck) 792 ASSERT(i >= m_storage->m_numValuesInVector); 793 } 794 } 795 ASSERT(numValuesInVector == m_storage->m_numValuesInVector); 796 797 if (m_storage->m_sparseValueMap) { 798 SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end(); 799 for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) { 800 unsigned index = it->first; 801 ASSERT(index < m_length); 802 ASSERT(index >= m_vectorLength); 803 ASSERT(index <= maxArrayIndex); 804 ASSERT(it->second); 805 if (type != DestructorConsistencyCheck) 806 it->second->type(); // Likely to crash if the object was deallocated. 807 } 808 } 809 } 810 811 #endif 812 813 }
Note:
See TracChangeset
for help on using the changeset viewer.