Chromium Code Reviews| 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 for (int i = 0; i < capacity; ++i) { | |
| 1468 Object* k = dictionary->KeyAt(i); | |
| 1469 if (!dictionary->IsKey(k)) continue; | |
| 1470 | |
| 1471 Object* element_k = dictionary->ValueAt(i); | |
| 1472 if (element_k == the_hole) continue; | |
| 1473 | |
| 1474 switch (dictionary->DetailsAt(i).kind()) { | |
| 1475 case kData: { | |
| 1476 if (value->SameValueZero(element_k)) { | |
| 1477 *result = Just(true); | |
| 1478 return true; | |
| 1479 } | |
| 1480 break; | |
| 1481 } | |
| 1482 case kAccessor: { | |
| 1483 // Restart from beginning in slow path, otherwise we may observably | |
| 1484 // access getters out of order | |
| 1485 return false; | |
|
caitp
2016/08/01 15:10:45
Unfortunately, this doesn't work. The only thing t
Camillo Bruni
2016/08/01 15:37:03
right. We already have a check HasAccessorsImpl()
caitp
2016/08/01 16:44:55
I've changed this to avoid having to loop through
| |
| 1486 } | |
| 1487 } | |
| 1488 } | |
| 1489 *result = Just(false); | |
| 1490 return true; | |
| 1491 } | |
| 1492 | |
| 1493 static Maybe<bool> IncludesValueImpl(Isolate* isolate, | |
| 1494 Handle<JSObject> receiver, | |
| 1495 Handle<Object> value, | |
| 1496 uint32_t start_from, uint32_t length) { | |
| 1497 bool search_for_hole = value->IsUndefined(isolate); | |
| 1498 | |
| 1499 if (!search_for_hole) { | |
| 1500 Maybe<bool> result = Nothing<bool>(); | |
| 1501 if (DictionaryElementsAccessor::IncludesValueFastPath( | |
| 1502 isolate, receiver, value, start_from, length, &result)) { | |
| 1503 return result; | |
| 1504 } | |
| 1505 } | |
| 1506 | |
| 1507 Handle<SeededNumberDictionary> dictionary( | |
| 1508 SeededNumberDictionary::cast(receiver->elements()), isolate); | |
| 1509 // Iterate through entire range, as accessing elements out of order is | |
| 1510 // observable | |
| 1511 for (uint32_t k = start_from; k < length; ++k) { | |
| 1512 int entry = dictionary->FindEntry(k); | |
| 1513 if (entry == SeededNumberDictionary::kNotFound) { | |
| 1514 if (search_for_hole) return Just(true); | |
| 1515 continue; | |
| 1516 } | |
| 1517 | |
| 1518 PropertyDetails details = GetDetailsImpl(receiver->elements(), entry); | |
| 1519 switch (details.kind()) { | |
| 1520 case kData: { | |
| 1521 Object* element_k = dictionary->ValueAt(entry); | |
| 1522 if (value->SameValueZero(element_k)) return Just(true); | |
| 1523 break; | |
| 1524 } | |
| 1525 case kAccessor: { | |
| 1526 LookupIterator it(isolate, receiver, k, | |
| 1527 LookupIterator::OWN_SKIP_INTERCEPTOR); | |
| 1528 DCHECK(it.IsFound()); | |
| 1529 DCHECK_EQ(it.state(), LookupIterator::ACCESSOR); | |
| 1530 Handle<Object> element_k; | |
| 1531 | |
| 1532 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 1533 isolate, element_k, JSObject::GetPropertyWithAccessor(&it), | |
| 1534 Nothing<bool>()); | |
| 1535 | |
| 1536 if (value->SameValueZero(*element_k)) return Just(true); | |
| 1537 | |
| 1538 // Some mutation to the prototype elements may have occurred in | |
| 1539 // accessor. | |
| 1540 if (!JSObject::PrototypeHasNoElements(isolate, *receiver)) { | |
| 1541 return IncludesValueSlowPath(isolate, receiver, value, k + 1, | |
| 1542 length); | |
| 1543 } | |
| 1544 break; | |
| 1545 } | |
| 1546 } | |
| 1547 } | |
| 1548 return Just(false); | |
| 1549 } | |
| 1423 }; | 1550 }; |
| 1424 | 1551 |
| 1425 | 1552 |
| 1426 // Super class for all fast element arrays. | 1553 // Super class for all fast element arrays. |
| 1427 template <typename Subclass, typename KindTraits> | 1554 template <typename Subclass, typename KindTraits> |
| 1428 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { | 1555 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { |
| 1429 public: | 1556 public: |
| 1430 explicit FastElementsAccessor(const char* name) | 1557 explicit FastElementsAccessor(const char* name) |
| 1431 : ElementsAccessorBase<Subclass, KindTraits>(name) {} | 1558 : ElementsAccessorBase<Subclass, KindTraits>(name) {} |
| 1432 | 1559 |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1773 DisallowHeapAllocation no_gc; | 1900 DisallowHeapAllocation no_gc; |
| 1774 heap->MoveElements(FixedArray::cast(*dst_elms), dst_index, src_index, | 1901 heap->MoveElements(FixedArray::cast(*dst_elms), dst_index, src_index, |
| 1775 len); | 1902 len); |
| 1776 } | 1903 } |
| 1777 } | 1904 } |
| 1778 if (hole_start != hole_end) { | 1905 if (hole_start != hole_end) { |
| 1779 dst_elms->FillWithHoles(hole_start, hole_end); | 1906 dst_elms->FillWithHoles(hole_start, hole_end); |
| 1780 } | 1907 } |
| 1781 } | 1908 } |
| 1782 | 1909 |
| 1910 static Maybe<bool> IncludesValueImpl(Isolate* isolate, | |
| 1911 Handle<JSObject> receiver, | |
| 1912 Handle<Object> search_value, | |
| 1913 uint32_t start_from, uint32_t length) { | |
| 1914 DisallowHeapAllocation no_gc; | |
| 1915 FixedArrayBase* elements_base = receiver->elements(); | |
| 1916 Object* the_hole = isolate->heap()->the_hole_value(); | |
| 1917 Object* undefined = isolate->heap()->undefined_value(); | |
| 1918 Object* value = *search_value; | |
| 1919 | |
| 1920 // Elements beyond the capacity of the backing store treated as undefined. | |
| 1921 if (value == undefined && elements_base->length() < length) { | |
| 1922 return Just(true); | |
| 1923 } | |
| 1924 | |
| 1925 if (start_from >= length) return Just(false); | |
| 1926 | |
| 1927 if (!value->IsNumber()) { | |
| 1928 if (value == undefined) { | |
| 1929 // Only FAST_ELEMENTS, FAST_HOLEY_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, and | |
| 1930 // FAST_HOLEY_DOUBLE_ELEMENTS can have `undefined` as a value. | |
| 1931 if (!IsFastObjectElementsKind(Subclass::kind()) && | |
| 1932 !IsFastHoleyElementsKind(Subclass::kind())) { | |
| 1933 return Just(false); | |
| 1934 } | |
| 1935 | |
| 1936 // Search for `undefined` or The Hole in FAST_ELEMENTS, | |
| 1937 // FAST_HOLEY_ELEMENTS or FAST_HOLEY_SMI_ELEMENTS | |
| 1938 if (IsFastSmiOrObjectElementsKind(Subclass::kind())) { | |
| 1939 auto elements = FixedArray::cast(receiver->elements()); | |
| 1940 | |
| 1941 for (uint32_t k = start_from; k < length; ++k) { | |
| 1942 Object* element_k = elements->get(k); | |
| 1943 | |
| 1944 if (IsFastHoleyElementsKind(Subclass::kind()) && | |
| 1945 element_k == the_hole) { | |
| 1946 return Just(true); | |
| 1947 } | |
| 1948 if (IsFastObjectElementsKind(Subclass::kind()) && | |
| 1949 element_k == undefined) { | |
| 1950 return Just(true); | |
| 1951 } | |
| 1952 } | |
| 1953 return Just(false); | |
| 1954 } else { | |
| 1955 // Seach for The Hole in FAST_HOLEY_DOUBLE_ELEMENTS | |
| 1956 DCHECK_EQ(Subclass::kind(), FAST_HOLEY_DOUBLE_ELEMENTS); | |
| 1957 auto elements = FixedDoubleArray::cast(receiver->elements()); | |
| 1958 | |
| 1959 for (uint32_t k = start_from; k < length; ++k) { | |
| 1960 if (IsFastHoleyElementsKind(Subclass::kind()) && | |
| 1961 elements->is_the_hole(k)) { | |
| 1962 return Just(true); | |
| 1963 } | |
| 1964 } | |
| 1965 return Just(false); | |
| 1966 } | |
| 1967 } else if (!IsFastObjectElementsKind(Subclass::kind())) { | |
| 1968 // Search for non-number, non-Undefined value, with either | |
| 1969 // FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS or | |
| 1970 // FAST_HOLEY_DOUBLE_ELEMENTS. Guaranteed to return false, since these | |
| 1971 // elements kinds can only contain Number values or undefined. | |
| 1972 return Just(false); | |
| 1973 } else { | |
| 1974 // Search for non-number, non-Undefined value with either | |
| 1975 // FAST_ELEMENTS or FAST_HOLEY_ELEMENTS. | |
| 1976 DCHECK(IsFastObjectElementsKind(Subclass::kind())); | |
| 1977 auto elements = FixedArray::cast(receiver->elements()); | |
| 1978 | |
| 1979 for (uint32_t k = start_from; k < length; ++k) { | |
| 1980 Object* element_k = elements->get(k); | |
| 1981 if (IsFastHoleyElementsKind(Subclass::kind()) && | |
| 1982 element_k == the_hole) { | |
| 1983 continue; | |
| 1984 } | |
| 1985 | |
| 1986 if (value->SameValueZero(element_k)) return Just(true); | |
| 1987 } | |
| 1988 return Just(false); | |
| 1989 } | |
| 1990 } else { | |
| 1991 if (!value->IsNaN()) { | |
| 1992 double search_value = value->Number(); | |
| 1993 if (IsFastDoubleElementsKind(Subclass::kind())) { | |
| 1994 // Search for non-NaN Number in FAST_DOUBLE_ELEMENTS or | |
| 1995 // FAST_HOLEY_DOUBLE_ELEMENTS --- Skip TheHole, and trust UCOMISD or | |
| 1996 // similar operation for result. | |
| 1997 auto elements = FixedDoubleArray::cast(receiver->elements()); | |
| 1998 | |
| 1999 for (uint32_t k = start_from; k < length; ++k) { | |
| 2000 if (IsFastHoleyElementsKind(Subclass::kind()) && | |
| 2001 elements->is_the_hole(k)) { | |
| 2002 continue; | |
| 2003 } | |
|
Camillo Bruni
2016/08/01 07:23:47
bah, sucks that you can just fold the hole check i
| |
| 2004 if (elements->get_scalar(k) == search_value) return Just(true); | |
| 2005 } | |
| 2006 return Just(false); | |
| 2007 } else { | |
| 2008 // Search for non-NaN Number in FAST_ELEMENTS, FAST_HOLEY_ELEMENTS, | |
| 2009 // FAST_SMI_ELEMENTS or FAST_HOLEY_SMI_ELEMENTS --- Skip non-Numbers, | |
| 2010 // and trust UCOMISD or similar operation for result | |
| 2011 auto elements = FixedArray::cast(receiver->elements()); | |
| 2012 | |
| 2013 for (uint32_t k = start_from; k < length; ++k) { | |
| 2014 Object* element_k = elements->get(k); | |
| 2015 if (element_k->IsNumber() && element_k->Number() == search_value) { | |
| 2016 return Just(true); | |
| 2017 } | |
| 2018 } | |
| 2019 return Just(false); | |
| 2020 } | |
| 2021 } else { | |
| 2022 // Search for NaN --- NaN cannot be represented with Smi elements, so | |
| 2023 // abort if ElementsKind is FAST_SMI_ELEMENTS or FAST_HOLEY_SMI_ELEMENTS | |
| 2024 if (IsFastSmiElementsKind(Subclass::kind())) return Just(false); | |
| 2025 | |
| 2026 if (IsFastDoubleElementsKind(Subclass::kind())) { | |
| 2027 // Search for NaN in FAST_DOUBLE_ELEMENTS or | |
| 2028 // FAST_HOLEY_DOUBLE_ELEMENTS --- Skip The Hole and trust | |
| 2029 // std::isnan(elementK) for result | |
| 2030 auto elements = FixedDoubleArray::cast(receiver->elements()); | |
| 2031 | |
| 2032 for (uint32_t k = start_from; k < length; ++k) { | |
| 2033 if (IsFastHoleyElementsKind(Subclass::kind()) && | |
| 2034 elements->is_the_hole(k)) { | |
| 2035 continue; | |
| 2036 } | |
| 2037 if (std::isnan(elements->get_scalar(k))) return Just(true); | |
| 2038 } | |
| 2039 return Just(false); | |
| 2040 } else { | |
| 2041 // Search for NaN in FAST_ELEMENTS, FAST_HOLEY_ELEMENTS, | |
| 2042 // FAST_SMI_ELEMENTS or FAST_HOLEY_SMI_ELEMENTS. Return true if | |
| 2043 // elementK->IsHeapNumber() && std::isnan(elementK->Number()) | |
|
Camillo Bruni
2016/08/01 07:23:47
thanks for all the comments!
| |
| 2044 DCHECK(IsFastSmiOrObjectElementsKind(Subclass::kind())); | |
| 2045 auto elements = FixedArray::cast(receiver->elements()); | |
| 2046 | |
| 2047 for (uint32_t k = start_from; k < length; ++k) { | |
| 2048 if (elements->get(k)->IsNaN()) return Just(true); | |
| 2049 } | |
| 2050 return Just(false); | |
| 2051 } | |
| 2052 } | |
| 2053 } | |
| 2054 } | |
| 2055 | |
| 1783 private: | 2056 private: |
| 1784 // SpliceShrinkStep might modify the backing_store. | 2057 // SpliceShrinkStep might modify the backing_store. |
| 1785 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, | 2058 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, |
| 1786 Handle<FixedArrayBase> backing_store, | 2059 Handle<FixedArrayBase> backing_store, |
| 1787 uint32_t start, uint32_t delete_count, | 2060 uint32_t start, uint32_t delete_count, |
| 1788 uint32_t add_count, uint32_t len, | 2061 uint32_t add_count, uint32_t len, |
| 1789 uint32_t new_length) { | 2062 uint32_t new_length) { |
| 1790 const int move_left_count = len - delete_count - start; | 2063 const int move_left_count = len - delete_count - start; |
| 1791 const int move_left_dst_index = start + add_count; | 2064 const int move_left_dst_index = start + add_count; |
| 1792 Subclass::MoveElements(isolate, receiver, backing_store, | 2065 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> > { | 2391 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { |
| 2119 public: | 2392 public: |
| 2120 explicit FastHoleyDoubleElementsAccessor(const char* name) | 2393 explicit FastHoleyDoubleElementsAccessor(const char* name) |
| 2121 : FastDoubleElementsAccessor< | 2394 : FastDoubleElementsAccessor< |
| 2122 FastHoleyDoubleElementsAccessor, | 2395 FastHoleyDoubleElementsAccessor, |
| 2123 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} | 2396 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} |
| 2124 }; | 2397 }; |
| 2125 | 2398 |
| 2126 | 2399 |
| 2127 // Super class for all external element arrays. | 2400 // Super class for all external element arrays. |
| 2128 template<ElementsKind Kind> | 2401 template <ElementsKind Kind, typename ctype> |
| 2129 class TypedElementsAccessor | 2402 class TypedElementsAccessor |
| 2130 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, | 2403 : public ElementsAccessorBase<TypedElementsAccessor<Kind, ctype>, |
| 2131 ElementsKindTraits<Kind> > { | 2404 ElementsKindTraits<Kind>> { |
| 2132 public: | 2405 public: |
| 2133 explicit TypedElementsAccessor(const char* name) | 2406 explicit TypedElementsAccessor(const char* name) |
| 2134 : ElementsAccessorBase<AccessorClass, | 2407 : ElementsAccessorBase<AccessorClass, |
| 2135 ElementsKindTraits<Kind> >(name) {} | 2408 ElementsKindTraits<Kind> >(name) {} |
| 2136 | 2409 |
| 2137 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 2410 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
| 2138 typedef TypedElementsAccessor<Kind> AccessorClass; | 2411 typedef TypedElementsAccessor<Kind, ctype> AccessorClass; |
| 2139 | 2412 |
| 2140 static inline void SetImpl(Handle<JSObject> holder, uint32_t entry, | 2413 static inline void SetImpl(Handle<JSObject> holder, uint32_t entry, |
| 2141 Object* value) { | 2414 Object* value) { |
| 2142 SetImpl(holder->elements(), entry, value); | 2415 SetImpl(holder->elements(), entry, value); |
| 2143 } | 2416 } |
| 2144 | 2417 |
| 2145 static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry, | 2418 static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry, |
| 2146 Object* value) { | 2419 Object* value) { |
| 2147 BackingStore::cast(backing_store)->SetValue(entry, value); | 2420 BackingStore::cast(backing_store)->SetValue(entry, value); |
| 2148 } | 2421 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2234 Handle<Object> value = AccessorClass::GetImpl(*elements, index); | 2507 Handle<Object> value = AccessorClass::GetImpl(*elements, index); |
| 2235 if (get_entries) { | 2508 if (get_entries) { |
| 2236 value = MakeEntryPair(isolate, index, value); | 2509 value = MakeEntryPair(isolate, index, value); |
| 2237 } | 2510 } |
| 2238 values_or_entries->set(count++, *value); | 2511 values_or_entries->set(count++, *value); |
| 2239 } | 2512 } |
| 2240 } | 2513 } |
| 2241 *nof_items = count; | 2514 *nof_items = count; |
| 2242 return Just(true); | 2515 return Just(true); |
| 2243 } | 2516 } |
| 2517 | |
| 2518 static Maybe<bool> IncludesValueImpl(Isolate* isolate, | |
| 2519 Handle<JSObject> receiver, | |
| 2520 Handle<Object> value, | |
| 2521 uint32_t start_from, uint32_t length) { | |
| 2522 DisallowHeapAllocation no_gc; | |
| 2523 | |
| 2524 BackingStore* elements = BackingStore::cast(receiver->elements()); | |
| 2525 if (value->IsUndefined(isolate) && length > elements->length()) { | |
| 2526 return Just(true); | |
| 2527 } | |
| 2528 if (!value->IsNumber()) return Just(false); | |
| 2529 | |
| 2530 double search_value = value->Number(); | |
| 2531 | |
| 2532 if (!std::isfinite(search_value)) { | |
| 2533 // Integral types cannot represent +Inf or NaN | |
| 2534 if (AccessorClass::kind() < FLOAT32_ELEMENTS || | |
| 2535 AccessorClass::kind() > FLOAT64_ELEMENTS) { | |
| 2536 return Just(false); | |
| 2537 } | |
| 2538 } else if (search_value < std::numeric_limits<ctype>::lowest() || | |
| 2539 search_value > std::numeric_limits<ctype>::max()) { | |
| 2540 // Return false if value can't be represented in this space | |
| 2541 return Just(false); | |
| 2542 } | |
| 2543 | |
| 2544 if (!std::isnan(search_value)) { | |
| 2545 for (uint32_t k = start_from; k < length; ++k) { | |
| 2546 double element_k = elements->get_scalar(k); | |
| 2547 if (element_k == search_value) return Just(true); | |
| 2548 } | |
| 2549 return Just(false); | |
| 2550 } else { | |
| 2551 for (uint32_t k = start_from; k < length; ++k) { | |
| 2552 double element_k = elements->get_scalar(k); | |
| 2553 if (std::isnan(element_k)) return Just(true); | |
| 2554 } | |
| 2555 return Just(false); | |
| 2556 } | |
| 2557 } | |
| 2244 }; | 2558 }; |
| 2245 | 2559 |
| 2246 | 2560 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ |
| 2247 | 2561 typedef TypedElementsAccessor<TYPE##_ELEMENTS, ctype> \ |
| 2248 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ | |
| 2249 typedef TypedElementsAccessor<TYPE##_ELEMENTS > \ | |
| 2250 Fixed##Type##ElementsAccessor; | 2562 Fixed##Type##ElementsAccessor; |
| 2251 | 2563 |
| 2252 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) | 2564 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) |
| 2253 #undef FIXED_ELEMENTS_ACCESSOR | 2565 #undef FIXED_ELEMENTS_ACCESSOR |
| 2254 | 2566 |
| 2255 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> | 2567 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> |
| 2256 class SloppyArgumentsElementsAccessor | 2568 class SloppyArgumentsElementsAccessor |
| 2257 : public ElementsAccessorBase<Subclass, KindTraits> { | 2569 : public ElementsAccessorBase<Subclass, KindTraits> { |
| 2258 public: | 2570 public: |
| 2259 explicit SloppyArgumentsElementsAccessor(const char* name) | 2571 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); | 2786 list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER); |
| 2475 } | 2787 } |
| 2476 insertion_index++; | 2788 insertion_index++; |
| 2477 } | 2789 } |
| 2478 | 2790 |
| 2479 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); | 2791 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); |
| 2480 return ArgumentsAccessor::DirectCollectElementIndicesImpl( | 2792 return ArgumentsAccessor::DirectCollectElementIndicesImpl( |
| 2481 isolate, object, store, convert, filter, list, nof_indices, | 2793 isolate, object, store, convert, filter, list, nof_indices, |
| 2482 insertion_index); | 2794 insertion_index); |
| 2483 } | 2795 } |
| 2796 | |
| 2797 static Maybe<bool> IncludesValueImpl(Isolate* isolate, | |
| 2798 Handle<JSObject> object, | |
| 2799 Handle<Object> value, | |
| 2800 uint32_t start_from, uint32_t length) { | |
|
Camillo Bruni
2016/08/01 07:23:47
nit: could you add DCHECK(JSObject::PrototypeHasNo
caitp
2016/08/01 15:10:45
I've added the DCHECK for all of the ElementsAcces
Camillo Bruni
2016/08/01 15:37:03
nice
| |
| 2801 Handle<Map> original_map = handle(object->map(), isolate); | |
| 2802 FixedArray* parameter_map = FixedArray::cast(object->elements()); | |
| 2803 bool search_for_hole = value->IsUndefined(isolate); | |
| 2804 | |
| 2805 for (uint32_t k = start_from; k < length; ++k) { | |
| 2806 uint32_t entry = | |
| 2807 GetEntryForIndexImpl(*object, parameter_map, k, ALL_PROPERTIES); | |
| 2808 if (entry == kMaxUInt32) { | |
| 2809 if (search_for_hole) return Just(true); | |
| 2810 continue; | |
| 2811 } | |
| 2812 | |
| 2813 Handle<Object> element_k = GetImpl(parameter_map, entry); | |
| 2814 | |
| 2815 if (element_k->IsAccessorPair()) { | |
| 2816 LookupIterator it(isolate, object, k, LookupIterator::OWN); | |
| 2817 DCHECK(it.IsFound()); | |
| 2818 DCHECK_EQ(it.state(), LookupIterator::ACCESSOR); | |
| 2819 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k, | |
| 2820 Object::GetPropertyWithAccessor(&it), | |
| 2821 Nothing<bool>()); | |
| 2822 | |
| 2823 if (value->SameValueZero(*element_k)) return Just(true); | |
| 2824 | |
| 2825 if (object->map() != *original_map) { | |
| 2826 // Some mutation occurred in accessor. Abort "fast" path | |
| 2827 return IncludesValueSlowPath(isolate, object, value, k + 1, length); | |
| 2828 } | |
| 2829 } else if (value->SameValueZero(*element_k)) { | |
| 2830 return Just(true); | |
| 2831 } | |
| 2832 } | |
| 2833 return Just(false); | |
| 2834 } | |
| 2484 }; | 2835 }; |
| 2485 | 2836 |
| 2486 | 2837 |
| 2487 class SlowSloppyArgumentsElementsAccessor | 2838 class SlowSloppyArgumentsElementsAccessor |
| 2488 : public SloppyArgumentsElementsAccessor< | 2839 : public SloppyArgumentsElementsAccessor< |
| 2489 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | 2840 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 2490 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { | 2841 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { |
| 2491 public: | 2842 public: |
| 2492 explicit SlowSloppyArgumentsElementsAccessor(const char* name) | 2843 explicit SlowSloppyArgumentsElementsAccessor(const char* name) |
| 2493 : SloppyArgumentsElementsAccessor< | 2844 : SloppyArgumentsElementsAccessor< |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3081 insertion_index += len; | 3432 insertion_index += len; |
| 3082 } | 3433 } |
| 3083 | 3434 |
| 3084 DCHECK_EQ(insertion_index, result_len); | 3435 DCHECK_EQ(insertion_index, result_len); |
| 3085 return result_array; | 3436 return result_array; |
| 3086 } | 3437 } |
| 3087 | 3438 |
| 3088 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3439 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
| 3089 } // namespace internal | 3440 } // namespace internal |
| 3090 } // namespace v8 | 3441 } // namespace v8 |
| OLD | NEW |