| 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 |