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 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 Handle<Object> element_k; | 482 Handle<Object> element_k; |
| 483 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k, | 483 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k, |
| 484 Object::GetProperty(&it), Nothing<bool>()); | 484 Object::GetProperty(&it), Nothing<bool>()); |
| 485 | 485 |
| 486 if (value->SameValueZero(*element_k)) return Just(true); | 486 if (value->SameValueZero(*element_k)) return Just(true); |
| 487 } | 487 } |
| 488 | 488 |
| 489 return Just(false); | 489 return Just(false); |
| 490 } | 490 } |
| 491 | 491 |
| 492 static Maybe<int64_t> IndexOfValueSlowPath(Isolate* isolate, | |
| 493 Handle<JSObject> receiver, | |
| 494 Handle<Object> value, | |
| 495 uint32_t start_from, | |
| 496 uint32_t length) { | |
| 497 for (uint32_t k = start_from; k < length; ++k) { | |
| 498 LookupIterator it(isolate, receiver, k); | |
| 499 if (!it.IsFound()) { | |
| 500 continue; | |
| 501 } | |
| 502 Handle<Object> element_k; | |
| 503 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 504 isolate, element_k, Object::GetProperty(&it), Nothing<int64_t>()); | |
| 505 | |
| 506 if (value->StrictEquals(*element_k)) return Just<int64_t>(k); | |
| 507 } | |
| 508 | |
| 509 return Just<int64_t>(-1); | |
| 510 } | |
| 511 | |
| 492 // Base class for element handler implementations. Contains the | 512 // Base class for element handler implementations. Contains the |
| 493 // the common logic for objects with different ElementsKinds. | 513 // the common logic for objects with different ElementsKinds. |
| 494 // Subclasses must specialize method for which the element | 514 // Subclasses must specialize method for which the element |
| 495 // implementation differs from the base class implementation. | 515 // implementation differs from the base class implementation. |
| 496 // | 516 // |
| 497 // This class is intended to be used in the following way: | 517 // This class is intended to be used in the following way: |
| 498 // | 518 // |
| 499 // class SomeElementsAccessor : | 519 // class SomeElementsAccessor : |
| 500 // public ElementsAccessorBase<SomeElementsAccessor, | 520 // public ElementsAccessorBase<SomeElementsAccessor, |
| 501 // BackingStoreClass> { | 521 // BackingStoreClass> { |
| (...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1116 return IncludesValueSlowPath(isolate, receiver, value, start_from, length); | 1136 return IncludesValueSlowPath(isolate, receiver, value, start_from, length); |
| 1117 } | 1137 } |
| 1118 | 1138 |
| 1119 Maybe<bool> IncludesValue(Isolate* isolate, Handle<JSObject> receiver, | 1139 Maybe<bool> IncludesValue(Isolate* isolate, Handle<JSObject> receiver, |
| 1120 Handle<Object> value, uint32_t start_from, | 1140 Handle<Object> value, uint32_t start_from, |
| 1121 uint32_t length) final { | 1141 uint32_t length) final { |
| 1122 return Subclass::IncludesValueImpl(isolate, receiver, value, start_from, | 1142 return Subclass::IncludesValueImpl(isolate, receiver, value, start_from, |
| 1123 length); | 1143 length); |
| 1124 } | 1144 } |
| 1125 | 1145 |
| 1146 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate, | |
| 1147 Handle<JSObject> receiver, | |
| 1148 Handle<Object> value, | |
| 1149 uint32_t start_from, uint32_t length) { | |
| 1150 return IndexOfValueSlowPath(isolate, receiver, value, start_from, length); | |
| 1151 } | |
| 1152 | |
| 1153 Maybe<int64_t> IndexOfValue(Isolate* isolate, Handle<JSObject> receiver, | |
| 1154 Handle<Object> value, uint32_t start_from, | |
| 1155 uint32_t length) final { | |
| 1156 return Subclass::IndexOfValueImpl(isolate, receiver, value, start_from, | |
| 1157 length); | |
| 1158 } | |
| 1159 | |
| 1126 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, | 1160 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
| 1127 uint32_t entry) { | 1161 uint32_t entry) { |
| 1128 return entry; | 1162 return entry; |
| 1129 } | 1163 } |
| 1130 | 1164 |
| 1131 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1165 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
| 1132 FixedArrayBase* backing_store, | 1166 FixedArrayBase* backing_store, |
| 1133 uint32_t index, PropertyFilter filter) { | 1167 uint32_t index, PropertyFilter filter) { |
| 1134 if (IsHoleyElementsKind(kind())) { | 1168 if (IsHoleyElementsKind(kind())) { |
| 1135 return index < Subclass::GetCapacityImpl(holder, backing_store) && | 1169 return index < Subclass::GetCapacityImpl(holder, backing_store) && |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1564 length); | 1598 length); |
| 1565 } | 1599 } |
| 1566 dictionary = handle( | 1600 dictionary = handle( |
| 1567 SeededNumberDictionary::cast(receiver->elements()), isolate); | 1601 SeededNumberDictionary::cast(receiver->elements()), isolate); |
| 1568 break; | 1602 break; |
| 1569 } | 1603 } |
| 1570 } | 1604 } |
| 1571 } | 1605 } |
| 1572 return Just(false); | 1606 return Just(false); |
| 1573 } | 1607 } |
| 1608 | |
| 1609 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate, | |
| 1610 Handle<JSObject> receiver, | |
| 1611 Handle<Object> value, | |
| 1612 uint32_t start_from, uint32_t length) { | |
| 1613 DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver)); | |
| 1614 | |
| 1615 Handle<SeededNumberDictionary> dictionary( | |
| 1616 SeededNumberDictionary::cast(receiver->elements()), isolate); | |
| 1617 // Iterate through entire range, as accessing elements out of order is | |
| 1618 // observable. | |
| 1619 for (uint32_t k = start_from; k < length; ++k) { | |
| 1620 int entry = dictionary->FindEntry(k); | |
| 1621 if (entry == SeededNumberDictionary::kNotFound) { | |
| 1622 continue; | |
| 1623 } | |
| 1624 | |
| 1625 PropertyDetails details = GetDetailsImpl(*dictionary, entry); | |
| 1626 switch (details.kind()) { | |
| 1627 case kData: { | |
| 1628 Object* element_k = dictionary->ValueAt(entry); | |
| 1629 if (value->StrictEquals(element_k)) { | |
| 1630 return Just<int64_t>(k); | |
| 1631 } | |
| 1632 break; | |
| 1633 } | |
| 1634 case kAccessor: { | |
| 1635 LookupIterator it(isolate, receiver, k, | |
| 1636 LookupIterator::OWN_SKIP_INTERCEPTOR); | |
| 1637 DCHECK(it.IsFound()); | |
| 1638 DCHECK_EQ(it.state(), LookupIterator::ACCESSOR); | |
| 1639 Handle<Object> element_k; | |
| 1640 | |
| 1641 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 1642 isolate, element_k, JSObject::GetPropertyWithAccessor(&it), | |
| 1643 Nothing<int64_t>()); | |
| 1644 | |
| 1645 if (value->StrictEquals(*element_k)) return Just<int64_t>(k); | |
| 1646 | |
| 1647 // Bailout to slow path if elements on prototype changed. | |
| 1648 if (!JSObject::PrototypeHasNoElements(isolate, *receiver)) { | |
| 1649 return IndexOfValueSlowPath(isolate, receiver, value, k + 1, | |
| 1650 length); | |
| 1651 } | |
| 1652 | |
| 1653 // Continue if elements unchanged. | |
| 1654 if (*dictionary == receiver->elements()) continue; | |
| 1655 | |
| 1656 // Otherwise, bailout or update elements. | |
| 1657 if (receiver->GetElementsKind() != DICTIONARY_ELEMENTS) { | |
| 1658 // Otherwise, switch to slow path. | |
| 1659 return IndexOfValueSlowPath(isolate, receiver, value, k + 1, | |
| 1660 length); | |
| 1661 } | |
| 1662 dictionary = handle( | |
| 1663 SeededNumberDictionary::cast(receiver->elements()), isolate); | |
| 1664 break; | |
| 1665 } | |
| 1666 } | |
| 1667 } | |
| 1668 return Just<int64_t>(-1); | |
| 1669 } | |
| 1574 }; | 1670 }; |
| 1575 | 1671 |
| 1576 | 1672 |
| 1577 // Super class for all fast element arrays. | 1673 // Super class for all fast element arrays. |
| 1578 template <typename Subclass, typename KindTraits> | 1674 template <typename Subclass, typename KindTraits> |
| 1579 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { | 1675 class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> { |
| 1580 public: | 1676 public: |
| 1581 explicit FastElementsAccessor(const char* name) | 1677 explicit FastElementsAccessor(const char* name) |
| 1582 : ElementsAccessorBase<Subclass, KindTraits>(name) {} | 1678 : ElementsAccessorBase<Subclass, KindTraits>(name) {} |
| 1583 | 1679 |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2074 | 2170 |
| 2075 for (uint32_t k = start_from; k < length; ++k) { | 2171 for (uint32_t k = start_from; k < length; ++k) { |
| 2076 if (elements->get(k)->IsNaN()) return Just(true); | 2172 if (elements->get(k)->IsNaN()) return Just(true); |
| 2077 } | 2173 } |
| 2078 return Just(false); | 2174 return Just(false); |
| 2079 } | 2175 } |
| 2080 } | 2176 } |
| 2081 } | 2177 } |
| 2082 } | 2178 } |
| 2083 | 2179 |
| 2180 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate, | |
| 2181 Handle<JSObject> receiver, | |
| 2182 Handle<Object> search_value, | |
| 2183 uint32_t start_from, uint32_t length) { | |
| 2184 DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver)); | |
| 2185 DisallowHeapAllocation no_gc; | |
| 2186 FixedArrayBase* elements_base = receiver->elements(); | |
| 2187 Object* the_hole = isolate->heap()->the_hole_value(); | |
| 2188 Object* undefined = isolate->heap()->undefined_value(); | |
| 2189 Object* value = *search_value; | |
| 2190 | |
| 2191 if (start_from >= length) return Just<int64_t>(-1); | |
| 2192 | |
| 2193 length = std::min(static_cast<uint32_t>(elements_base->length()), length); | |
| 2194 | |
| 2195 if (!value->IsNumber()) { | |
|
Jakob Kummerow
2016/08/19 09:49:56
Try this simplification:
// Only FAST_{,HOLEY
mattloring
2016/08/19 17:22:33
I did not observe a performance difference so I've
Jakob Kummerow
2016/08/22 09:54:10
FixedArray::cast(receiver->elements()) only works
mattloring
2016/08/22 17:07:03
Ah ok, that makes sense. Thanks!
| |
| 2196 if (value == undefined) { | |
| 2197 // Only FAST_ELEMENTS and FAST_HOLEY_ELEMENTS can have | |
| 2198 // `undefined` as a value. | |
| 2199 if (!IsFastElementsKind(Subclass::kind()) && | |
|
Jakob Kummerow
2016/08/19 09:49:56
This is the FastElementsAccessor. All Subclass::ki
mattloring
2016/08/19 17:22:33
Thank you for the clarification. This check is no
| |
| 2200 !IsFastHoleyElementsKind(Subclass::kind())) { | |
| 2201 return Just<int64_t>(-1); | |
| 2202 } | |
| 2203 | |
| 2204 FixedArray* elements = FixedArray::cast(receiver->elements()); | |
| 2205 | |
| 2206 for (uint32_t k = start_from; k < length; ++k) { | |
| 2207 if (elements->get(k) == undefined) { | |
| 2208 return Just<int64_t>(k); | |
| 2209 } | |
| 2210 } | |
| 2211 return Just<int64_t>(-1); | |
| 2212 } else { | |
| 2213 // Search for non-number, non-Undefined value with either | |
| 2214 // FAST_ELEMENTS or FAST_HOLEY_ELEMENTS. | |
| 2215 DCHECK(IsFastObjectElementsKind(Subclass::kind())); | |
| 2216 FixedArray* elements = FixedArray::cast(receiver->elements()); | |
| 2217 | |
| 2218 for (uint32_t k = start_from; k < length; ++k) { | |
| 2219 Object* element_k = elements->get(k); | |
| 2220 if (element_k == the_hole) { | |
| 2221 continue; | |
| 2222 } | |
| 2223 | |
| 2224 if (value->StrictEquals(element_k)) { | |
| 2225 return Just<int64_t>(k); | |
| 2226 } | |
| 2227 } | |
| 2228 return Just<int64_t>(-1); | |
| 2229 } | |
| 2230 } else { | |
| 2231 if (value->IsNaN()) { | |
| 2232 return Just<int64_t>(-1); | |
| 2233 } | |
| 2234 double search_value = value->Number(); | |
| 2235 FixedArray* elements = FixedArray::cast(receiver->elements()); | |
| 2236 | |
| 2237 for (uint32_t k = start_from; k < length; ++k) { | |
| 2238 Object* element_k = elements->get(k); | |
| 2239 if (element_k->IsNumber() && element_k->Number() == search_value) { | |
| 2240 return Just<int64_t>(k); | |
| 2241 } | |
| 2242 } | |
| 2243 return Just<int64_t>(-1); | |
| 2244 } | |
| 2245 } | |
| 2246 | |
| 2084 private: | 2247 private: |
| 2085 // SpliceShrinkStep might modify the backing_store. | 2248 // SpliceShrinkStep might modify the backing_store. |
| 2086 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, | 2249 static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, |
| 2087 Handle<FixedArrayBase> backing_store, | 2250 Handle<FixedArrayBase> backing_store, |
| 2088 uint32_t start, uint32_t delete_count, | 2251 uint32_t start, uint32_t delete_count, |
| 2089 uint32_t add_count, uint32_t len, | 2252 uint32_t add_count, uint32_t len, |
| 2090 uint32_t new_length) { | 2253 uint32_t new_length) { |
| 2091 const int move_left_count = len - delete_count - start; | 2254 const int move_left_count = len - delete_count - start; |
| 2092 const int move_left_dst_index = start + add_count; | 2255 const int move_left_dst_index = start + add_count; |
| 2093 Subclass::MoveElements(isolate, receiver, backing_store, | 2256 Subclass::MoveElements(isolate, receiver, backing_store, |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2391 case NO_ELEMENTS: | 2554 case NO_ELEMENTS: |
| 2392 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: | 2555 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: |
| 2393 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 2556 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 2394 #undef TYPED_ARRAY_CASE | 2557 #undef TYPED_ARRAY_CASE |
| 2395 // This function is currently only used for JSArrays with non-zero | 2558 // This function is currently only used for JSArrays with non-zero |
| 2396 // length. | 2559 // length. |
| 2397 UNREACHABLE(); | 2560 UNREACHABLE(); |
| 2398 break; | 2561 break; |
| 2399 } | 2562 } |
| 2400 } | 2563 } |
| 2564 | |
| 2565 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate, | |
| 2566 Handle<JSObject> receiver, | |
| 2567 Handle<Object> search_value, | |
| 2568 uint32_t start_from, uint32_t length) { | |
| 2569 DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver)); | |
| 2570 DisallowHeapAllocation no_gc; | |
| 2571 FixedArrayBase* elements_base = receiver->elements(); | |
| 2572 Object* value = *search_value; | |
| 2573 | |
| 2574 if (start_from >= length) return Just<int64_t>(-1); | |
| 2575 | |
| 2576 length = std::min(static_cast<uint32_t>(elements_base->length()), length); | |
| 2577 | |
| 2578 if (!value->IsNumber()) { | |
| 2579 return Just<int64_t>(-1); | |
| 2580 } | |
| 2581 if (value->IsNaN()) { | |
| 2582 return Just<int64_t>(-1); | |
| 2583 } | |
| 2584 double numeric_search_value = value->Number(); | |
| 2585 FixedDoubleArray* elements = FixedDoubleArray::cast(receiver->elements()); | |
| 2586 | |
| 2587 for (uint32_t k = start_from; k < length; ++k) { | |
| 2588 if (elements->is_the_hole(k)) { | |
|
Jakob Kummerow
2016/08/19 09:49:56
(Just for the record: if everything does fit on on
mattloring
2016/08/19 17:22:33
Ack. Thanks for clarifying.
| |
| 2589 continue; | |
| 2590 } | |
| 2591 if (elements->get_scalar(k) == numeric_search_value) { | |
| 2592 return Just<int64_t>(k); | |
| 2593 } | |
| 2594 } | |
| 2595 return Just<int64_t>(-1); | |
| 2596 } | |
| 2401 }; | 2597 }; |
| 2402 | 2598 |
| 2403 | 2599 |
| 2404 class FastPackedDoubleElementsAccessor | 2600 class FastPackedDoubleElementsAccessor |
| 2405 : public FastDoubleElementsAccessor< | 2601 : public FastDoubleElementsAccessor< |
| 2406 FastPackedDoubleElementsAccessor, | 2602 FastPackedDoubleElementsAccessor, |
| 2407 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > { | 2603 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > { |
| 2408 public: | 2604 public: |
| 2409 explicit FastPackedDoubleElementsAccessor(const char* name) | 2605 explicit FastPackedDoubleElementsAccessor(const char* name) |
| 2410 : FastDoubleElementsAccessor< | 2606 : FastDoubleElementsAccessor< |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2584 } | 2780 } |
| 2585 return Just(false); | 2781 return Just(false); |
| 2586 } else { | 2782 } else { |
| 2587 for (uint32_t k = start_from; k < length; ++k) { | 2783 for (uint32_t k = start_from; k < length; ++k) { |
| 2588 double element_k = elements->get_scalar(k); | 2784 double element_k = elements->get_scalar(k); |
| 2589 if (std::isnan(element_k)) return Just(true); | 2785 if (std::isnan(element_k)) return Just(true); |
| 2590 } | 2786 } |
| 2591 return Just(false); | 2787 return Just(false); |
| 2592 } | 2788 } |
| 2593 } | 2789 } |
| 2790 | |
| 2791 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate, | |
| 2792 Handle<JSObject> receiver, | |
| 2793 Handle<Object> value, | |
| 2794 uint32_t start_from, uint32_t length) { | |
| 2795 DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver)); | |
| 2796 DisallowHeapAllocation no_gc; | |
| 2797 | |
| 2798 BackingStore* elements = BackingStore::cast(receiver->elements()); | |
| 2799 if (!value->IsNumber()) return Just<int64_t>(-1); | |
| 2800 | |
| 2801 double search_value = value->Number(); | |
| 2802 | |
| 2803 if (!std::isfinite(search_value)) { | |
| 2804 // Integral types cannot represent +Inf or NaN. | |
| 2805 if (AccessorClass::kind() < FLOAT32_ELEMENTS || | |
| 2806 AccessorClass::kind() > FLOAT64_ELEMENTS) { | |
| 2807 return Just<int64_t>(-1); | |
| 2808 } | |
| 2809 } else if (search_value < std::numeric_limits<ctype>::lowest() || | |
| 2810 search_value > std::numeric_limits<ctype>::max()) { | |
| 2811 // Return false if value can't be represented in this ElementsKind. | |
| 2812 return Just<int64_t>(-1); | |
| 2813 } | |
| 2814 | |
| 2815 // Prototype has no elements, and not searching for the hole --- limit | |
| 2816 // search to backing store length. | |
| 2817 if (static_cast<uint32_t>(elements->length()) < length) { | |
| 2818 length = elements->length(); | |
| 2819 } | |
| 2820 | |
| 2821 if (std::isnan(search_value)) { | |
| 2822 return Just<int64_t>(-1); | |
| 2823 } | |
| 2824 for (uint32_t k = start_from; k < length; ++k) { | |
| 2825 ctype element_k = elements->get_scalar(k); | |
| 2826 if (element_k == search_value) return Just<int64_t>(k); | |
|
Jakob Kummerow
2016/08/19 09:49:56
This still does an implicit cast to double, which
mattloring
2016/08/19 17:22:33
Done.
| |
| 2827 } | |
| 2828 return Just<int64_t>(-1); | |
| 2829 } | |
| 2594 }; | 2830 }; |
| 2595 | 2831 |
| 2596 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ | 2832 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ |
| 2597 typedef TypedElementsAccessor<TYPE##_ELEMENTS, ctype> \ | 2833 typedef TypedElementsAccessor<TYPE##_ELEMENTS, ctype> \ |
| 2598 Fixed##Type##ElementsAccessor; | 2834 Fixed##Type##ElementsAccessor; |
| 2599 | 2835 |
| 2600 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) | 2836 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) |
| 2601 #undef FIXED_ELEMENTS_ACCESSOR | 2837 #undef FIXED_ELEMENTS_ACCESSOR |
| 2602 | 2838 |
| 2603 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> | 2839 template <typename Subclass, typename ArgumentsAccessor, typename KindTraits> |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2862 if (object->map() != *original_map) { | 3098 if (object->map() != *original_map) { |
| 2863 // Some mutation occurred in accessor. Abort "fast" path | 3099 // Some mutation occurred in accessor. Abort "fast" path |
| 2864 return IncludesValueSlowPath(isolate, object, value, k + 1, length); | 3100 return IncludesValueSlowPath(isolate, object, value, k + 1, length); |
| 2865 } | 3101 } |
| 2866 } else if (value->SameValueZero(*element_k)) { | 3102 } else if (value->SameValueZero(*element_k)) { |
| 2867 return Just(true); | 3103 return Just(true); |
| 2868 } | 3104 } |
| 2869 } | 3105 } |
| 2870 return Just(false); | 3106 return Just(false); |
| 2871 } | 3107 } |
| 3108 | |
| 3109 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate, | |
| 3110 Handle<JSObject> object, | |
| 3111 Handle<Object> value, | |
| 3112 uint32_t start_from, uint32_t length) { | |
| 3113 DCHECK(JSObject::PrototypeHasNoElements(isolate, *object)); | |
| 3114 Handle<Map> original_map = handle(object->map(), isolate); | |
| 3115 FixedArray* parameter_map = FixedArray::cast(object->elements()); | |
| 3116 | |
| 3117 for (uint32_t k = start_from; k < length; ++k) { | |
| 3118 uint32_t entry = | |
| 3119 GetEntryForIndexImpl(*object, parameter_map, k, ALL_PROPERTIES); | |
| 3120 if (entry == kMaxUInt32) { | |
| 3121 continue; | |
| 3122 } | |
| 3123 | |
| 3124 Handle<Object> element_k = GetImpl(parameter_map, entry); | |
| 3125 | |
| 3126 if (element_k->IsAccessorPair()) { | |
| 3127 LookupIterator it(isolate, object, k, LookupIterator::OWN); | |
| 3128 DCHECK(it.IsFound()); | |
| 3129 DCHECK_EQ(it.state(), LookupIterator::ACCESSOR); | |
| 3130 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k, | |
| 3131 Object::GetPropertyWithAccessor(&it), | |
| 3132 Nothing<int64_t>()); | |
| 3133 | |
| 3134 if (value->StrictEquals(*element_k)) { | |
| 3135 return Just<int64_t>(k); | |
| 3136 } | |
| 3137 | |
| 3138 if (object->map() != *original_map) { | |
| 3139 // Some mutation occurred in accessor. Abort "fast" path. | |
| 3140 return IndexOfValueSlowPath(isolate, object, value, k + 1, length); | |
| 3141 } | |
| 3142 } else if (value->StrictEquals(*element_k)) { | |
| 3143 return Just<int64_t>(k); | |
| 3144 } | |
| 3145 } | |
| 3146 return Just<int64_t>(-1); | |
| 3147 } | |
| 2872 }; | 3148 }; |
| 2873 | 3149 |
| 2874 | 3150 |
| 2875 class SlowSloppyArgumentsElementsAccessor | 3151 class SlowSloppyArgumentsElementsAccessor |
| 2876 : public SloppyArgumentsElementsAccessor< | 3152 : public SloppyArgumentsElementsAccessor< |
| 2877 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | 3153 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 2878 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { | 3154 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { |
| 2879 public: | 3155 public: |
| 2880 explicit SlowSloppyArgumentsElementsAccessor(const char* name) | 3156 explicit SlowSloppyArgumentsElementsAccessor(const char* name) |
| 2881 : SloppyArgumentsElementsAccessor< | 3157 : SloppyArgumentsElementsAccessor< |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3469 insertion_index += len; | 3745 insertion_index += len; |
| 3470 } | 3746 } |
| 3471 | 3747 |
| 3472 DCHECK_EQ(insertion_index, result_len); | 3748 DCHECK_EQ(insertion_index, result_len); |
| 3473 return result_array; | 3749 return result_array; |
| 3474 } | 3750 } |
| 3475 | 3751 |
| 3476 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3752 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
| 3477 } // namespace internal | 3753 } // namespace internal |
| 3478 } // namespace v8 | 3754 } // namespace v8 |
| OLD | NEW |