diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc index 82c3b1a6d429..85b3689f9132 100644 --- a/src/compiler/js-call-reducer.cc +++ b/src/compiler/js-call-reducer.cc @@ -710,9 +710,8 @@ class IteratingArrayBuiltinReducerAssembler : public JSCallReducerAssembler { MapInference* inference, const bool has_stability_dependency, ElementsKind kind, const SharedFunctionInfoRef& shared, const NativeContextRef& native_context, ArrayEverySomeVariant variant); - TNode ReduceArrayPrototypeAt(ZoneVector kinds, - bool needs_fallback_builtin_call, - Node* receiver_kind); + TNode ReduceArrayPrototypeAt(ZoneVector kinds, + bool needs_fallback_builtin_call); TNode ReduceArrayPrototypeIndexOfIncludes( ElementsKind kind, ArrayIndexOfIncludesVariant variant); @@ -1322,24 +1321,26 @@ TNode JSCallReducerAssembler::ReduceStringPrototypeSlice() { } TNode IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeAt( - ZoneVector kinds, bool needs_fallback_builtin_call, - Node* receiver_kind) { + ZoneVector maps, bool needs_fallback_builtin_call) { TNode receiver = ReceiverInputAs(); TNode index = ArgumentOrZero(0); TNode index_num = CheckSmi(index); TNode elements = LoadElements(receiver); + TNode receiver_map = + TNode::UncheckedCast(LoadField(AccessBuilder::ForMap(), receiver)); + auto out = MakeLabel(MachineRepresentation::kTagged); - for (ElementsKind kind : kinds) { + for (const MapRef* map : maps) { + DCHECK(map->supports_fast_array_iteration()); auto correct_map_label = MakeLabel(), wrong_map_label = MakeLabel(); - Branch(NumberEqual(TNode::UncheckedCast(receiver_kind), - NumberConstant(kind)), - &correct_map_label, &wrong_map_label); + TNode is_map_equal = ReferenceEqual(receiver_map, Constant(*map)); + Branch(is_map_equal, &correct_map_label, &wrong_map_label); Bind(&correct_map_label); - TNode length = LoadJSArrayLength(receiver, kind); + TNode length = LoadJSArrayLength(receiver, map->elements_kind()); // If index is less than 0, then subtract from length. TNode cond = NumberLessThan(index_num, ZeroConstant()); @@ -1358,15 +1359,16 @@ TNode IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeAt( // Retrieving element at index. TNode element = LoadElement( - AccessBuilder::ForFixedArrayElement(kind), elements, real_index_num); - if (IsHoleyElementsKind(kind)) { + AccessBuilder::ForFixedArrayElement(map->elements_kind()), elements, + real_index_num); + if (IsHoleyElementsKind(map->elements_kind())) { // This case is needed in particular for HOLEY_DOUBLE_ELEMENTS: raw // doubles are stored in the FixedDoubleArray, and need to be converted to // HeapNumber or to Smi so that this function can return an Object. The // automatic converstion performed by // RepresentationChanger::GetTaggedRepresentationFor does not handle // holes, so we convert manually a potential hole here. - element = TryConvertHoleToUndefined(element, kind); + element = TryConvertHoleToUndefined(element, map->elements_kind()); } Goto(&out, element); @@ -5632,25 +5634,22 @@ Reduction JSCallReducer::ReduceArrayPrototypeAt(Node* node) { MapInference inference(broker(), receiver, effect); if (!inference.HaveMaps()) return NoChange(); - // Collecting kinds - ZoneVector kinds(broker()->zone()); + // Collecting maps, and checking if a fallback builtin call will be required + // (it is required if at least one map doesn't support fast array iteration). + ZoneVector maps(broker()->zone()); bool needs_fallback_builtin_call = false; for (const MapRef& map : inference.GetMaps()) { if (map.supports_fast_array_iteration()) { - ElementsKind kind = map.elements_kind(); - // Checking that |kind| isn't already in |kinds|. Using std::find should - // be fast enough since |kinds| can contain at most 4 items. - if (std::find(kinds.begin(), kinds.end(), kind) == kinds.end()) { - kinds.push_back(kind); - } + maps.push_back(&map); } else { needs_fallback_builtin_call = true; } } + inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect, control, p.feedback()); - if (kinds.empty()) { + if (maps.empty()) { // No map in the feedback supports fast iteration. Keeping the builtin call. return NoChange(); } @@ -5659,13 +5658,11 @@ Reduction JSCallReducer::ReduceArrayPrototypeAt(Node* node) { return NoChange(); } - Node* receiver_kind = LoadReceiverElementsKind(receiver, &effect, control); - IteratingArrayBuiltinReducerAssembler a(this, node); a.InitializeEffectControl(effect, control); - TNode subgraph = a.ReduceArrayPrototypeAt( - kinds, needs_fallback_builtin_call, receiver_kind); + TNode subgraph = + a.ReduceArrayPrototypeAt(maps, needs_fallback_builtin_call); return ReplaceWithSubgraph(&a, subgraph); }