@@ -710,9 +710,8 @@ class IteratingArrayBuiltinReducerAssembler : public JSCallReducerAssembler {
710710 MapInference* inference, const bool has_stability_dependency,
711711 ElementsKind kind, const SharedFunctionInfoRef& shared,
712712 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);
716715 TNode<Object> ReduceArrayPrototypeIndexOfIncludes(
717716 ElementsKind kind, ArrayIndexOfIncludesVariant variant);
718717
@@ -1323,24 +1322,26 @@ TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSlice() {
13231322}
13241323
13251324TNode<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) {
13281326 TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
13291327 TNode<Object> index = ArgumentOrZero(0);
13301328
13311329 TNode<Number> index_num = CheckSmi(index);
13321330 TNode<FixedArrayBase> elements = LoadElements(receiver);
13331331
1332+ TNode<Map> receiver_map =
1333+ TNode<Map>::UncheckedCast(LoadField(AccessBuilder::ForMap(), receiver));
1334+
13341335 auto out = MakeLabel(MachineRepresentation::kTagged);
13351336
1336- for (ElementsKind kind : kinds) {
1337+ for (const MapRef* map : maps) {
1338+ DCHECK(map->supports_fast_array_iteration());
13371339 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);
13411342 Bind(&correct_map_label);
13421343
1343- TNode<Number> length = LoadJSArrayLength(receiver, kind );
1344+ TNode<Number> length = LoadJSArrayLength(receiver, map->elements_kind() );
13441345
13451346 // If index is less than 0, then subtract from length.
13461347 TNode<Boolean> cond = NumberLessThan(index_num, ZeroConstant());
@@ -1359,15 +1360,16 @@ TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeAt(
13591360
13601361 // Retrieving element at index.
13611362 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())) {
13641366 // This case is needed in particular for HOLEY_DOUBLE_ELEMENTS: raw
13651367 // doubles are stored in the FixedDoubleArray, and need to be converted to
13661368 // HeapNumber or to Smi so that this function can return an Object. The
13671369 // automatic converstion performed by
13681370 // RepresentationChanger::GetTaggedRepresentationFor does not handle
13691371 // holes, so we convert manually a potential hole here.
1370- element = TryConvertHoleToUndefined(element, kind );
1372+ element = TryConvertHoleToUndefined(element, map->elements_kind() );
13711373 }
13721374 Goto(&out, element);
13731375
@@ -5633,25 +5635,22 @@ Reduction JSCallReducer::ReduceArrayPrototypeAt(Node* node) {
56335635 MapInference inference(broker(), receiver, effect);
56345636 if (!inference.HaveMaps()) return NoChange();
56355637
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());
56385641 bool needs_fallback_builtin_call = false;
56395642 for (const MapRef& map : inference.GetMaps()) {
56405643 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);
56475645 } else {
56485646 needs_fallback_builtin_call = true;
56495647 }
56505648 }
5649+
56515650 inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
56525651 control, p.feedback());
56535652
5654- if (kinds .empty()) {
5653+ if (maps .empty()) {
56555654 // No map in the feedback supports fast iteration. Keeping the builtin call.
56565655 return NoChange();
56575656 }
@@ -5660,13 +5659,11 @@ Reduction JSCallReducer::ReduceArrayPrototypeAt(Node* node) {
56605659 return NoChange();
56615660 }
56625661
5663- Node* receiver_kind = LoadReceiverElementsKind(receiver, &effect, control);
5664-
56655662 IteratingArrayBuiltinReducerAssembler a(this, node);
56665663 a.InitializeEffectControl(effect, control);
56675664
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);
56705667 return ReplaceWithSubgraph(&a, subgraph);
56715668}
56725669
0 commit comments