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 | |
492 // Base class for element handler implementations. Contains the | 471 // Base class for element handler implementations. Contains the |
493 // the common logic for objects with different ElementsKinds. | 472 // the common logic for objects with different ElementsKinds. |
494 // Subclasses must specialize method for which the element | 473 // Subclasses must specialize method for which the element |
495 // implementation differs from the base class implementation. | 474 // implementation differs from the base class implementation. |
496 // | 475 // |
497 // This class is intended to be used in the following way: | 476 // This class is intended to be used in the following way: |
498 // | 477 // |
499 // class SomeElementsAccessor : | 478 // class SomeElementsAccessor : |
500 // public ElementsAccessorBase<SomeElementsAccessor, | 479 // public ElementsAccessorBase<SomeElementsAccessor, |
501 // BackingStoreClass> { | 480 // BackingStoreClass> { |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1098 | 1077 |
1099 static uint32_t GetCapacityImpl(JSObject* holder, | 1078 static uint32_t GetCapacityImpl(JSObject* holder, |
1100 FixedArrayBase* backing_store) { | 1079 FixedArrayBase* backing_store) { |
1101 return backing_store->length(); | 1080 return backing_store->length(); |
1102 } | 1081 } |
1103 | 1082 |
1104 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { | 1083 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { |
1105 return Subclass::GetCapacityImpl(holder, backing_store); | 1084 return Subclass::GetCapacityImpl(holder, backing_store); |
1106 } | 1085 } |
1107 | 1086 |
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 | |
1122 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, | 1087 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
1123 uint32_t entry) { | 1088 uint32_t entry) { |
1124 return entry; | 1089 return entry; |
1125 } | 1090 } |
1126 | 1091 |
1127 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1092 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
1128 FixedArrayBase* backing_store, | 1093 FixedArrayBase* backing_store, |
1129 uint32_t index, PropertyFilter filter) { | 1094 uint32_t index, PropertyFilter filter) { |
1130 if (IsHoleyElementsKind(kind())) { | 1095 if (IsHoleyElementsKind(kind())) { |
1131 return index < Subclass::GetCapacityImpl(holder, backing_store) && | 1096 return index < Subclass::GetCapacityImpl(holder, backing_store) && |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1448 if (k == *undefined) continue; | 1413 if (k == *undefined) continue; |
1449 if (k == *the_hole) continue; | 1414 if (k == *the_hole) continue; |
1450 if (dictionary->IsDeleted(i)) continue; | 1415 if (dictionary->IsDeleted(i)) continue; |
1451 Object* value = dictionary->ValueAt(i); | 1416 Object* value = dictionary->ValueAt(i); |
1452 DCHECK(!value->IsTheHole(isolate)); | 1417 DCHECK(!value->IsTheHole(isolate)); |
1453 DCHECK(!value->IsAccessorPair()); | 1418 DCHECK(!value->IsAccessorPair()); |
1454 DCHECK(!value->IsAccessorInfo()); | 1419 DCHECK(!value->IsAccessorInfo()); |
1455 accumulator->AddKey(value, convert); | 1420 accumulator->AddKey(value, convert); |
1456 } | 1421 } |
1457 } | 1422 } |
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 } | |
1554 }; | 1423 }; |
1555 | 1424 |
1556 | 1425 |
1557 // Super class for all fast element arrays. | 1426 // Super class for all fast element arrays. |
1558 template <typename Subclass, typename KindTraits> | 1427 template <typename Subclass, typename KindTraits> |
1559 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { | 1428 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { |
1560 public: | 1429 public: |
1561 explicit FastElementsAccessor(const char* name) | 1430 explicit FastElementsAccessor(const char* name) |
1562 : ElementsAccessorBase<Subclass, KindTraits>(name) {} | 1431 : ElementsAccessorBase<Subclass, KindTraits>(name) {} |
1563 | 1432 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1904 DisallowHeapAllocation no_gc; | 1773 DisallowHeapAllocation no_gc; |
1905 heap->MoveElements(FixedArray::cast(*dst_elms), dst_index, src_index, | 1774 heap->MoveElements(FixedArray::cast(*dst_elms), dst_index, src_index, |
1906 len); | 1775 len); |
1907 } | 1776 } |
1908 } | 1777 } |
1909 if (hole_start != hole_end) { | 1778 if (hole_start != hole_end) { |
1910 dst_elms->FillWithHoles(hole_start, hole_end); | 1779 dst_elms->FillWithHoles(hole_start, hole_end); |
1911 } | 1780 } |
1912 } | 1781 } |
1913 | 1782 |
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 | |
2064 private: | 1783 private: |
2065 // SpliceShrinkStep might modify the backing_store. | 1784 // SpliceShrinkStep might modify the backing_store. |
2066 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, | 1785 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, |
2067 Handle<FixedArrayBase> backing_store, | 1786 Handle<FixedArrayBase> backing_store, |
2068 uint32_t start, uint32_t delete_count, | 1787 uint32_t start, uint32_t delete_count, |
2069 uint32_t add_count, uint32_t len, | 1788 uint32_t add_count, uint32_t len, |
2070 uint32_t new_length) { | 1789 uint32_t new_length) { |
2071 const int move_left_count = len - delete_count - start; | 1790 const int move_left_count = len - delete_count - start; |
2072 const int move_left_dst_index = start + add_count; | 1791 const int move_left_dst_index = start + add_count; |
2073 Subclass::MoveElements(isolate, receiver, backing_store, | 1792 Subclass::MoveElements(isolate, receiver, backing_store, |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2399 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { | 2118 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { |
2400 public: | 2119 public: |
2401 explicit FastHoleyDoubleElementsAccessor(const char* name) | 2120 explicit FastHoleyDoubleElementsAccessor(const char* name) |
2402 : FastDoubleElementsAccessor< | 2121 : FastDoubleElementsAccessor< |
2403 FastHoleyDoubleElementsAccessor, | 2122 FastHoleyDoubleElementsAccessor, |
2404 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} | 2123 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} |
2405 }; | 2124 }; |
2406 | 2125 |
2407 | 2126 |
2408 // Super class for all external element arrays. | 2127 // Super class for all external element arrays. |
2409 template <ElementsKind Kind, typename ctype> | 2128 template<ElementsKind Kind> |
2410 class TypedElementsAccessor | 2129 class TypedElementsAccessor |
2411 : public ElementsAccessorBase<TypedElementsAccessor<Kind, ctype>, | 2130 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, |
2412 ElementsKindTraits<Kind>> { | 2131 ElementsKindTraits<Kind> > { |
2413 public: | 2132 public: |
2414 explicit TypedElementsAccessor(const char* name) | 2133 explicit TypedElementsAccessor(const char* name) |
2415 : ElementsAccessorBase<AccessorClass, | 2134 : ElementsAccessorBase<AccessorClass, |
2416 ElementsKindTraits<Kind> >(name) {} | 2135 ElementsKindTraits<Kind> >(name) {} |
2417 | 2136 |
2418 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 2137 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
2419 typedef TypedElementsAccessor<Kind, ctype> AccessorClass; | 2138 typedef TypedElementsAccessor<Kind> AccessorClass; |
2420 | 2139 |
2421 static inline void SetImpl(Handle<JSObject> holder, uint32_t entry, | 2140 static inline void SetImpl(Handle<JSObject> holder, uint32_t entry, |
2422 Object* value) { | 2141 Object* value) { |
2423 SetImpl(holder->elements(), entry, value); | 2142 SetImpl(holder->elements(), entry, value); |
2424 } | 2143 } |
2425 | 2144 |
2426 static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry, | 2145 static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry, |
2427 Object* value) { | 2146 Object* value) { |
2428 BackingStore::cast(backing_store)->SetValue(entry, value); | 2147 BackingStore::cast(backing_store)->SetValue(entry, value); |
2429 } | 2148 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2515 Handle<Object> value = AccessorClass::GetImpl(*elements, index); | 2234 Handle<Object> value = AccessorClass::GetImpl(*elements, index); |
2516 if (get_entries) { | 2235 if (get_entries) { |
2517 value = MakeEntryPair(isolate, index, value); | 2236 value = MakeEntryPair(isolate, index, value); |
2518 } | 2237 } |
2519 values_or_entries->set(count++, *value); | 2238 values_or_entries->set(count++, *value); |
2520 } | 2239 } |
2521 } | 2240 } |
2522 *nof_items = count; | 2241 *nof_items = count; |
2523 return Just(true); | 2242 return Just(true); |
2524 } | 2243 } |
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 } | |
2568 }; | 2244 }; |
2569 | 2245 |
2570 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ | 2246 |
2571 typedef TypedElementsAccessor<TYPE##_ELEMENTS, ctype> \ | 2247 |
| 2248 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ |
| 2249 typedef TypedElementsAccessor<TYPE##_ELEMENTS > \ |
2572 Fixed##Type##ElementsAccessor; | 2250 Fixed##Type##ElementsAccessor; |
2573 | 2251 |
2574 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) | 2252 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) |
2575 #undef FIXED_ELEMENTS_ACCESSOR | 2253 #undef FIXED_ELEMENTS_ACCESSOR |
2576 | 2254 |
2577 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> | 2255 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> |
2578 class SloppyArgumentsElementsAccessor | 2256 class SloppyArgumentsElementsAccessor |
2579 : public ElementsAccessorBase<Subclass, KindTraits> { | 2257 : public ElementsAccessorBase<Subclass, KindTraits> { |
2580 public: | 2258 public: |
2581 explicit SloppyArgumentsElementsAccessor(const char* name) | 2259 explicit SloppyArgumentsElementsAccessor(const char* name) |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2796 list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 2474 list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER); |
2797 } | 2475 } |
2798 insertion_index++; | 2476 insertion_index++; |
2799 } | 2477 } |
2800 | 2478 |
2801 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); | 2479 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); |
2802 return ArgumentsAccessor::DirectCollectElementIndicesImpl( | 2480 return ArgumentsAccessor::DirectCollectElementIndicesImpl( |
2803 isolate, object, store, convert, filter, list, nof_indices, | 2481 isolate, object, store, convert, filter, list, nof_indices, |
2804 insertion_index); | 2482 insertion_index); |
2805 } | 2483 } |
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 } | |
2846 }; | 2484 }; |
2847 | 2485 |
2848 | 2486 |
2849 class SlowSloppyArgumentsElementsAccessor | 2487 class SlowSloppyArgumentsElementsAccessor |
2850 : public SloppyArgumentsElementsAccessor< | 2488 : public SloppyArgumentsElementsAccessor< |
2851 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | 2489 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
2852 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { | 2490 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { |
2853 public: | 2491 public: |
2854 explicit SlowSloppyArgumentsElementsAccessor(const char* name) | 2492 explicit SlowSloppyArgumentsElementsAccessor(const char* name) |
2855 : SloppyArgumentsElementsAccessor< | 2493 : SloppyArgumentsElementsAccessor< |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3443 insertion_index += len; | 3081 insertion_index += len; |
3444 } | 3082 } |
3445 | 3083 |
3446 DCHECK_EQ(insertion_index, result_len); | 3084 DCHECK_EQ(insertion_index, result_len); |
3447 return result_array; | 3085 return result_array; |
3448 } | 3086 } |
3449 | 3087 |
3450 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3088 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
3451 } // namespace internal | 3089 } // namespace internal |
3452 } // namespace v8 | 3090 } // namespace v8 |
OLD | NEW |