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/elements.h" | 5 #include "src/elements.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/factory.h" | 9 #include "src/factory.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 } cmp; | 461 } cmp; |
462 Object** start = | 462 Object** start = |
463 reinterpret_cast<Object**>(indices->GetFirstElementAddress()); | 463 reinterpret_cast<Object**>(indices->GetFirstElementAddress()); |
464 std::sort(start, start + sort_size, cmp); | 464 std::sort(start, start + sort_size, cmp); |
465 if (write_barrier_mode != SKIP_WRITE_BARRIER) { | 465 if (write_barrier_mode != SKIP_WRITE_BARRIER) { |
466 FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(indices->GetIsolate()->heap(), *indices, | 466 FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(indices->GetIsolate()->heap(), *indices, |
467 0, sort_size); | 467 0, sort_size); |
468 } | 468 } |
469 } | 469 } |
470 | 470 |
| 471 static Maybe<bool> IncludesValueSlowPath(Isolate* isolate, |
| 472 Handle<JSObject> receiver, |
| 473 Handle<Object> value, |
| 474 uint32_t start_from, uint32_t length) { |
| 475 bool search_for_hole = value->IsUndefined(isolate); |
| 476 for (uint32_t k = start_from; k < length; ++k) { |
| 477 LookupIterator it(isolate, receiver, k); |
| 478 if (!it.IsFound()) { |
| 479 if (search_for_hole) return Just(true); |
| 480 continue; |
| 481 } |
| 482 Handle<Object> element_k; |
| 483 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k, |
| 484 Object::GetProperty(&it), Nothing<bool>()); |
| 485 |
| 486 if (value->SameValueZero(*element_k)) return Just(true); |
| 487 } |
| 488 |
| 489 return Just(false); |
| 490 } |
| 491 |
471 // Base class for element handler implementations. Contains the | 492 // Base class for element handler implementations. Contains the |
472 // the common logic for objects with different ElementsKinds. | 493 // the common logic for objects with different ElementsKinds. |
473 // Subclasses must specialize method for which the element | 494 // Subclasses must specialize method for which the element |
474 // implementation differs from the base class implementation. | 495 // implementation differs from the base class implementation. |
475 // | 496 // |
476 // This class is intended to be used in the following way: | 497 // This class is intended to be used in the following way: |
477 // | 498 // |
478 // class SomeElementsAccessor : | 499 // class SomeElementsAccessor : |
479 // public ElementsAccessorBase<SomeElementsAccessor, | 500 // public ElementsAccessorBase<SomeElementsAccessor, |
480 // BackingStoreClass> { | 501 // BackingStoreClass> { |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 | 1098 |
1078 static uint32_t GetCapacityImpl(JSObject* holder, | 1099 static uint32_t GetCapacityImpl(JSObject* holder, |
1079 FixedArrayBase* backing_store) { | 1100 FixedArrayBase* backing_store) { |
1080 return backing_store->length(); | 1101 return backing_store->length(); |
1081 } | 1102 } |
1082 | 1103 |
1083 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { | 1104 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { |
1084 return Subclass::GetCapacityImpl(holder, backing_store); | 1105 return Subclass::GetCapacityImpl(holder, backing_store); |
1085 } | 1106 } |
1086 | 1107 |
| 1108 static Maybe<bool> IncludesValueImpl(Isolate* isolate, |
| 1109 Handle<JSObject> receiver, |
| 1110 Handle<Object> value, |
| 1111 uint32_t start_from, uint32_t length) { |
| 1112 return IncludesValueSlowPath(isolate, receiver, value, start_from, length); |
| 1113 } |
| 1114 |
| 1115 Maybe<bool> IncludesValue(Isolate* isolate, Handle<JSObject> receiver, |
| 1116 Handle<Object> value, uint32_t start_from, |
| 1117 uint32_t length) final { |
| 1118 return Subclass::IncludesValueImpl(isolate, receiver, value, start_from, |
| 1119 length); |
| 1120 } |
| 1121 |
1087 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, | 1122 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
1088 uint32_t entry) { | 1123 uint32_t entry) { |
1089 return entry; | 1124 return entry; |
1090 } | 1125 } |
1091 | 1126 |
1092 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1127 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
1093 FixedArrayBase* backing_store, | 1128 FixedArrayBase* backing_store, |
1094 uint32_t index, PropertyFilter filter) { | 1129 uint32_t index, PropertyFilter filter) { |
1095 if (IsHoleyElementsKind(kind())) { | 1130 if (IsHoleyElementsKind(kind())) { |
1096 return index < Subclass::GetCapacityImpl(holder, backing_store) && | 1131 return index < Subclass::GetCapacityImpl(holder, backing_store) && |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 if (k == *undefined) continue; | 1448 if (k == *undefined) continue; |
1414 if (k == *the_hole) continue; | 1449 if (k == *the_hole) continue; |
1415 if (dictionary->IsDeleted(i)) continue; | 1450 if (dictionary->IsDeleted(i)) continue; |
1416 Object* value = dictionary->ValueAt(i); | 1451 Object* value = dictionary->ValueAt(i); |
1417 DCHECK(!value->IsTheHole(isolate)); | 1452 DCHECK(!value->IsTheHole(isolate)); |
1418 DCHECK(!value->IsAccessorPair()); | 1453 DCHECK(!value->IsAccessorPair()); |
1419 DCHECK(!value->IsAccessorInfo()); | 1454 DCHECK(!value->IsAccessorInfo()); |
1420 accumulator->AddKey(value, convert); | 1455 accumulator->AddKey(value, convert); |
1421 } | 1456 } |
1422 } | 1457 } |
| 1458 |
| 1459 static bool IncludesValueFastPath(Isolate* isolate, Handle<JSObject> receiver, |
| 1460 Handle<Object> value, uint32_t start_from, |
| 1461 uint32_t length, Maybe<bool>* result) { |
| 1462 DisallowHeapAllocation no_gc; |
| 1463 SeededNumberDictionary* dictionary = |
| 1464 SeededNumberDictionary::cast(receiver->elements()); |
| 1465 int capacity = dictionary->Capacity(); |
| 1466 Object* the_hole = isolate->heap()->the_hole_value(); |
| 1467 Object* undefined = isolate->heap()->undefined_value(); |
| 1468 |
| 1469 // Scan for accessor properties. If accessors are present, then elements |
| 1470 // must be accessed in order via the slow path. |
| 1471 bool found = false; |
| 1472 for (int i = 0; i < capacity; ++i) { |
| 1473 Object* k = dictionary->KeyAt(i); |
| 1474 if (k == the_hole) continue; |
| 1475 if (k == undefined) continue; |
| 1476 |
| 1477 uint32_t index; |
| 1478 if (!k->ToArrayIndex(&index) || index < start_from || index >= length) { |
| 1479 continue; |
| 1480 } |
| 1481 |
| 1482 if (dictionary->DetailsAt(i).type() == ACCESSOR_CONSTANT) { |
| 1483 // Restart from beginning in slow path, otherwise we may observably |
| 1484 // access getters out of order |
| 1485 return false; |
| 1486 } else if (!found) { |
| 1487 Object* element_k = dictionary->ValueAt(i); |
| 1488 if (value->SameValueZero(element_k)) found = true; |
| 1489 } |
| 1490 } |
| 1491 |
| 1492 *result = Just(found); |
| 1493 return true; |
| 1494 } |
| 1495 |
| 1496 static Maybe<bool> IncludesValueImpl(Isolate* isolate, |
| 1497 Handle<JSObject> receiver, |
| 1498 Handle<Object> value, |
| 1499 uint32_t start_from, uint32_t length) { |
| 1500 DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver)); |
| 1501 bool search_for_hole = value->IsUndefined(isolate); |
| 1502 |
| 1503 if (!search_for_hole) { |
| 1504 Maybe<bool> result = Nothing<bool>(); |
| 1505 if (DictionaryElementsAccessor::IncludesValueFastPath( |
| 1506 isolate, receiver, value, start_from, length, &result)) { |
| 1507 return result; |
| 1508 } |
| 1509 } |
| 1510 |
| 1511 Handle<SeededNumberDictionary> dictionary( |
| 1512 SeededNumberDictionary::cast(receiver->elements()), isolate); |
| 1513 // Iterate through entire range, as accessing elements out of order is |
| 1514 // observable |
| 1515 for (uint32_t k = start_from; k < length; ++k) { |
| 1516 int entry = dictionary->FindEntry(k); |
| 1517 if (entry == SeededNumberDictionary::kNotFound) { |
| 1518 if (search_for_hole) return Just(true); |
| 1519 continue; |
| 1520 } |
| 1521 |
| 1522 PropertyDetails details = GetDetailsImpl(receiver->elements(), entry); |
| 1523 switch (details.kind()) { |
| 1524 case kData: { |
| 1525 Object* element_k = dictionary->ValueAt(entry); |
| 1526 if (value->SameValueZero(element_k)) return Just(true); |
| 1527 break; |
| 1528 } |
| 1529 case kAccessor: { |
| 1530 LookupIterator it(isolate, receiver, k, |
| 1531 LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 1532 DCHECK(it.IsFound()); |
| 1533 DCHECK_EQ(it.state(), LookupIterator::ACCESSOR); |
| 1534 Handle<Object> element_k; |
| 1535 |
| 1536 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 1537 isolate, element_k, JSObject::GetPropertyWithAccessor(&it), |
| 1538 Nothing<bool>()); |
| 1539 |
| 1540 if (value->SameValueZero(*element_k)) return Just(true); |
| 1541 |
| 1542 // Some mutation to the prototype elements may have occurred in |
| 1543 // accessor. |
| 1544 if (!JSObject::PrototypeHasNoElements(isolate, *receiver)) { |
| 1545 return IncludesValueSlowPath(isolate, receiver, value, k + 1, |
| 1546 length); |
| 1547 } |
| 1548 break; |
| 1549 } |
| 1550 } |
| 1551 } |
| 1552 return Just(false); |
| 1553 } |
1423 }; | 1554 }; |
1424 | 1555 |
1425 | 1556 |
1426 // Super class for all fast element arrays. | 1557 // Super class for all fast element arrays. |
1427 template <typename Subclass, typename KindTraits> | 1558 template <typename Subclass, typename KindTraits> |
1428 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { | 1559 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { |
1429 public: | 1560 public: |
1430 explicit FastElementsAccessor(const char* name) | 1561 explicit FastElementsAccessor(const char* name) |
1431 : ElementsAccessorBase<Subclass, KindTraits>(name) {} | 1562 : ElementsAccessorBase<Subclass, KindTraits>(name) {} |
1432 | 1563 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1773 DisallowHeapAllocation no_gc; | 1904 DisallowHeapAllocation no_gc; |
1774 heap->MoveElements(FixedArray::cast(*dst_elms), dst_index, src_index, | 1905 heap->MoveElements(FixedArray::cast(*dst_elms), dst_index, src_index, |
1775 len); | 1906 len); |
1776 } | 1907 } |
1777 } | 1908 } |
1778 if (hole_start != hole_end) { | 1909 if (hole_start != hole_end) { |
1779 dst_elms->FillWithHoles(hole_start, hole_end); | 1910 dst_elms->FillWithHoles(hole_start, hole_end); |
1780 } | 1911 } |
1781 } | 1912 } |
1782 | 1913 |
| 1914 static Maybe<bool> IncludesValueImpl(Isolate* isolate, |
| 1915 Handle<JSObject> receiver, |
| 1916 Handle<Object> search_value, |
| 1917 uint32_t start_from, uint32_t length) { |
| 1918 DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver)); |
| 1919 DisallowHeapAllocation no_gc; |
| 1920 FixedArrayBase* elements_base = receiver->elements(); |
| 1921 Object* the_hole = isolate->heap()->the_hole_value(); |
| 1922 Object* undefined = isolate->heap()->undefined_value(); |
| 1923 Object* value = *search_value; |
| 1924 |
| 1925 // Elements beyond the capacity of the backing store treated as undefined. |
| 1926 if (value == undefined && |
| 1927 static_cast<uint32_t>(elements_base->length()) < length) { |
| 1928 return Just(true); |
| 1929 } |
| 1930 |
| 1931 if (start_from >= length) return Just(false); |
| 1932 |
| 1933 length = std::min(static_cast<uint32_t>(elements_base->length()), length); |
| 1934 |
| 1935 if (!value->IsNumber()) { |
| 1936 if (value == undefined) { |
| 1937 // Only FAST_ELEMENTS, FAST_HOLEY_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, and |
| 1938 // FAST_HOLEY_DOUBLE_ELEMENTS can have `undefined` as a value. |
| 1939 if (!IsFastObjectElementsKind(Subclass::kind()) && |
| 1940 !IsFastHoleyElementsKind(Subclass::kind())) { |
| 1941 return Just(false); |
| 1942 } |
| 1943 |
| 1944 // Search for `undefined` or The Hole in FAST_ELEMENTS, |
| 1945 // FAST_HOLEY_ELEMENTS or FAST_HOLEY_SMI_ELEMENTS |
| 1946 if (IsFastSmiOrObjectElementsKind(Subclass::kind())) { |
| 1947 auto elements = FixedArray::cast(receiver->elements()); |
| 1948 |
| 1949 for (uint32_t k = start_from; k < length; ++k) { |
| 1950 Object* element_k = elements->get(k); |
| 1951 |
| 1952 if (IsFastHoleyElementsKind(Subclass::kind()) && |
| 1953 element_k == the_hole) { |
| 1954 return Just(true); |
| 1955 } |
| 1956 if (IsFastObjectElementsKind(Subclass::kind()) && |
| 1957 element_k == undefined) { |
| 1958 return Just(true); |
| 1959 } |
| 1960 } |
| 1961 return Just(false); |
| 1962 } else { |
| 1963 // Seach for The Hole in FAST_HOLEY_DOUBLE_ELEMENTS |
| 1964 DCHECK_EQ(Subclass::kind(), FAST_HOLEY_DOUBLE_ELEMENTS); |
| 1965 auto elements = FixedDoubleArray::cast(receiver->elements()); |
| 1966 |
| 1967 for (uint32_t k = start_from; k < length; ++k) { |
| 1968 if (IsFastHoleyElementsKind(Subclass::kind()) && |
| 1969 elements->is_the_hole(k)) { |
| 1970 return Just(true); |
| 1971 } |
| 1972 } |
| 1973 return Just(false); |
| 1974 } |
| 1975 } else if (!IsFastObjectElementsKind(Subclass::kind())) { |
| 1976 // Search for non-number, non-Undefined value, with either |
| 1977 // FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS or |
| 1978 // FAST_HOLEY_DOUBLE_ELEMENTS. Guaranteed to return false, since these |
| 1979 // elements kinds can only contain Number values or undefined. |
| 1980 return Just(false); |
| 1981 } else { |
| 1982 // Search for non-number, non-Undefined value with either |
| 1983 // FAST_ELEMENTS or FAST_HOLEY_ELEMENTS. |
| 1984 DCHECK(IsFastObjectElementsKind(Subclass::kind())); |
| 1985 auto elements = FixedArray::cast(receiver->elements()); |
| 1986 |
| 1987 for (uint32_t k = start_from; k < length; ++k) { |
| 1988 Object* element_k = elements->get(k); |
| 1989 if (IsFastHoleyElementsKind(Subclass::kind()) && |
| 1990 element_k == the_hole) { |
| 1991 continue; |
| 1992 } |
| 1993 |
| 1994 if (value->SameValueZero(element_k)) return Just(true); |
| 1995 } |
| 1996 return Just(false); |
| 1997 } |
| 1998 } else { |
| 1999 if (!value->IsNaN()) { |
| 2000 double search_value = value->Number(); |
| 2001 if (IsFastDoubleElementsKind(Subclass::kind())) { |
| 2002 // Search for non-NaN Number in FAST_DOUBLE_ELEMENTS or |
| 2003 // FAST_HOLEY_DOUBLE_ELEMENTS --- Skip TheHole, and trust UCOMISD or |
| 2004 // similar operation for result. |
| 2005 auto elements = FixedDoubleArray::cast(receiver->elements()); |
| 2006 |
| 2007 for (uint32_t k = start_from; k < length; ++k) { |
| 2008 if (IsFastHoleyElementsKind(Subclass::kind()) && |
| 2009 elements->is_the_hole(k)) { |
| 2010 continue; |
| 2011 } |
| 2012 if (elements->get_scalar(k) == search_value) return Just(true); |
| 2013 } |
| 2014 return Just(false); |
| 2015 } else { |
| 2016 // Search for non-NaN Number in FAST_ELEMENTS, FAST_HOLEY_ELEMENTS, |
| 2017 // FAST_SMI_ELEMENTS or FAST_HOLEY_SMI_ELEMENTS --- Skip non-Numbers, |
| 2018 // and trust UCOMISD or similar operation for result |
| 2019 auto elements = FixedArray::cast(receiver->elements()); |
| 2020 |
| 2021 for (uint32_t k = start_from; k < length; ++k) { |
| 2022 Object* element_k = elements->get(k); |
| 2023 if (element_k->IsNumber() && element_k->Number() == search_value) { |
| 2024 return Just(true); |
| 2025 } |
| 2026 } |
| 2027 return Just(false); |
| 2028 } |
| 2029 } else { |
| 2030 // Search for NaN --- NaN cannot be represented with Smi elements, so |
| 2031 // abort if ElementsKind is FAST_SMI_ELEMENTS or FAST_HOLEY_SMI_ELEMENTS |
| 2032 if (IsFastSmiElementsKind(Subclass::kind())) return Just(false); |
| 2033 |
| 2034 if (IsFastDoubleElementsKind(Subclass::kind())) { |
| 2035 // Search for NaN in FAST_DOUBLE_ELEMENTS or |
| 2036 // FAST_HOLEY_DOUBLE_ELEMENTS --- Skip The Hole and trust |
| 2037 // std::isnan(elementK) for result |
| 2038 auto elements = FixedDoubleArray::cast(receiver->elements()); |
| 2039 |
| 2040 for (uint32_t k = start_from; k < length; ++k) { |
| 2041 if (IsFastHoleyElementsKind(Subclass::kind()) && |
| 2042 elements->is_the_hole(k)) { |
| 2043 continue; |
| 2044 } |
| 2045 if (std::isnan(elements->get_scalar(k))) return Just(true); |
| 2046 } |
| 2047 return Just(false); |
| 2048 } else { |
| 2049 // Search for NaN in FAST_ELEMENTS, FAST_HOLEY_ELEMENTS, |
| 2050 // FAST_SMI_ELEMENTS or FAST_HOLEY_SMI_ELEMENTS. Return true if |
| 2051 // elementK->IsHeapNumber() && std::isnan(elementK->Number()) |
| 2052 DCHECK(IsFastSmiOrObjectElementsKind(Subclass::kind())); |
| 2053 auto elements = FixedArray::cast(receiver->elements()); |
| 2054 |
| 2055 for (uint32_t k = start_from; k < length; ++k) { |
| 2056 if (elements->get(k)->IsNaN()) return Just(true); |
| 2057 } |
| 2058 return Just(false); |
| 2059 } |
| 2060 } |
| 2061 } |
| 2062 } |
| 2063 |
1783 private: | 2064 private: |
1784 // SpliceShrinkStep might modify the backing_store. | 2065 // SpliceShrinkStep might modify the backing_store. |
1785 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, | 2066 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, |
1786 Handle<FixedArrayBase> backing_store, | 2067 Handle<FixedArrayBase> backing_store, |
1787 uint32_t start, uint32_t delete_count, | 2068 uint32_t start, uint32_t delete_count, |
1788 uint32_t add_count, uint32_t len, | 2069 uint32_t add_count, uint32_t len, |
1789 uint32_t new_length) { | 2070 uint32_t new_length) { |
1790 const int move_left_count = len - delete_count - start; | 2071 const int move_left_count = len - delete_count - start; |
1791 const int move_left_dst_index = start + add_count; | 2072 const int move_left_dst_index = start + add_count; |
1792 Subclass::MoveElements(isolate, receiver, backing_store, | 2073 Subclass::MoveElements(isolate, receiver, backing_store, |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2118 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { | 2399 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { |
2119 public: | 2400 public: |
2120 explicit FastHoleyDoubleElementsAccessor(const char* name) | 2401 explicit FastHoleyDoubleElementsAccessor(const char* name) |
2121 : FastDoubleElementsAccessor< | 2402 : FastDoubleElementsAccessor< |
2122 FastHoleyDoubleElementsAccessor, | 2403 FastHoleyDoubleElementsAccessor, |
2123 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} | 2404 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} |
2124 }; | 2405 }; |
2125 | 2406 |
2126 | 2407 |
2127 // Super class for all external element arrays. | 2408 // Super class for all external element arrays. |
2128 template<ElementsKind Kind> | 2409 template <ElementsKind Kind, typename ctype> |
2129 class TypedElementsAccessor | 2410 class TypedElementsAccessor |
2130 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, | 2411 : public ElementsAccessorBase<TypedElementsAccessor<Kind, ctype>, |
2131 ElementsKindTraits<Kind> > { | 2412 ElementsKindTraits<Kind>> { |
2132 public: | 2413 public: |
2133 explicit TypedElementsAccessor(const char* name) | 2414 explicit TypedElementsAccessor(const char* name) |
2134 : ElementsAccessorBase<AccessorClass, | 2415 : ElementsAccessorBase<AccessorClass, |
2135 ElementsKindTraits<Kind> >(name) {} | 2416 ElementsKindTraits<Kind> >(name) {} |
2136 | 2417 |
2137 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 2418 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
2138 typedef TypedElementsAccessor<Kind> AccessorClass; | 2419 typedef TypedElementsAccessor<Kind, ctype> AccessorClass; |
2139 | 2420 |
2140 static inline void SetImpl(Handle<JSObject> holder, uint32_t entry, | 2421 static inline void SetImpl(Handle<JSObject> holder, uint32_t entry, |
2141 Object* value) { | 2422 Object* value) { |
2142 SetImpl(holder->elements(), entry, value); | 2423 SetImpl(holder->elements(), entry, value); |
2143 } | 2424 } |
2144 | 2425 |
2145 static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry, | 2426 static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry, |
2146 Object* value) { | 2427 Object* value) { |
2147 BackingStore::cast(backing_store)->SetValue(entry, value); | 2428 BackingStore::cast(backing_store)->SetValue(entry, value); |
2148 } | 2429 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2234 Handle<Object> value = AccessorClass::GetImpl(*elements, index); | 2515 Handle<Object> value = AccessorClass::GetImpl(*elements, index); |
2235 if (get_entries) { | 2516 if (get_entries) { |
2236 value = MakeEntryPair(isolate, index, value); | 2517 value = MakeEntryPair(isolate, index, value); |
2237 } | 2518 } |
2238 values_or_entries->set(count++, *value); | 2519 values_or_entries->set(count++, *value); |
2239 } | 2520 } |
2240 } | 2521 } |
2241 *nof_items = count; | 2522 *nof_items = count; |
2242 return Just(true); | 2523 return Just(true); |
2243 } | 2524 } |
| 2525 |
| 2526 static Maybe<bool> IncludesValueImpl(Isolate* isolate, |
| 2527 Handle<JSObject> receiver, |
| 2528 Handle<Object> value, |
| 2529 uint32_t start_from, uint32_t length) { |
| 2530 DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver)); |
| 2531 DisallowHeapAllocation no_gc; |
| 2532 |
| 2533 BackingStore* elements = BackingStore::cast(receiver->elements()); |
| 2534 if (value->IsUndefined(isolate) && |
| 2535 length > static_cast<uint32_t>(elements->length())) { |
| 2536 return Just(true); |
| 2537 } |
| 2538 if (!value->IsNumber()) return Just(false); |
| 2539 |
| 2540 double search_value = value->Number(); |
| 2541 |
| 2542 if (!std::isfinite(search_value)) { |
| 2543 // Integral types cannot represent +Inf or NaN |
| 2544 if (AccessorClass::kind() < FLOAT32_ELEMENTS || |
| 2545 AccessorClass::kind() > FLOAT64_ELEMENTS) { |
| 2546 return Just(false); |
| 2547 } |
| 2548 } else if (search_value < std::numeric_limits<ctype>::lowest() || |
| 2549 search_value > std::numeric_limits<ctype>::max()) { |
| 2550 // Return false if value can't be represented in this space |
| 2551 return Just(false); |
| 2552 } |
| 2553 |
| 2554 if (!std::isnan(search_value)) { |
| 2555 for (uint32_t k = start_from; k < length; ++k) { |
| 2556 double element_k = elements->get_scalar(k); |
| 2557 if (element_k == search_value) return Just(true); |
| 2558 } |
| 2559 return Just(false); |
| 2560 } else { |
| 2561 for (uint32_t k = start_from; k < length; ++k) { |
| 2562 double element_k = elements->get_scalar(k); |
| 2563 if (std::isnan(element_k)) return Just(true); |
| 2564 } |
| 2565 return Just(false); |
| 2566 } |
| 2567 } |
2244 }; | 2568 }; |
2245 | 2569 |
2246 | 2570 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ |
2247 | 2571 typedef TypedElementsAccessor<TYPE##_ELEMENTS, ctype> \ |
2248 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ | |
2249 typedef TypedElementsAccessor<TYPE##_ELEMENTS > \ | |
2250 Fixed##Type##ElementsAccessor; | 2572 Fixed##Type##ElementsAccessor; |
2251 | 2573 |
2252 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) | 2574 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) |
2253 #undef FIXED_ELEMENTS_ACCESSOR | 2575 #undef FIXED_ELEMENTS_ACCESSOR |
2254 | 2576 |
2255 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> | 2577 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> |
2256 class SloppyArgumentsElementsAccessor | 2578 class SloppyArgumentsElementsAccessor |
2257 : public ElementsAccessorBase<Subclass, KindTraits> { | 2579 : public ElementsAccessorBase<Subclass, KindTraits> { |
2258 public: | 2580 public: |
2259 explicit SloppyArgumentsElementsAccessor(const char* name) | 2581 explicit SloppyArgumentsElementsAccessor(const char* name) |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2474 list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 2796 list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER); |
2475 } | 2797 } |
2476 insertion_index++; | 2798 insertion_index++; |
2477 } | 2799 } |
2478 | 2800 |
2479 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); | 2801 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); |
2480 return ArgumentsAccessor::DirectCollectElementIndicesImpl( | 2802 return ArgumentsAccessor::DirectCollectElementIndicesImpl( |
2481 isolate, object, store, convert, filter, list, nof_indices, | 2803 isolate, object, store, convert, filter, list, nof_indices, |
2482 insertion_index); | 2804 insertion_index); |
2483 } | 2805 } |
| 2806 |
| 2807 static Maybe<bool> IncludesValueImpl(Isolate* isolate, |
| 2808 Handle<JSObject> object, |
| 2809 Handle<Object> value, |
| 2810 uint32_t start_from, uint32_t length) { |
| 2811 DCHECK(JSObject::PrototypeHasNoElements(isolate, *object)); |
| 2812 Handle<Map> original_map = handle(object->map(), isolate); |
| 2813 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
| 2814 bool search_for_hole = value->IsUndefined(isolate); |
| 2815 |
| 2816 for (uint32_t k = start_from; k < length; ++k) { |
| 2817 uint32_t entry = |
| 2818 GetEntryForIndexImpl(*object, parameter_map, k, ALL_PROPERTIES); |
| 2819 if (entry == kMaxUInt32) { |
| 2820 if (search_for_hole) return Just(true); |
| 2821 continue; |
| 2822 } |
| 2823 |
| 2824 Handle<Object> element_k = GetImpl(parameter_map, entry); |
| 2825 |
| 2826 if (element_k->IsAccessorPair()) { |
| 2827 LookupIterator it(isolate, object, k, LookupIterator::OWN); |
| 2828 DCHECK(it.IsFound()); |
| 2829 DCHECK_EQ(it.state(), LookupIterator::ACCESSOR); |
| 2830 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k, |
| 2831 Object::GetPropertyWithAccessor(&it), |
| 2832 Nothing<bool>()); |
| 2833 |
| 2834 if (value->SameValueZero(*element_k)) return Just(true); |
| 2835 |
| 2836 if (object->map() != *original_map) { |
| 2837 // Some mutation occurred in accessor. Abort "fast" path |
| 2838 return IncludesValueSlowPath(isolate, object, value, k + 1, length); |
| 2839 } |
| 2840 } else if (value->SameValueZero(*element_k)) { |
| 2841 return Just(true); |
| 2842 } |
| 2843 } |
| 2844 return Just(false); |
| 2845 } |
2484 }; | 2846 }; |
2485 | 2847 |
2486 | 2848 |
2487 class SlowSloppyArgumentsElementsAccessor | 2849 class SlowSloppyArgumentsElementsAccessor |
2488 : public SloppyArgumentsElementsAccessor< | 2850 : public SloppyArgumentsElementsAccessor< |
2489 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | 2851 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
2490 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { | 2852 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { |
2491 public: | 2853 public: |
2492 explicit SlowSloppyArgumentsElementsAccessor(const char* name) | 2854 explicit SlowSloppyArgumentsElementsAccessor(const char* name) |
2493 : SloppyArgumentsElementsAccessor< | 2855 : SloppyArgumentsElementsAccessor< |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3081 insertion_index += len; | 3443 insertion_index += len; |
3082 } | 3444 } |
3083 | 3445 |
3084 DCHECK_EQ(insertion_index, result_len); | 3446 DCHECK_EQ(insertion_index, result_len); |
3085 return result_array; | 3447 return result_array; |
3086 } | 3448 } |
3087 | 3449 |
3088 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3450 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
3089 } // namespace internal | 3451 } // namespace internal |
3090 } // namespace v8 | 3452 } // namespace v8 |
OLD | NEW |