@@ -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
0 commit comments