@@ -710,9 +710,8 @@ class IteratingArrayBuiltinReducerAssembler : public JSCallReducerAssembler { |
710 | 710 | MapInference* inference, const bool has_stability_dependency, |
711 | 711 | ElementsKind kind, const SharedFunctionInfoRef& shared, |
712 | 712 | const NativeContextRef& native_context, ArrayEverySomeVariant variant); |
713 | | - TNode<Object> ReduceArrayPrototypeAt(ZoneVector<ElementsKind> kinds, |
714 | | - bool needs_fallback_builtin_call, |
715 | | - Node* receiver_kind); |
| 713 | + TNode<Object> ReduceArrayPrototypeAt(ZoneVector<const MapRef*> kinds, |
| 714 | + bool needs_fallback_builtin_call); |
716 | 715 | TNode<Object> ReduceArrayPrototypeIndexOfIncludes( |
717 | 716 | ElementsKind kind, ArrayIndexOfIncludesVariant variant); |
718 | 717 |
|
@@ -1323,24 +1322,26 @@ TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSlice() { |
1323 | 1322 | } |
1324 | 1323 |
|
1325 | 1324 | TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeAt( |
1326 | | - ZoneVector<ElementsKind> kinds, bool needs_fallback_builtin_call, |
1327 | | - Node* receiver_kind) { |
| 1325 | + ZoneVector<const MapRef*> maps, bool needs_fallback_builtin_call) { |
1328 | 1326 | TNode<JSArray> receiver = ReceiverInputAs<JSArray>(); |
1329 | 1327 | TNode<Object> index = ArgumentOrZero(0); |
1330 | 1328 |
|
1331 | 1329 | TNode<Number> index_num = CheckSmi(index); |
1332 | 1330 | TNode<FixedArrayBase> elements = LoadElements(receiver); |
1333 | 1331 |
|
| 1332 | + TNode<Map> receiver_map = |
| 1333 | + TNode<Map>::UncheckedCast(LoadField(AccessBuilder::ForMap(), receiver)); |
| 1334 | + |
1334 | 1335 | auto out = MakeLabel(MachineRepresentation::kTagged); |
1335 | 1336 |
|
1336 | | - for (ElementsKind kind : kinds) { |
| 1337 | + for (const MapRef* map : maps) { |
| 1338 | + DCHECK(map->supports_fast_array_iteration()); |
1337 | 1339 | auto correct_map_label = MakeLabel(), wrong_map_label = MakeLabel(); |
1338 | | - Branch(NumberEqual(TNode<Number>::UncheckedCast(receiver_kind), |
1339 | | - NumberConstant(kind)), |
1340 | | - &correct_map_label, &wrong_map_label); |
| 1340 | + TNode<Boolean> is_map_equal = ReferenceEqual(receiver_map, Constant(*map)); |
| 1341 | + Branch(is_map_equal, &correct_map_label, &wrong_map_label); |
1341 | 1342 | Bind(&correct_map_label); |
1342 | 1343 |
|
1343 | | - TNode<Number> length = LoadJSArrayLength(receiver, kind); |
| 1344 | + TNode<Number> length = LoadJSArrayLength(receiver, map->elements_kind()); |
1344 | 1345 |
|
1345 | 1346 | // If index is less than 0, then subtract from length. |
1346 | 1347 | TNode<Boolean> cond = NumberLessThan(index_num, ZeroConstant()); |
@@ -1359,15 +1360,16 @@ TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeAt( |
1359 | 1360 |
|
1360 | 1361 | // Retrieving element at index. |
1361 | 1362 | TNode<Object> element = LoadElement<Object>( |
1362 | | - AccessBuilder::ForFixedArrayElement(kind), elements, real_index_num); |
1363 | | - if (IsHoleyElementsKind(kind)) { |
| 1363 | + AccessBuilder::ForFixedArrayElement(map->elements_kind()), elements, |
| 1364 | + real_index_num); |
| 1365 | + if (IsHoleyElementsKind(map->elements_kind())) { |
1364 | 1366 | // This case is needed in particular for HOLEY_DOUBLE_ELEMENTS: raw |
1365 | 1367 | // doubles are stored in the FixedDoubleArray, and need to be converted to |
1366 | 1368 | // HeapNumber or to Smi so that this function can return an Object. The |
1367 | 1369 | // automatic converstion performed by |
1368 | 1370 | // RepresentationChanger::GetTaggedRepresentationFor does not handle |
1369 | 1371 | // holes, so we convert manually a potential hole here. |
1370 | | - element = TryConvertHoleToUndefined(element, kind); |
| 1372 | + element = TryConvertHoleToUndefined(element, map->elements_kind()); |
1371 | 1373 | } |
1372 | 1374 | Goto(&out, element); |
1373 | 1375 |
|
@@ -5633,25 +5635,22 @@ Reduction JSCallReducer::ReduceArrayPrototypeAt(Node* node) { |
5633 | 5635 | MapInference inference(broker(), receiver, effect); |
5634 | 5636 | if (!inference.HaveMaps()) return NoChange(); |
5635 | 5637 |
|
5636 | | - // Collecting kinds |
5637 | | - ZoneVector<ElementsKind> kinds(broker()->zone()); |
| 5638 | + // Collecting maps, and checking if a fallback builtin call will be required |
| 5639 | + // (it is required if at least one map doesn't support fast array iteration). |
| 5640 | + ZoneVector<const MapRef*> maps(broker()->zone()); |
5638 | 5641 | bool needs_fallback_builtin_call = false; |
5639 | 5642 | for (const MapRef& map : inference.GetMaps()) { |
5640 | 5643 | if (map.supports_fast_array_iteration()) { |
5641 | | - ElementsKind kind = map.elements_kind(); |
5642 | | - // Checking that |kind| isn't already in |kinds|. Using std::find should |
5643 | | - // be fast enough since |kinds| can contain at most 4 items. |
5644 | | - if (std::find(kinds.begin(), kinds.end(), kind) == kinds.end()) { |
5645 | | - kinds.push_back(kind); |
5646 | | - } |
| 5644 | + maps.push_back(&map); |
5647 | 5645 | } else { |
5648 | 5646 | needs_fallback_builtin_call = true; |
5649 | 5647 | } |
5650 | 5648 | } |
| 5649 | + |
5651 | 5650 | inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect, |
5652 | 5651 | control, p.feedback()); |
5653 | 5652 |
|
5654 | | - if (kinds.empty()) { |
| 5653 | + if (maps.empty()) { |
5655 | 5654 | // No map in the feedback supports fast iteration. Keeping the builtin call. |
5656 | 5655 | return NoChange(); |
5657 | 5656 | } |
@@ -5660,13 +5659,11 @@ Reduction JSCallReducer::ReduceArrayPrototypeAt(Node* node) { |
5660 | 5659 | return NoChange(); |
5661 | 5660 | } |
5662 | 5661 |
|
5663 | | - Node* receiver_kind = LoadReceiverElementsKind(receiver, &effect, control); |
5664 | | - |
5665 | 5662 | IteratingArrayBuiltinReducerAssembler a(this, node); |
5666 | 5663 | a.InitializeEffectControl(effect, control); |
5667 | 5664 |
|
5668 | | - TNode<Object> subgraph = a.ReduceArrayPrototypeAt( |
5669 | | - kinds, needs_fallback_builtin_call, receiver_kind); |
| 5665 | + TNode<Object> subgraph = |
| 5666 | + a.ReduceArrayPrototypeAt(maps, needs_fallback_builtin_call); |
5670 | 5667 | return ReplaceWithSubgraph(&a, subgraph); |
5671 | 5668 | } |
5672 | 5669 |
|
|