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) { | |
Camillo Bruni
2016/07/28 12:57:29
nit: expose this globally and use the common imple
caitp
2016/07/29 20:27:47
The builtin has to deal with non-JSObject receiver
| |
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 Maybe<bool> IncludesValueImpl(Isolate* isolate, | |
1460 Handle<JSObject> receiver, | |
1461 Handle<Object> value, | |
1462 uint32_t start_from, uint32_t length) { | |
1463 Handle<SeededNumberDictionary> dictionary( | |
1464 SeededNumberDictionary::cast(receiver->elements()), isolate); | |
1465 | |
1466 bool search_for_hole = value->IsUndefined(isolate); | |
1467 if (search_for_hole) goto slow_path; | |
Camillo Bruni
2016/07/28 12:57:29
shush, I didn't see this goto :D.
For the sake of
caitp
2016/07/29 20:27:46
Done.
| |
1468 goto slow_path; | |
1469 { | |
1470 DisallowHeapAllocation no_gc; | |
1471 int capacity = dictionary->Capacity(); | |
1472 Object* the_hole = isolate->heap()->the_hole_value(); | |
1473 for (int i = 0; i < capacity; ++i) { | |
1474 Object* k = dictionary->KeyAt(i); | |
1475 if (!dictionary->IsKey(k)) continue; | |
1476 | |
1477 Object* element_k = dictionary->ValueAt(i); | |
1478 if (element_k == the_hole) continue; | |
1479 | |
1480 switch (dictionary->DetailsAt(i).kind()) { | |
1481 case kData: { | |
1482 if (value->SameValueZero(element_k)) return Just(true); | |
1483 break; | |
1484 } | |
1485 case kAccessor: { | |
1486 // Restart from beginning in slow path, otherwise we may observably | |
1487 // access getters out of order | |
1488 goto slow_path; | |
1489 } | |
1490 } | |
1491 } | |
1492 return Just(false); | |
1493 } | |
1494 | |
1495 slow_path: | |
1496 // Iterate through entire range, as accessing elements out of order is | |
1497 // observable | |
1498 for (uint32_t k = start_from; k < length; ++k) { | |
1499 int entry = dictionary->FindEntry(k); | |
1500 if (entry == SeededNumberDictionary::kNotFound) { | |
1501 if (search_for_hole) return Just(true); | |
1502 continue; | |
1503 } | |
1504 | |
1505 PropertyDetails details = GetDetailsImpl(receiver->elements(), entry); | |
1506 switch (details.kind()) { | |
1507 case kData: { | |
1508 Object* element_k = dictionary->ValueAt(entry); | |
1509 if (value->SameValueZero(element_k)) return Just(true); | |
1510 break; | |
1511 } | |
1512 case kAccessor: { | |
1513 LookupIterator it(isolate, receiver, k, LookupIterator::OWN); | |
Camillo Bruni
2016/07/28 12:57:29
nit: You can minimally speed up the lookup iterato
caitp
2016/07/29 20:27:47
Done.
| |
1514 DCHECK(it.IsFound()); | |
1515 DCHECK_EQ(it.state(), LookupIterator::ACCESSOR); | |
1516 Handle<Object> element_k; | |
1517 | |
1518 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
1519 isolate, element_k, JSObject::GetPropertyWithAccessor(&it), | |
1520 Nothing<bool>()); | |
1521 | |
1522 if (value->SameValueZero(*element_k)) return Just(true); | |
1523 | |
1524 // Some mutation to the prototype elements may have occurred in | |
1525 // accessor. | |
1526 if (!JSObject::PrototypeHasNoElements(isolate, *receiver)) { | |
1527 return IncludesValueSlowPath(isolate, receiver, value, k + 1, | |
1528 length); | |
1529 } | |
1530 break; | |
1531 } | |
1532 } | |
1533 } | |
1534 return Just(false); | |
1535 } | |
1423 }; | 1536 }; |
1424 | 1537 |
1425 | 1538 |
1426 // Super class for all fast element arrays. | 1539 // Super class for all fast element arrays. |
1427 template <typename Subclass, typename KindTraits> | 1540 template <typename Subclass, typename KindTraits> |
1428 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { | 1541 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { |
1429 public: | 1542 public: |
1430 explicit FastElementsAccessor(const char* name) | 1543 explicit FastElementsAccessor(const char* name) |
1431 : ElementsAccessorBase<Subclass, KindTraits>(name) {} | 1544 : ElementsAccessorBase<Subclass, KindTraits>(name) {} |
1432 | 1545 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1773 DisallowHeapAllocation no_gc; | 1886 DisallowHeapAllocation no_gc; |
1774 heap->MoveElements(FixedArray::cast(*dst_elms), dst_index, src_index, | 1887 heap->MoveElements(FixedArray::cast(*dst_elms), dst_index, src_index, |
1775 len); | 1888 len); |
1776 } | 1889 } |
1777 } | 1890 } |
1778 if (hole_start != hole_end) { | 1891 if (hole_start != hole_end) { |
1779 dst_elms->FillWithHoles(hole_start, hole_end); | 1892 dst_elms->FillWithHoles(hole_start, hole_end); |
1780 } | 1893 } |
1781 } | 1894 } |
1782 | 1895 |
1896 static Maybe<bool> IncludesValueImpl(Isolate* isolate, | |
1897 Handle<JSObject> receiver, | |
1898 Handle<Object> search_value, | |
1899 uint32_t start_from, uint32_t length) { | |
1900 DisallowHeapAllocation no_gc; | |
1901 FixedArrayBase* elements_base = receiver->elements(); | |
1902 Object* the_hole = isolate->heap()->the_hole_value(); | |
1903 Object* undefined = isolate->heap()->undefined_value(); | |
1904 Object* value = *search_value; | |
1905 | |
1906 // Elements beyond the capacity of the backing store treated as undefined. | |
1907 if (value == undefined && elements_base->length() < length) { | |
1908 return Just(true); | |
1909 } | |
1910 | |
1911 if (start_from >= length) return Just(false); | |
1912 | |
1913 if (!value->IsNumber()) { | |
1914 if (value == undefined) { | |
1915 // Only FAST_ELEMENTS, FAST_HOLEY_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, and | |
1916 // FAST_HOLEY_DOUBLE_ELEMENTS can have `undefined` as a value. | |
1917 if (!IsFastObjectElementsKind(KindTraits::Kind) && | |
1918 !IsFastHoleyElementsKind(KindTraits::Kind)) { | |
1919 return Just(false); | |
1920 } | |
1921 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { | |
Camillo Bruni
2016/07/28 12:57:29
nit: please add comments to each branch on what yo
caitp
2016/07/29 20:27:47
Done.
| |
1922 auto elements = FixedArray::cast(receiver->elements()); | |
1923 | |
1924 for (uint32_t k = start_from; k < length; ++k) { | |
1925 Object* element_k = elements->get(k); | |
1926 | |
1927 if (IsFastHoleyElementsKind(KindTraits::Kind) && | |
1928 element_k == the_hole) { | |
1929 return Just(true); | |
1930 } | |
1931 if (IsFastObjectElementsKind(KindTraits::Kind) && | |
1932 element_k == undefined) { | |
1933 return Just(true); | |
1934 } | |
1935 } | |
1936 return Just(false); | |
1937 } else { | |
1938 // Loop searching for non-Number, non-Undefined elements | |
1939 auto elements = FixedDoubleArray::cast(receiver->elements()); | |
1940 | |
1941 for (uint32_t k = start_from; k < length; ++k) { | |
1942 if (IsFastHoleyElementsKind(KindTraits::Kind) && | |
1943 elements->is_the_hole(k)) { | |
1944 return Just(true); | |
1945 } | |
1946 } | |
1947 return Just(false); | |
1948 } | |
1949 } else if (!IsFastObjectElementsKind(KindTraits::Kind)) { | |
1950 // Only Numbers can be represented as packed Smi or Double elements | |
1951 return Just(false); | |
1952 } else { | |
1953 auto elements = FixedArray::cast(receiver->elements()); | |
1954 | |
1955 for (uint32_t k = start_from; k < length; ++k) { | |
1956 Object* element_k = elements->get(k); | |
1957 if (IsFastHoleyElementsKind(KindTraits::Kind) && | |
1958 element_k == the_hole) { | |
1959 continue; | |
1960 } | |
1961 | |
1962 if (value->SameValueZero(element_k)) return Just(true); | |
1963 } | |
1964 return Just(false); | |
1965 } | |
1966 } else { | |
1967 if (!value->IsNaN()) { | |
1968 double search_value = value->Number(); | |
1969 if (IsFastDoubleElementsKind(KindTraits::Kind)) { | |
1970 auto elements = FixedDoubleArray::cast(receiver->elements()); | |
1971 | |
1972 for (uint32_t k = start_from; k < length; ++k) { | |
1973 if (IsFastHoleyElementsKind(KindTraits::Kind) && | |
1974 elements->is_the_hole(k)) { | |
1975 continue; | |
1976 } | |
1977 if (elements->get_scalar(k) == search_value) return Just(true); | |
1978 } | |
1979 return Just(false); | |
1980 } else { | |
1981 auto elements = FixedArray::cast(receiver->elements()); | |
1982 | |
1983 for (uint32_t k = start_from; k < length; ++k) { | |
1984 Object* element_k = elements->get(k); | |
1985 if (element_k->IsNumber() && element_k->Number() == search_value) { | |
1986 return Just(true); | |
1987 } | |
1988 } | |
1989 return Just(false); | |
1990 } | |
1991 } else { | |
1992 // NaN cannot be represented with Smi elements | |
1993 if (IsFastSmiElementsKind(KindTraits::Kind)) return Just(false); | |
1994 | |
1995 if (IsFastDoubleElementsKind(KindTraits::Kind)) { | |
1996 auto elements = FixedDoubleArray::cast(receiver->elements()); | |
1997 | |
1998 for (uint32_t k = start_from; k < length; ++k) { | |
1999 if (IsFastHoleyElementsKind(KindTraits::Kind) && | |
2000 elements->is_the_hole(k)) { | |
2001 continue; | |
2002 } | |
2003 if (std::isnan(elements->get_scalar(k))) return Just(true); | |
2004 } | |
2005 return Just(false); | |
2006 } else { | |
2007 auto elements = FixedArray::cast(receiver->elements()); | |
2008 | |
2009 for (uint32_t k = start_from; k < length; ++k) { | |
2010 if (elements->get(k)->IsNaN()) return Just(true); | |
2011 } | |
2012 return Just(false); | |
2013 } | |
2014 } | |
2015 } | |
2016 } | |
2017 | |
1783 private: | 2018 private: |
1784 // SpliceShrinkStep might modify the backing_store. | 2019 // SpliceShrinkStep might modify the backing_store. |
1785 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, | 2020 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, |
1786 Handle<FixedArrayBase> backing_store, | 2021 Handle<FixedArrayBase> backing_store, |
1787 uint32_t start, uint32_t delete_count, | 2022 uint32_t start, uint32_t delete_count, |
1788 uint32_t add_count, uint32_t len, | 2023 uint32_t add_count, uint32_t len, |
1789 uint32_t new_length) { | 2024 uint32_t new_length) { |
1790 const int move_left_count = len - delete_count - start; | 2025 const int move_left_count = len - delete_count - start; |
1791 const int move_left_dst_index = start + add_count; | 2026 const int move_left_dst_index = start + add_count; |
1792 Subclass::MoveElements(isolate, receiver, backing_store, | 2027 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> > { | 2353 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { |
2119 public: | 2354 public: |
2120 explicit FastHoleyDoubleElementsAccessor(const char* name) | 2355 explicit FastHoleyDoubleElementsAccessor(const char* name) |
2121 : FastDoubleElementsAccessor< | 2356 : FastDoubleElementsAccessor< |
2122 FastHoleyDoubleElementsAccessor, | 2357 FastHoleyDoubleElementsAccessor, |
2123 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} | 2358 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} |
2124 }; | 2359 }; |
2125 | 2360 |
2126 | 2361 |
2127 // Super class for all external element arrays. | 2362 // Super class for all external element arrays. |
2128 template<ElementsKind Kind> | 2363 template <ElementsKind Kind, typename ctype> |
Camillo Bruni
2016/07/28 12:57:29
nice :)
| |
2129 class TypedElementsAccessor | 2364 class TypedElementsAccessor |
2130 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, | 2365 : public ElementsAccessorBase<TypedElementsAccessor<Kind, ctype>, |
2131 ElementsKindTraits<Kind> > { | 2366 ElementsKindTraits<Kind>> { |
2132 public: | 2367 public: |
2133 explicit TypedElementsAccessor(const char* name) | 2368 explicit TypedElementsAccessor(const char* name) |
2134 : ElementsAccessorBase<AccessorClass, | 2369 : ElementsAccessorBase<AccessorClass, |
2135 ElementsKindTraits<Kind> >(name) {} | 2370 ElementsKindTraits<Kind> >(name) {} |
2136 | 2371 |
2137 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 2372 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
2138 typedef TypedElementsAccessor<Kind> AccessorClass; | 2373 typedef TypedElementsAccessor<Kind, ctype> AccessorClass; |
2139 | 2374 |
2140 static inline void SetImpl(Handle<JSObject> holder, uint32_t entry, | 2375 static inline void SetImpl(Handle<JSObject> holder, uint32_t entry, |
2141 Object* value) { | 2376 Object* value) { |
2142 SetImpl(holder->elements(), entry, value); | 2377 SetImpl(holder->elements(), entry, value); |
2143 } | 2378 } |
2144 | 2379 |
2145 static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry, | 2380 static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry, |
2146 Object* value) { | 2381 Object* value) { |
2147 BackingStore::cast(backing_store)->SetValue(entry, value); | 2382 BackingStore::cast(backing_store)->SetValue(entry, value); |
2148 } | 2383 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2234 Handle<Object> value = AccessorClass::GetImpl(*elements, index); | 2469 Handle<Object> value = AccessorClass::GetImpl(*elements, index); |
2235 if (get_entries) { | 2470 if (get_entries) { |
2236 value = MakeEntryPair(isolate, index, value); | 2471 value = MakeEntryPair(isolate, index, value); |
2237 } | 2472 } |
2238 values_or_entries->set(count++, *value); | 2473 values_or_entries->set(count++, *value); |
2239 } | 2474 } |
2240 } | 2475 } |
2241 *nof_items = count; | 2476 *nof_items = count; |
2242 return Just(true); | 2477 return Just(true); |
2243 } | 2478 } |
2479 | |
2480 static Maybe<bool> IncludesValueImpl(Isolate* isolate, | |
2481 Handle<JSObject> receiver, | |
2482 Handle<Object> value, | |
2483 uint32_t start_from, uint32_t length) { | |
2484 DisallowHeapAllocation no_gc; | |
2485 auto HasNeuteredArrayBuffer = [](JSObject* object) -> bool { | |
Camillo Bruni
2016/07/28 12:57:29
can you just put this in a helper on this elements
caitp
2016/07/29 20:27:46
Done (moved to `static inline JSObject::HasNeutere
| |
2486 switch (object->map()->instance_type()) { | |
2487 case JS_ARRAY_BUFFER_TYPE: | |
2488 return JSArrayBuffer::cast(object)->was_neutered(); | |
2489 case JS_DATA_VIEW_TYPE: | |
2490 case JS_TYPED_ARRAY_TYPE: { | |
2491 Object* buffer = static_cast<JSArrayBufferView*>(object)->buffer(); | |
2492 if (!buffer->IsJSArrayBuffer()) return false; | |
2493 return JSArrayBuffer::cast(buffer)->was_neutered(); | |
2494 } | |
2495 default: | |
2496 return false; | |
2497 } | |
2498 }; | |
2499 | |
2500 // Don't exit early if buffers are neutred, because this is observable | |
2501 // via a thrown exception (but should still throw early). | |
2502 if (HasNeuteredArrayBuffer(*receiver)) { | |
2503 return IncludesValueSlowPath(isolate, receiver, value, start_from, | |
2504 length); | |
Camillo Bruni
2016/07/28 12:57:29
nit: If we have nothing on the prototype chain we
caitp
2016/07/29 20:27:46
Actually, I think this whole thing can be removed,
| |
2505 } | |
2506 | |
2507 BackingStore* elements = BackingStore::cast(receiver->elements()); | |
2508 if (value->IsUndefined(isolate) && length > elements->length()) { | |
2509 return Just(true); | |
2510 } | |
2511 if (!value->IsNumber()) return Just(false); | |
2512 | |
2513 double search_value = value->Number(); | |
2514 | |
2515 if (!std::isfinite(search_value)) { | |
2516 // Integral types cannot represent +Inf or NaN | |
2517 if (Kind < FLOAT32_ELEMENTS || Kind > FLOAT64_ELEMENTS) { | |
Camillo Bruni
2016/07/28 12:57:29
I think you can use kind() which is consistent acr
caitp
2016/07/29 20:27:47
Done
| |
2518 return Just(false); | |
2519 } | |
2520 } else if (search_value < std::numeric_limits<ctype>::min() || | |
caitp
2016/07/29 20:27:47
switched to numeric_limits<ctype>::lowest() rather
Camillo Bruni
2016/07/30 06:56:56
argh, good catch!
| |
2521 search_value > std::numeric_limits<ctype>::max()) { | |
2522 // Return false if value can't be represented in this space | |
2523 return Just(false); | |
2524 } | |
2525 | |
2526 if (!std::isnan(search_value)) { | |
2527 for (uint32_t k = start_from; k < length; ++k) { | |
2528 double element_k = elements->get_scalar(k); | |
2529 if (element_k == search_value) return Just(true); | |
2530 } | |
2531 return Just(false); | |
2532 } else { | |
2533 for (uint32_t k = start_from; k < length; ++k) { | |
2534 double element_k = elements->get_scalar(k); | |
2535 if (std::isnan(element_k)) return Just(true); | |
2536 } | |
2537 return Just(false); | |
2538 } | |
2539 } | |
2244 }; | 2540 }; |
2245 | 2541 |
2246 | 2542 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ |
2247 | 2543 typedef TypedElementsAccessor<TYPE##_ELEMENTS, ctype> \ |
2248 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ | |
2249 typedef TypedElementsAccessor<TYPE##_ELEMENTS > \ | |
2250 Fixed##Type##ElementsAccessor; | 2544 Fixed##Type##ElementsAccessor; |
2251 | 2545 |
2252 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) | 2546 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) |
2253 #undef FIXED_ELEMENTS_ACCESSOR | 2547 #undef FIXED_ELEMENTS_ACCESSOR |
2254 | 2548 |
2255 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> | 2549 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> |
2256 class SloppyArgumentsElementsAccessor | 2550 class SloppyArgumentsElementsAccessor |
2257 : public ElementsAccessorBase<Subclass, KindTraits> { | 2551 : public ElementsAccessorBase<Subclass, KindTraits> { |
2258 public: | 2552 public: |
2259 explicit SloppyArgumentsElementsAccessor(const char* name) | 2553 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); | 2768 list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER); |
2475 } | 2769 } |
2476 insertion_index++; | 2770 insertion_index++; |
2477 } | 2771 } |
2478 | 2772 |
2479 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); | 2773 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); |
2480 return ArgumentsAccessor::DirectCollectElementIndicesImpl( | 2774 return ArgumentsAccessor::DirectCollectElementIndicesImpl( |
2481 isolate, object, store, convert, filter, list, nof_indices, | 2775 isolate, object, store, convert, filter, list, nof_indices, |
2482 insertion_index); | 2776 insertion_index); |
2483 } | 2777 } |
2778 | |
2779 static Maybe<bool> IncludesValueImpl(Isolate* isolate, | |
2780 Handle<JSObject> object, | |
2781 Handle<Object> value, | |
2782 uint32_t start_from, uint32_t length) { | |
2783 Handle<Map> original_map = handle(object->map(), isolate); | |
2784 FixedArray* parameter_map = FixedArray::cast(object->elements()); | |
2785 bool search_for_hole = value->IsUndefined(isolate); | |
2786 | |
2787 for (uint32_t k = start_from; k < length; ++k) { | |
2788 uint32_t entry = | |
2789 GetEntryForIndexImpl(*object, parameter_map, k, ALL_PROPERTIES); | |
2790 if (entry == kMaxUInt32) { | |
2791 if (search_for_hole) return Just(true); | |
2792 continue; | |
2793 } | |
2794 | |
2795 Handle<Object> element_k = GetImpl(parameter_map, entry); | |
2796 | |
2797 if (element_k->IsAccessorPair()) { | |
2798 LookupIterator it(isolate, object, k, LookupIterator::OWN); | |
2799 DCHECK(it.IsFound()); | |
2800 DCHECK_EQ(it.state(), LookupIterator::ACCESSOR); | |
2801 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k, | |
2802 Object::GetPropertyWithAccessor(&it), | |
2803 Nothing<bool>()); | |
2804 | |
2805 if (value->SameValueZero(*element_k)) return Just(true); | |
2806 | |
2807 if (object->map() != *original_map) { | |
2808 // Some mutation occurred in accessor. Abort "fast" path | |
2809 return IncludesValueSlowPath(isolate, object, value, k + 1, length); | |
2810 } | |
2811 } else if (value->SameValueZero(*element_k)) { | |
2812 return Just(true); | |
2813 } | |
2814 } | |
2815 return Just(false); | |
2816 } | |
2484 }; | 2817 }; |
2485 | 2818 |
2486 | 2819 |
2487 class SlowSloppyArgumentsElementsAccessor | 2820 class SlowSloppyArgumentsElementsAccessor |
2488 : public SloppyArgumentsElementsAccessor< | 2821 : public SloppyArgumentsElementsAccessor< |
2489 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | 2822 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
2490 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { | 2823 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { |
2491 public: | 2824 public: |
2492 explicit SlowSloppyArgumentsElementsAccessor(const char* name) | 2825 explicit SlowSloppyArgumentsElementsAccessor(const char* name) |
2493 : SloppyArgumentsElementsAccessor< | 2826 : SloppyArgumentsElementsAccessor< |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3081 insertion_index += len; | 3414 insertion_index += len; |
3082 } | 3415 } |
3083 | 3416 |
3084 DCHECK_EQ(insertion_index, result_len); | 3417 DCHECK_EQ(insertion_index, result_len); |
3085 return result_array; | 3418 return result_array; |
3086 } | 3419 } |
3087 | 3420 |
3088 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3421 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
3089 } // namespace internal | 3422 } // namespace internal |
3090 } // namespace v8 | 3423 } // namespace v8 |
OLD | NEW |