OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
9 #include "src/elements.h" | 9 #include "src/elements.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 return ElementsAccessorSubclass::GetAccessorPairImpl(holder, key, | 629 return ElementsAccessorSubclass::GetAccessorPairImpl(holder, key, |
630 backing_store); | 630 backing_store); |
631 } | 631 } |
632 | 632 |
633 static MaybeHandle<AccessorPair> GetAccessorPairImpl( | 633 static MaybeHandle<AccessorPair> GetAccessorPairImpl( |
634 Handle<JSObject> obj, uint32_t key, | 634 Handle<JSObject> obj, uint32_t key, |
635 Handle<FixedArrayBase> backing_store) { | 635 Handle<FixedArrayBase> backing_store) { |
636 return MaybeHandle<AccessorPair>(); | 636 return MaybeHandle<AccessorPair>(); |
637 } | 637 } |
638 | 638 |
639 MUST_USE_RESULT virtual MaybeHandle<Object> SetLength( | 639 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { |
640 Handle<JSArray> array, Handle<Object> length) final { | 640 ElementsAccessorSubclass::SetLengthImpl(array, length, |
641 return ElementsAccessorSubclass::SetLengthImpl( | 641 handle(array->elements())); |
642 array, length, handle(array->elements())); | |
643 } | 642 } |
644 | 643 |
645 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( | 644 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
646 Handle<JSObject> obj, | 645 Handle<FixedArrayBase> backing_store); |
647 Handle<Object> length, | |
648 Handle<FixedArrayBase> backing_store); | |
649 | 646 |
650 virtual void SetCapacityAndLength(Handle<JSArray> array, int capacity, | 647 virtual void SetCapacityAndLength(Handle<JSArray> array, int capacity, |
651 int length) final { | 648 int length) final { |
652 ElementsAccessorSubclass:: | 649 ElementsAccessorSubclass:: |
653 SetFastElementsCapacityAndLength(array, capacity, length); | 650 SetFastElementsCapacityAndLength(array, capacity, length); |
654 } | 651 } |
655 | 652 |
656 static void SetFastElementsCapacityAndLength( | 653 static void SetFastElementsCapacityAndLength( |
657 Handle<JSObject> obj, | 654 Handle<JSObject> obj, |
658 int capacity, | 655 int capacity, |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 explicit FastElementsAccessor(const char* name) | 856 explicit FastElementsAccessor(const char* name) |
860 : ElementsAccessorBase<FastElementsAccessorSubclass, | 857 : ElementsAccessorBase<FastElementsAccessorSubclass, |
861 KindTraits>(name) {} | 858 KindTraits>(name) {} |
862 protected: | 859 protected: |
863 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; | 860 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
864 friend class SloppyArgumentsElementsAccessor; | 861 friend class SloppyArgumentsElementsAccessor; |
865 | 862 |
866 typedef typename KindTraits::BackingStore BackingStore; | 863 typedef typename KindTraits::BackingStore BackingStore; |
867 | 864 |
868 // Adjusts the length of the fast backing store. | 865 // Adjusts the length of the fast backing store. |
869 static Handle<Object> SetLengthWithoutNormalize( | 866 static uint32_t SetLengthWithoutNormalize( |
870 Handle<FixedArrayBase> backing_store, | 867 Handle<FixedArrayBase> backing_store, Handle<JSArray> array, |
871 Handle<JSArray> array, | |
872 Handle<Object> length_object, | |
873 uint32_t length) { | 868 uint32_t length) { |
874 Isolate* isolate = array->GetIsolate(); | 869 Isolate* isolate = array->GetIsolate(); |
875 uint32_t old_capacity = backing_store->length(); | 870 uint32_t old_capacity = backing_store->length(); |
876 Handle<Object> old_length(array->length(), isolate); | 871 Handle<Object> old_length(array->length(), isolate); |
877 bool same_or_smaller_size = old_length->IsSmi() && | 872 bool same_or_smaller_size = old_length->IsSmi() && |
878 static_cast<uint32_t>(Handle<Smi>::cast(old_length)->value()) >= length; | 873 static_cast<uint32_t>(Handle<Smi>::cast(old_length)->value()) >= length; |
879 ElementsKind kind = array->GetElementsKind(); | 874 ElementsKind kind = array->GetElementsKind(); |
880 | 875 |
881 if (!same_or_smaller_size && IsFastElementsKind(kind) && | 876 if (!same_or_smaller_size && IsFastElementsKind(kind) && |
882 !IsFastHoleyElementsKind(kind)) { | 877 !IsFastHoleyElementsKind(kind)) { |
(...skipping 14 matching lines...) Expand all Loading... |
897 isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | 892 isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
898 *backing_store, old_capacity - length); | 893 *backing_store, old_capacity - length); |
899 } | 894 } |
900 } else { | 895 } else { |
901 // Otherwise, fill the unused tail with holes. | 896 // Otherwise, fill the unused tail with holes. |
902 int old_length = FastD2IChecked(array->length()->Number()); | 897 int old_length = FastD2IChecked(array->length()->Number()); |
903 for (int i = length; i < old_length; i++) { | 898 for (int i = length; i < old_length; i++) { |
904 Handle<BackingStore>::cast(backing_store)->set_the_hole(i); | 899 Handle<BackingStore>::cast(backing_store)->set_the_hole(i); |
905 } | 900 } |
906 } | 901 } |
907 return length_object; | 902 return length; |
908 } | 903 } |
909 | 904 |
910 // Check whether the backing store should be expanded. | 905 // Check whether the backing store should be expanded. |
911 uint32_t min = JSObject::NewElementsCapacity(old_capacity); | 906 uint32_t min = JSObject::NewElementsCapacity(old_capacity); |
912 uint32_t new_capacity = length > min ? length : min; | 907 uint32_t new_capacity = length > min ? length : min; |
913 FastElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 908 FastElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
914 array, new_capacity, length); | 909 array, new_capacity, length); |
915 JSObject::ValidateElements(array); | 910 JSObject::ValidateElements(array); |
916 return length_object; | 911 return length; |
917 } | 912 } |
918 | 913 |
919 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, | 914 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
920 LanguageMode language_mode) { | 915 LanguageMode language_mode) { |
921 DCHECK(obj->HasFastSmiOrObjectElements() || | 916 DCHECK(obj->HasFastSmiOrObjectElements() || |
922 obj->HasFastDoubleElements() || | 917 obj->HasFastDoubleElements() || |
923 obj->HasFastArgumentsElements()); | 918 obj->HasFastArgumentsElements()); |
924 Isolate* isolate = obj->GetIsolate(); | 919 Isolate* isolate = obj->GetIsolate(); |
925 Heap* heap = obj->GetHeap(); | 920 Heap* heap = obj->GetHeap(); |
926 Handle<FixedArrayBase> elements(obj->elements()); | 921 Handle<FixedArrayBase> elements(obj->elements()); |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 } else { | 1259 } else { |
1265 return backing_store->GetIsolate()->factory()->undefined_value(); | 1260 return backing_store->GetIsolate()->factory()->undefined_value(); |
1266 } | 1261 } |
1267 } | 1262 } |
1268 | 1263 |
1269 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1264 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
1270 uint32_t index) { | 1265 uint32_t index) { |
1271 return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell); | 1266 return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell); |
1272 } | 1267 } |
1273 | 1268 |
1274 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( | 1269 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
1275 Handle<JSObject> obj, | 1270 Handle<FixedArrayBase> backing_store) { |
1276 Handle<Object> length, | |
1277 Handle<FixedArrayBase> backing_store) { | |
1278 // External arrays do not support changing their length. | 1271 // External arrays do not support changing their length. |
1279 UNREACHABLE(); | 1272 UNREACHABLE(); |
1280 return obj; | |
1281 } | 1273 } |
1282 | 1274 |
1283 virtual void Delete(Handle<JSObject> obj, uint32_t key, | 1275 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
1284 LanguageMode language_mode) final { | 1276 LanguageMode language_mode) final { |
1285 // External arrays always ignore deletes. | 1277 // External arrays always ignore deletes. |
1286 } | 1278 } |
1287 | 1279 |
1288 static uint32_t GetIndexForKeyImpl(JSObject* holder, | 1280 static uint32_t GetIndexForKeyImpl(JSObject* holder, |
1289 FixedArrayBase* backing_store, | 1281 FixedArrayBase* backing_store, |
1290 uint32_t key) { | 1282 uint32_t key) { |
(...skipping 29 matching lines...) Expand all Loading... |
1320 | 1312 |
1321 | 1313 |
1322 class DictionaryElementsAccessor | 1314 class DictionaryElementsAccessor |
1323 : public ElementsAccessorBase<DictionaryElementsAccessor, | 1315 : public ElementsAccessorBase<DictionaryElementsAccessor, |
1324 ElementsKindTraits<DICTIONARY_ELEMENTS> > { | 1316 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
1325 public: | 1317 public: |
1326 explicit DictionaryElementsAccessor(const char* name) | 1318 explicit DictionaryElementsAccessor(const char* name) |
1327 : ElementsAccessorBase<DictionaryElementsAccessor, | 1319 : ElementsAccessorBase<DictionaryElementsAccessor, |
1328 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} | 1320 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
1329 | 1321 |
| 1322 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
| 1323 Handle<FixedArrayBase> backing_store) { |
| 1324 uint32_t new_length = |
| 1325 SetLengthWithoutNormalize(backing_store, array, length); |
| 1326 // SetLengthWithoutNormalize does not allow length to drop below the last |
| 1327 // non-deletable element. |
| 1328 DCHECK_GE(new_length, length); |
| 1329 if (new_length <= Smi::kMaxValue) { |
| 1330 array->set_length(Smi::FromInt(new_length)); |
| 1331 } else { |
| 1332 Isolate* isolate = array->GetIsolate(); |
| 1333 Handle<Object> length_obj = |
| 1334 isolate->factory()->NewNumberFromUint(new_length); |
| 1335 array->set_length(*length_obj); |
| 1336 } |
| 1337 } |
| 1338 |
1330 // Adjusts the length of the dictionary backing store and returns the new | 1339 // Adjusts the length of the dictionary backing store and returns the new |
1331 // length according to ES5 section 15.4.5.2 behavior. | 1340 // length according to ES5 section 15.4.5.2 behavior. |
1332 static Handle<Object> SetLengthWithoutNormalize( | 1341 static uint32_t SetLengthWithoutNormalize(Handle<FixedArrayBase> store, |
1333 Handle<FixedArrayBase> store, | 1342 Handle<JSArray> array, |
1334 Handle<JSArray> array, | 1343 uint32_t length) { |
1335 Handle<Object> length_object, | |
1336 uint32_t length) { | |
1337 Handle<SeededNumberDictionary> dict = | 1344 Handle<SeededNumberDictionary> dict = |
1338 Handle<SeededNumberDictionary>::cast(store); | 1345 Handle<SeededNumberDictionary>::cast(store); |
1339 Isolate* isolate = array->GetIsolate(); | 1346 Isolate* isolate = array->GetIsolate(); |
1340 int capacity = dict->Capacity(); | 1347 int capacity = dict->Capacity(); |
1341 uint32_t new_length = length; | 1348 uint32_t old_length = 0; |
1342 uint32_t old_length = static_cast<uint32_t>(array->length()->Number()); | 1349 CHECK(array->length()->ToArrayLength(&old_length)); |
1343 if (new_length < old_length) { | 1350 if (length < old_length) { |
1344 // Find last non-deletable element in range of elements to be | 1351 // Find last non-deletable element in range of elements to be |
1345 // deleted and adjust range accordingly. | 1352 // deleted and adjust range accordingly. |
1346 for (int i = 0; i < capacity; i++) { | 1353 for (int i = 0; i < capacity; i++) { |
1347 DisallowHeapAllocation no_gc; | 1354 DisallowHeapAllocation no_gc; |
1348 Object* key = dict->KeyAt(i); | 1355 Object* key = dict->KeyAt(i); |
1349 if (key->IsNumber()) { | 1356 if (key->IsNumber()) { |
1350 uint32_t number = static_cast<uint32_t>(key->Number()); | 1357 uint32_t number = static_cast<uint32_t>(key->Number()); |
1351 if (new_length <= number && number < old_length) { | 1358 if (length <= number && number < old_length) { |
1352 PropertyDetails details = dict->DetailsAt(i); | 1359 PropertyDetails details = dict->DetailsAt(i); |
1353 if (!details.IsConfigurable()) new_length = number + 1; | 1360 if (!details.IsConfigurable()) length = number + 1; |
1354 } | 1361 } |
1355 } | 1362 } |
1356 } | 1363 } |
1357 if (new_length != length) { | |
1358 length_object = isolate->factory()->NewNumberFromUint(new_length); | |
1359 } | |
1360 } | 1364 } |
1361 | 1365 |
1362 if (new_length == 0) { | 1366 if (length == 0) { |
1363 // Flush the backing store. | 1367 // Flush the backing store. |
1364 JSObject::ResetElements(array); | 1368 JSObject::ResetElements(array); |
1365 } else { | 1369 } else { |
1366 DisallowHeapAllocation no_gc; | 1370 DisallowHeapAllocation no_gc; |
1367 // Remove elements that should be deleted. | 1371 // Remove elements that should be deleted. |
1368 int removed_entries = 0; | 1372 int removed_entries = 0; |
1369 Handle<Object> the_hole_value = isolate->factory()->the_hole_value(); | 1373 Handle<Object> the_hole_value = isolate->factory()->the_hole_value(); |
1370 for (int i = 0; i < capacity; i++) { | 1374 for (int i = 0; i < capacity; i++) { |
1371 Object* key = dict->KeyAt(i); | 1375 Object* key = dict->KeyAt(i); |
1372 if (key->IsNumber()) { | 1376 if (key->IsNumber()) { |
1373 uint32_t number = static_cast<uint32_t>(key->Number()); | 1377 uint32_t number = static_cast<uint32_t>(key->Number()); |
1374 if (new_length <= number && number < old_length) { | 1378 if (length <= number && number < old_length) { |
1375 dict->SetEntry(i, the_hole_value, the_hole_value); | 1379 dict->SetEntry(i, the_hole_value, the_hole_value); |
1376 removed_entries++; | 1380 removed_entries++; |
1377 } | 1381 } |
1378 } | 1382 } |
1379 } | 1383 } |
1380 | 1384 |
1381 // Update the number of elements. | 1385 // Update the number of elements. |
1382 dict->ElementsRemoved(removed_entries); | 1386 dict->ElementsRemoved(removed_entries); |
1383 } | 1387 } |
1384 return length_object; | 1388 return length; |
1385 } | 1389 } |
1386 | 1390 |
1387 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, | 1391 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
1388 LanguageMode language_mode) { | 1392 LanguageMode language_mode) { |
1389 Isolate* isolate = obj->GetIsolate(); | 1393 Isolate* isolate = obj->GetIsolate(); |
1390 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), | 1394 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), |
1391 isolate); | 1395 isolate); |
1392 bool is_arguments = | 1396 bool is_arguments = |
1393 (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS); | 1397 (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS); |
1394 if (is_arguments) { | 1398 if (is_arguments) { |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1559 if (!probe->IsTheHole()) { | 1563 if (!probe->IsTheHole()) { |
1560 return MaybeHandle<AccessorPair>(); | 1564 return MaybeHandle<AccessorPair>(); |
1561 } else { | 1565 } else { |
1562 // If not aliased, check the arguments. | 1566 // If not aliased, check the arguments. |
1563 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | 1567 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); |
1564 return ElementsAccessor::ForArray(arguments) | 1568 return ElementsAccessor::ForArray(arguments) |
1565 ->GetAccessorPair(obj, key, arguments); | 1569 ->GetAccessorPair(obj, key, arguments); |
1566 } | 1570 } |
1567 } | 1571 } |
1568 | 1572 |
1569 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( | 1573 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
1570 Handle<JSObject> obj, | 1574 Handle<FixedArrayBase> parameter_map) { |
1571 Handle<Object> length, | 1575 // Sloppy arguments objects are not arrays. |
1572 Handle<FixedArrayBase> parameter_map) { | 1576 UNREACHABLE(); |
1573 // TODO(mstarzinger): This was never implemented but will be used once we | |
1574 // correctly implement [[DefineOwnProperty]] on arrays. | |
1575 UNIMPLEMENTED(); | |
1576 return obj; | |
1577 } | 1577 } |
1578 | 1578 |
1579 virtual void Delete(Handle<JSObject> obj, uint32_t key, | 1579 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
1580 LanguageMode language_mode) final { | 1580 LanguageMode language_mode) final { |
1581 Isolate* isolate = obj->GetIsolate(); | 1581 Isolate* isolate = obj->GetIsolate(); |
1582 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); | 1582 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); |
1583 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); | 1583 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); |
1584 if (!probe->IsTheHole()) { | 1584 if (!probe->IsTheHole()) { |
1585 // TODO(kmillikin): We could check if this was the last aliased | 1585 // TODO(kmillikin): We could check if this was the last aliased |
1586 // parameter, and revert to normal elements in that case. That | 1586 // parameter, and revert to normal elements in that case. That |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1697 void ElementsAccessor::TearDown() { | 1697 void ElementsAccessor::TearDown() { |
1698 if (elements_accessors_ == NULL) return; | 1698 if (elements_accessors_ == NULL) return; |
1699 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 1699 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
1700 ELEMENTS_LIST(ACCESSOR_DELETE) | 1700 ELEMENTS_LIST(ACCESSOR_DELETE) |
1701 #undef ACCESSOR_DELETE | 1701 #undef ACCESSOR_DELETE |
1702 elements_accessors_ = NULL; | 1702 elements_accessors_ = NULL; |
1703 } | 1703 } |
1704 | 1704 |
1705 | 1705 |
1706 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> | 1706 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
1707 MUST_USE_RESULT MaybeHandle<Object> ElementsAccessorBase< | 1707 void ElementsAccessorBase<ElementsAccessorSubclass, ElementsKindTraits>:: |
1708 ElementsAccessorSubclass, | 1708 SetLengthImpl(Handle<JSArray> array, uint32_t length, |
1709 ElementsKindTraits>::SetLengthImpl(Handle<JSObject> obj, | 1709 Handle<FixedArrayBase> backing_store) { |
1710 Handle<Object> length_obj, | 1710 // Normalize if the length does not fit in a smi. Fast mode arrays only |
1711 Handle<FixedArrayBase> backing_store) { | 1711 // support smi length. |
1712 Handle<JSArray> array = Handle<JSArray>::cast(obj); | 1712 if (JSArray::SetLengthWouldNormalize(array->GetHeap(), length)) { |
1713 | 1713 Handle<SeededNumberDictionary> dictionary = |
1714 uint32_t length = 0; | 1714 JSObject::NormalizeElements(array); |
1715 CHECK(length_obj->ToArrayLength(&length)); | 1715 DCHECK(!dictionary.is_null()); |
1716 // Fast case: length fits in a smi. | 1716 DictionaryElementsAccessor::SetLengthImpl(array, length, dictionary); |
1717 if (length <= Smi::kMaxValue) { | 1717 } else { |
1718 Handle<Smi> smi(Smi::FromInt(length), obj->GetIsolate()); | 1718 #ifdef DEBUG |
1719 Handle<Object> new_length = | 1719 uint32_t max = Smi::kMaxValue; |
1720 ElementsAccessorSubclass::SetLengthWithoutNormalize(backing_store, | 1720 DCHECK_LE(length, max); |
1721 array, smi, length); | 1721 #endif |
1722 DCHECK(!new_length.is_null()); | 1722 uint32_t new_length = ElementsAccessorSubclass::SetLengthWithoutNormalize( |
1723 | 1723 backing_store, array, length); |
1724 // Even though the proposed length was a smi, new_length could | 1724 DCHECK_EQ(length, new_length); |
1725 // still be a heap number because SetLengthWithoutNormalize doesn't | 1725 array->set_length(Smi::FromInt(new_length)); |
1726 // allow the array length property to drop below the index of | |
1727 // non-deletable elements. | |
1728 DCHECK(new_length->IsSmi() || new_length->IsHeapNumber() || | |
1729 new_length->IsUndefined()); | |
1730 if (new_length->IsSmi()) { | |
1731 array->set_length(*Handle<Smi>::cast(new_length)); | |
1732 return array; | |
1733 } else if (new_length->IsHeapNumber()) { | |
1734 array->set_length(*new_length); | |
1735 return array; | |
1736 } | |
1737 } | 1726 } |
1738 | |
1739 // Slow case: The new length does not fit into a Smi or conversion | |
1740 // to slow elements is needed for other reasons. | |
1741 Handle<SeededNumberDictionary> dictionary = | |
1742 JSObject::NormalizeElements(array); | |
1743 DCHECK(!dictionary.is_null()); | |
1744 | |
1745 Handle<Object> new_length = | |
1746 DictionaryElementsAccessor::SetLengthWithoutNormalize(dictionary, array, | |
1747 length_obj, length); | |
1748 DCHECK(!new_length.is_null()); | |
1749 | |
1750 DCHECK(new_length->IsNumber()); | |
1751 array->set_length(*new_length); | |
1752 return array; | |
1753 } | 1727 } |
1754 | 1728 |
1755 | 1729 |
1756 MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, | 1730 MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, |
1757 Arguments* args) { | 1731 Arguments* args) { |
1758 if (args->length() == 0) { | 1732 if (args->length() == 0) { |
1759 // Optimize the case where there are no parameters passed. | 1733 // Optimize the case where there are no parameters passed. |
1760 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); | 1734 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); |
1761 return array; | 1735 return array; |
1762 | 1736 |
1763 } else if (args->length() == 1 && args->at<Object>(0)->IsNumber()) { | 1737 } else if (args->length() == 1 && args->at<Object>(0)->IsNumber()) { |
1764 uint32_t length; | 1738 uint32_t length; |
1765 if (!args->at<Object>(0)->ToArrayLength(&length)) { | 1739 if (!args->at<Object>(0)->ToArrayLength(&length)) { |
1766 return ThrowArrayLengthRangeError(array->GetIsolate()); | 1740 return ThrowArrayLengthRangeError(array->GetIsolate()); |
1767 } | 1741 } |
1768 | 1742 |
1769 // Optimize the case where there is one argument and the argument is a small | 1743 // Optimize the case where there is one argument and the argument is a small |
1770 // smi. | 1744 // smi. |
1771 if (length > 0 && length < JSObject::kInitialMaxFastElementArray) { | 1745 if (length > 0 && length < JSObject::kInitialMaxFastElementArray) { |
1772 ElementsKind elements_kind = array->GetElementsKind(); | 1746 ElementsKind elements_kind = array->GetElementsKind(); |
1773 JSArray::Initialize(array, length, length); | 1747 JSArray::Initialize(array, length, length); |
1774 | 1748 |
1775 if (!IsFastHoleyElementsKind(elements_kind)) { | 1749 if (!IsFastHoleyElementsKind(elements_kind)) { |
1776 elements_kind = GetHoleyElementsKind(elements_kind); | 1750 elements_kind = GetHoleyElementsKind(elements_kind); |
1777 JSObject::TransitionElementsKind(array, elements_kind); | 1751 JSObject::TransitionElementsKind(array, elements_kind); |
1778 } | 1752 } |
1779 return array; | |
1780 } else if (length == 0) { | 1753 } else if (length == 0) { |
1781 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); | 1754 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); |
1782 return array; | 1755 } else { |
| 1756 // Take the argument as the length. |
| 1757 JSArray::Initialize(array, 0); |
| 1758 JSArray::SetLength(array, length); |
1783 } | 1759 } |
1784 | 1760 return array; |
1785 // Take the argument as the length. | |
1786 JSArray::Initialize(array, 0); | |
1787 return JSArray::SetElementsLength(array, args->at<Object>(0)); | |
1788 } | 1761 } |
1789 | 1762 |
1790 Factory* factory = array->GetIsolate()->factory(); | 1763 Factory* factory = array->GetIsolate()->factory(); |
1791 | 1764 |
1792 // Set length and elements on the array. | 1765 // Set length and elements on the array. |
1793 int number_of_elements = args->length(); | 1766 int number_of_elements = args->length(); |
1794 JSObject::EnsureCanContainElements( | 1767 JSObject::EnsureCanContainElements( |
1795 array, args, 0, number_of_elements, ALLOW_CONVERTED_DOUBLE_ELEMENTS); | 1768 array, args, 0, number_of_elements, ALLOW_CONVERTED_DOUBLE_ELEMENTS); |
1796 | 1769 |
1797 // Allocate an appropriately typed elements array. | 1770 // Allocate an appropriately typed elements array. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1839 break; | 1812 break; |
1840 } | 1813 } |
1841 | 1814 |
1842 array->set_elements(*elms); | 1815 array->set_elements(*elms); |
1843 array->set_length(Smi::FromInt(number_of_elements)); | 1816 array->set_length(Smi::FromInt(number_of_elements)); |
1844 return array; | 1817 return array; |
1845 } | 1818 } |
1846 | 1819 |
1847 } // namespace internal | 1820 } // namespace internal |
1848 } // namespace v8 | 1821 } // namespace v8 |
OLD | NEW |