Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(733)

Side by Side Diff: src/elements.cc

Issue 2146293003: [builtins] implement Array.prototype.includes in TurboFan (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix BranchIfSimd128Equal Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/elements.h ('k') | src/factory.h » ('j') | test/mjsunit/es7/array-includes-receiver.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698