| 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 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 SetFastElementsCapacityAndLength(array, capacity, length); | 662 SetFastElementsCapacityAndLength(array, capacity, length); |
| 663 } | 663 } |
| 664 | 664 |
| 665 static void SetFastElementsCapacityAndLength( | 665 static void SetFastElementsCapacityAndLength( |
| 666 Handle<JSObject> obj, | 666 Handle<JSObject> obj, |
| 667 int capacity, | 667 int capacity, |
| 668 int length) { | 668 int length) { |
| 669 UNIMPLEMENTED(); | 669 UNIMPLEMENTED(); |
| 670 } | 670 } |
| 671 | 671 |
| 672 MUST_USE_RESULT virtual MaybeHandle<Object> Delete( | 672 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
| 673 Handle<JSObject> obj, uint32_t key, | 673 LanguageMode language_mode) override = 0; |
| 674 LanguageMode language_mode) override = 0; | |
| 675 | 674 |
| 676 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 675 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 677 FixedArrayBase* to, ElementsKind from_kind, | 676 FixedArrayBase* to, ElementsKind from_kind, |
| 678 uint32_t to_start, int packed_size, | 677 uint32_t to_start, int packed_size, |
| 679 int copy_size) { | 678 int copy_size) { |
| 680 UNREACHABLE(); | 679 UNREACHABLE(); |
| 681 } | 680 } |
| 682 | 681 |
| 683 virtual void CopyElements(Handle<FixedArrayBase> from, uint32_t from_start, | 682 virtual void CopyElements(Handle<FixedArrayBase> from, uint32_t from_start, |
| 684 ElementsKind from_kind, Handle<FixedArrayBase> to, | 683 ElementsKind from_kind, Handle<FixedArrayBase> to, |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 912 | 911 |
| 913 // Check whether the backing store should be expanded. | 912 // Check whether the backing store should be expanded. |
| 914 uint32_t min = JSObject::NewElementsCapacity(old_capacity); | 913 uint32_t min = JSObject::NewElementsCapacity(old_capacity); |
| 915 uint32_t new_capacity = length > min ? length : min; | 914 uint32_t new_capacity = length > min ? length : min; |
| 916 FastElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 915 FastElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
| 917 array, new_capacity, length); | 916 array, new_capacity, length); |
| 918 JSObject::ValidateElements(array); | 917 JSObject::ValidateElements(array); |
| 919 return length_object; | 918 return length_object; |
| 920 } | 919 } |
| 921 | 920 |
| 922 static MaybeHandle<Object> DeleteCommon(Handle<JSObject> obj, uint32_t key, | 921 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
| 923 LanguageMode language_mode) { | 922 LanguageMode language_mode) { |
| 924 DCHECK(obj->HasFastSmiOrObjectElements() || | 923 DCHECK(obj->HasFastSmiOrObjectElements() || |
| 925 obj->HasFastDoubleElements() || | 924 obj->HasFastDoubleElements() || |
| 926 obj->HasFastArgumentsElements()); | 925 obj->HasFastArgumentsElements()); |
| 927 Isolate* isolate = obj->GetIsolate(); | 926 Isolate* isolate = obj->GetIsolate(); |
| 928 Heap* heap = obj->GetHeap(); | 927 Heap* heap = obj->GetHeap(); |
| 929 Handle<FixedArrayBase> elements(obj->elements()); | 928 Handle<FixedArrayBase> elements(obj->elements()); |
| 930 if (*elements == heap->empty_fixed_array()) { | 929 if (*elements == heap->empty_fixed_array()) return; |
| 931 return isolate->factory()->true_value(); | 930 |
| 932 } | |
| 933 Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements); | 931 Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements); |
| 934 bool is_sloppy_arguments_elements_map = | 932 bool is_sloppy_arguments_elements_map = |
| 935 backing_store->map() == heap->sloppy_arguments_elements_map(); | 933 backing_store->map() == heap->sloppy_arguments_elements_map(); |
| 936 if (is_sloppy_arguments_elements_map) { | 934 if (is_sloppy_arguments_elements_map) { |
| 937 backing_store = handle( | 935 backing_store = handle( |
| 938 BackingStore::cast(Handle<FixedArray>::cast(backing_store)->get(1)), | 936 BackingStore::cast(Handle<FixedArray>::cast(backing_store)->get(1)), |
| 939 isolate); | 937 isolate); |
| 940 } | 938 } |
| 941 uint32_t length = static_cast<uint32_t>( | 939 uint32_t length = static_cast<uint32_t>( |
| 942 obj->IsJSArray() | 940 obj->IsJSArray() |
| 943 ? Smi::cast(Handle<JSArray>::cast(obj)->length())->value() | 941 ? Smi::cast(Handle<JSArray>::cast(obj)->length())->value() |
| 944 : backing_store->length()); | 942 : backing_store->length()); |
| 945 if (key < length) { | 943 if (key < length) { |
| 946 if (obj->map()->is_strong() && !backing_store->is_the_hole(key)) { | |
| 947 if (is_strict(language_mode)) { | |
| 948 Handle<Object> name = isolate->factory()->NewNumberFromUint(key); | |
| 949 THROW_NEW_ERROR( | |
| 950 isolate, | |
| 951 NewTypeError(MessageTemplate::kStrongDeleteProperty, obj, name), | |
| 952 Object); | |
| 953 } | |
| 954 return isolate->factory()->false_value(); | |
| 955 } | |
| 956 if (!is_sloppy_arguments_elements_map) { | 944 if (!is_sloppy_arguments_elements_map) { |
| 957 ElementsKind kind = KindTraits::Kind; | 945 ElementsKind kind = KindTraits::Kind; |
| 958 if (IsFastPackedElementsKind(kind)) { | 946 if (IsFastPackedElementsKind(kind)) { |
| 959 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind)); | 947 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind)); |
| 960 } | 948 } |
| 961 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { | 949 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { |
| 962 Handle<Object> writable = JSObject::EnsureWritableFastElements(obj); | 950 Handle<Object> writable = JSObject::EnsureWritableFastElements(obj); |
| 963 backing_store = Handle<BackingStore>::cast(writable); | 951 backing_store = Handle<BackingStore>::cast(writable); |
| 964 } | 952 } |
| 965 } | 953 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 977 for (int i = 0; i < backing_store->length(); ++i) { | 965 for (int i = 0; i < backing_store->length(); ++i) { |
| 978 if (!backing_store->is_the_hole(i)) ++num_used; | 966 if (!backing_store->is_the_hole(i)) ++num_used; |
| 979 // Bail out early if more than 1/4 is used. | 967 // Bail out early if more than 1/4 is used. |
| 980 if (4 * num_used > backing_store->length()) break; | 968 if (4 * num_used > backing_store->length()) break; |
| 981 } | 969 } |
| 982 if (4 * num_used <= backing_store->length()) { | 970 if (4 * num_used <= backing_store->length()) { |
| 983 JSObject::NormalizeElements(obj); | 971 JSObject::NormalizeElements(obj); |
| 984 } | 972 } |
| 985 } | 973 } |
| 986 } | 974 } |
| 987 return isolate->factory()->true_value(); | |
| 988 } | 975 } |
| 989 | 976 |
| 990 virtual MaybeHandle<Object> Delete(Handle<JSObject> obj, uint32_t key, | 977 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
| 991 LanguageMode language_mode) final { | 978 LanguageMode language_mode) final { |
| 992 return DeleteCommon(obj, key, language_mode); | 979 DeleteCommon(obj, key, language_mode); |
| 993 } | 980 } |
| 994 | 981 |
| 995 static bool HasElementImpl( | 982 static bool HasElementImpl( |
| 996 Handle<JSObject> holder, | 983 Handle<JSObject> holder, |
| 997 uint32_t key, | 984 uint32_t key, |
| 998 Handle<FixedArrayBase> backing_store) { | 985 Handle<FixedArrayBase> backing_store) { |
| 999 if (key >= static_cast<uint32_t>(backing_store->length())) { | 986 if (key >= static_cast<uint32_t>(backing_store->length())) { |
| 1000 return false; | 987 return false; |
| 1001 } | 988 } |
| 1002 return !Handle<BackingStore>::cast(backing_store)->is_the_hole(key); | 989 return !Handle<BackingStore>::cast(backing_store)->is_the_hole(key); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1299 | 1286 |
| 1300 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( | 1287 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( |
| 1301 Handle<JSObject> obj, | 1288 Handle<JSObject> obj, |
| 1302 Handle<Object> length, | 1289 Handle<Object> length, |
| 1303 Handle<FixedArrayBase> backing_store) { | 1290 Handle<FixedArrayBase> backing_store) { |
| 1304 // External arrays do not support changing their length. | 1291 // External arrays do not support changing their length. |
| 1305 UNREACHABLE(); | 1292 UNREACHABLE(); |
| 1306 return obj; | 1293 return obj; |
| 1307 } | 1294 } |
| 1308 | 1295 |
| 1309 MUST_USE_RESULT virtual MaybeHandle<Object> Delete( | 1296 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
| 1310 Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final { | 1297 LanguageMode language_mode) final { |
| 1311 // External arrays always ignore deletes. | 1298 // External arrays always ignore deletes. |
| 1312 return obj->GetIsolate()->factory()->true_value(); | |
| 1313 } | 1299 } |
| 1314 | 1300 |
| 1315 static bool HasElementImpl(Handle<JSObject> holder, uint32_t key, | 1301 static bool HasElementImpl(Handle<JSObject> holder, uint32_t key, |
| 1316 Handle<FixedArrayBase> backing_store) { | 1302 Handle<FixedArrayBase> backing_store) { |
| 1317 uint32_t capacity = AccessorClass::GetCapacityImpl(*holder, *backing_store); | 1303 uint32_t capacity = AccessorClass::GetCapacityImpl(*holder, *backing_store); |
| 1318 return key < capacity; | 1304 return key < capacity; |
| 1319 } | 1305 } |
| 1320 | 1306 |
| 1321 static uint32_t GetCapacityImpl(JSObject* holder, | 1307 static uint32_t GetCapacityImpl(JSObject* holder, |
| 1322 FixedArrayBase* backing_store) { | 1308 FixedArrayBase* backing_store) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1402 } | 1388 } |
| 1403 } | 1389 } |
| 1404 } | 1390 } |
| 1405 | 1391 |
| 1406 // Update the number of elements. | 1392 // Update the number of elements. |
| 1407 dict->ElementsRemoved(removed_entries); | 1393 dict->ElementsRemoved(removed_entries); |
| 1408 } | 1394 } |
| 1409 return length_object; | 1395 return length_object; |
| 1410 } | 1396 } |
| 1411 | 1397 |
| 1412 MUST_USE_RESULT static MaybeHandle<Object> DeleteCommon( | 1398 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
| 1413 Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) { | 1399 LanguageMode language_mode) { |
| 1414 Isolate* isolate = obj->GetIsolate(); | 1400 Isolate* isolate = obj->GetIsolate(); |
| 1415 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), | 1401 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), |
| 1416 isolate); | 1402 isolate); |
| 1417 bool is_arguments = | 1403 bool is_arguments = |
| 1418 (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS); | 1404 (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS); |
| 1419 if (is_arguments) { | 1405 if (is_arguments) { |
| 1420 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); | 1406 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); |
| 1421 } | 1407 } |
| 1422 Handle<SeededNumberDictionary> dictionary = | 1408 Handle<SeededNumberDictionary> dictionary = |
| 1423 Handle<SeededNumberDictionary>::cast(backing_store); | 1409 Handle<SeededNumberDictionary>::cast(backing_store); |
| 1424 int entry = dictionary->FindEntry(key); | 1410 int entry = dictionary->FindEntry(key); |
| 1425 if (entry != SeededNumberDictionary::kNotFound) { | 1411 if (entry != SeededNumberDictionary::kNotFound) { |
| 1426 Handle<Object> result; | 1412 Handle<Object> result = |
| 1427 bool strong = obj->map()->is_strong(); | 1413 SeededNumberDictionary::DeleteProperty(dictionary, entry); |
| 1428 if (!strong) { | 1414 USE(result); |
| 1429 result = SeededNumberDictionary::DeleteProperty(dictionary, entry); | 1415 DCHECK(result->IsTrue()); |
| 1430 } | |
| 1431 if (strong || *result == *isolate->factory()->false_value()) { | |
| 1432 // Fail if the property is not configurable, or on a strong object. | |
| 1433 if (is_strict(language_mode)) { | |
| 1434 Handle<Object> name = isolate->factory()->NewNumberFromUint(key); | |
| 1435 if (strong) { | |
| 1436 THROW_NEW_ERROR( | |
| 1437 isolate, | |
| 1438 NewTypeError(MessageTemplate::kStrongDeleteProperty, obj, name), | |
| 1439 Object); | |
| 1440 } | |
| 1441 THROW_NEW_ERROR( | |
| 1442 isolate, | |
| 1443 NewTypeError(MessageTemplate::kStrictDeleteProperty, name, obj), | |
| 1444 Object); | |
| 1445 } | |
| 1446 return isolate->factory()->false_value(); | |
| 1447 } | |
| 1448 Handle<FixedArray> new_elements = | 1416 Handle<FixedArray> new_elements = |
| 1449 SeededNumberDictionary::Shrink(dictionary, key); | 1417 SeededNumberDictionary::Shrink(dictionary, key); |
| 1450 | 1418 |
| 1451 if (is_arguments) { | 1419 if (is_arguments) { |
| 1452 FixedArray::cast(obj->elements())->set(1, *new_elements); | 1420 FixedArray::cast(obj->elements())->set(1, *new_elements); |
| 1453 } else { | 1421 } else { |
| 1454 obj->set_elements(*new_elements); | 1422 obj->set_elements(*new_elements); |
| 1455 } | 1423 } |
| 1456 } | 1424 } |
| 1457 return isolate->factory()->true_value(); | |
| 1458 } | 1425 } |
| 1459 | 1426 |
| 1460 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 1427 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 1461 FixedArrayBase* to, ElementsKind from_kind, | 1428 FixedArrayBase* to, ElementsKind from_kind, |
| 1462 uint32_t to_start, int packed_size, | 1429 uint32_t to_start, int packed_size, |
| 1463 int copy_size) { | 1430 int copy_size) { |
| 1464 UNREACHABLE(); | 1431 UNREACHABLE(); |
| 1465 } | 1432 } |
| 1466 | 1433 |
| 1467 | 1434 |
| 1468 protected: | 1435 protected: |
| 1469 friend class ElementsAccessorBase<DictionaryElementsAccessor, | 1436 friend class ElementsAccessorBase<DictionaryElementsAccessor, |
| 1470 ElementsKindTraits<DICTIONARY_ELEMENTS> >; | 1437 ElementsKindTraits<DICTIONARY_ELEMENTS> >; |
| 1471 | 1438 |
| 1472 MUST_USE_RESULT virtual MaybeHandle<Object> Delete( | 1439 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
| 1473 Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final { | 1440 LanguageMode language_mode) final { |
| 1474 return DeleteCommon(obj, key, language_mode); | 1441 DeleteCommon(obj, key, language_mode); |
| 1475 } | 1442 } |
| 1476 | 1443 |
| 1477 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1444 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, |
| 1478 Handle<FixedArrayBase> store) { | 1445 Handle<FixedArrayBase> store) { |
| 1479 Handle<SeededNumberDictionary> backing_store = | 1446 Handle<SeededNumberDictionary> backing_store = |
| 1480 Handle<SeededNumberDictionary>::cast(store); | 1447 Handle<SeededNumberDictionary>::cast(store); |
| 1481 Isolate* isolate = backing_store->GetIsolate(); | 1448 Isolate* isolate = backing_store->GetIsolate(); |
| 1482 int entry = backing_store->FindEntry(key); | 1449 int entry = backing_store->FindEntry(key); |
| 1483 if (entry != SeededNumberDictionary::kNotFound) { | 1450 if (entry != SeededNumberDictionary::kNotFound) { |
| 1484 return handle(backing_store->ValueAt(entry), isolate); | 1451 return handle(backing_store->ValueAt(entry), isolate); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1624 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( | 1591 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( |
| 1625 Handle<JSObject> obj, | 1592 Handle<JSObject> obj, |
| 1626 Handle<Object> length, | 1593 Handle<Object> length, |
| 1627 Handle<FixedArrayBase> parameter_map) { | 1594 Handle<FixedArrayBase> parameter_map) { |
| 1628 // TODO(mstarzinger): This was never implemented but will be used once we | 1595 // TODO(mstarzinger): This was never implemented but will be used once we |
| 1629 // correctly implement [[DefineOwnProperty]] on arrays. | 1596 // correctly implement [[DefineOwnProperty]] on arrays. |
| 1630 UNIMPLEMENTED(); | 1597 UNIMPLEMENTED(); |
| 1631 return obj; | 1598 return obj; |
| 1632 } | 1599 } |
| 1633 | 1600 |
| 1634 MUST_USE_RESULT virtual MaybeHandle<Object> Delete( | 1601 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
| 1635 Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final { | 1602 LanguageMode language_mode) final { |
| 1636 Isolate* isolate = obj->GetIsolate(); | 1603 Isolate* isolate = obj->GetIsolate(); |
| 1637 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); | 1604 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); |
| 1638 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); | 1605 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); |
| 1639 if (!probe->IsTheHole()) { | 1606 if (!probe->IsTheHole()) { |
| 1640 // TODO(kmillikin): We could check if this was the last aliased | 1607 // TODO(kmillikin): We could check if this was the last aliased |
| 1641 // parameter, and revert to normal elements in that case. That | 1608 // parameter, and revert to normal elements in that case. That |
| 1642 // would enable GC of the context. | 1609 // would enable GC of the context. |
| 1643 parameter_map->set_the_hole(key + 2); | 1610 parameter_map->set_the_hole(key + 2); |
| 1644 } else { | 1611 } else { |
| 1645 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | 1612 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); |
| 1646 if (arguments->IsDictionary()) { | 1613 if (arguments->IsDictionary()) { |
| 1647 return DictionaryElementsAccessor::DeleteCommon(obj, key, | 1614 DictionaryElementsAccessor::DeleteCommon(obj, key, language_mode); |
| 1648 language_mode); | |
| 1649 } else { | 1615 } else { |
| 1650 // It's difficult to access the version of DeleteCommon that is declared | 1616 // It's difficult to access the version of DeleteCommon that is declared |
| 1651 // in the templatized super class, call the concrete implementation in | 1617 // in the templatized super class, call the concrete implementation in |
| 1652 // the class for the most generalized ElementsKind subclass. | 1618 // the class for the most generalized ElementsKind subclass. |
| 1653 return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, | 1619 FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode); |
| 1654 language_mode); | |
| 1655 } | 1620 } |
| 1656 } | 1621 } |
| 1657 return isolate->factory()->true_value(); | |
| 1658 } | 1622 } |
| 1659 | 1623 |
| 1660 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 1624 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 1661 FixedArrayBase* to, ElementsKind from_kind, | 1625 FixedArrayBase* to, ElementsKind from_kind, |
| 1662 uint32_t to_start, int packed_size, | 1626 uint32_t to_start, int packed_size, |
| 1663 int copy_size) { | 1627 int copy_size) { |
| 1664 UNREACHABLE(); | 1628 UNREACHABLE(); |
| 1665 } | 1629 } |
| 1666 | 1630 |
| 1667 static uint32_t GetCapacityImpl(JSObject* holder, | 1631 static uint32_t GetCapacityImpl(JSObject* holder, |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1916 break; | 1880 break; |
| 1917 } | 1881 } |
| 1918 | 1882 |
| 1919 array->set_elements(*elms); | 1883 array->set_elements(*elms); |
| 1920 array->set_length(Smi::FromInt(number_of_elements)); | 1884 array->set_length(Smi::FromInt(number_of_elements)); |
| 1921 return array; | 1885 return array; |
| 1922 } | 1886 } |
| 1923 | 1887 |
| 1924 } // namespace internal | 1888 } // namespace internal |
| 1925 } // namespace v8 | 1889 } // namespace v8 |
| OLD | NEW |