diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc index d96a1a63e1f5..23acb893e707 100644 --- a/src/compiler/js-builtin-reducer.cc +++ b/src/compiler/js-builtin-reducer.cc @@ -121,6 +121,24 @@ MaybeHandle GetMapWitness(Node* node) { return MaybeHandle(); } +Maybe GetInstanceTypeWitness(Node* node) { + ZoneHandleSet maps; + Node* receiver = NodeProperties::GetValueInput(node, 1); + Node* effect = NodeProperties::GetEffectInput(node); + NodeProperties::InferReceiverMapsResult result = + NodeProperties::InferReceiverMaps(receiver, effect, &maps); + + if (result == NodeProperties::kNoReceiverMaps || maps.size() == 0) { + return Nothing(); + } + + InstanceType first_type = maps[0]->instance_type(); + for (const Handle& map : maps) { + if (map->instance_type() != first_type) return Nothing(); + } + return Just(first_type); +} + // TODO(turbofan): This was copied from Crankshaft, might be too restrictive. bool IsReadOnlyLengthDescriptor(Handle jsarray_map) { DCHECK(!jsarray_map->is_dictionary_map()); @@ -313,8 +331,9 @@ Reduction JSBuiltinReducer::ReduceArrayIterator(Handle receiver_map, return Replace(value); } -Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext( - Handle iterator_map, Node* node, IterationKind kind) { +Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext(InstanceType type, + Node* node, + IterationKind kind) { Node* iterator = NodeProperties::GetValueInput(node, 1); Node* effect = NodeProperties::GetEffectInput(node); Node* control = NodeProperties::GetControlInput(node); @@ -327,8 +346,8 @@ Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext( return NoChange(); } - ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType( - iterator_map->instance_type()); + ElementsKind elements_kind = + JSArrayIterator::ElementsKindForInstanceType(type); if (IsHoleyElementsKind(elements_kind)) { if (!isolate()->IsNoElementsProtectorIntact()) { @@ -484,15 +503,16 @@ Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext( return Replace(value); } -Reduction JSBuiltinReducer::ReduceTypedArrayIteratorNext( - Handle iterator_map, Node* node, IterationKind kind) { +Reduction JSBuiltinReducer::ReduceTypedArrayIteratorNext(InstanceType type, + Node* node, + IterationKind kind) { Node* iterator = NodeProperties::GetValueInput(node, 1); Node* effect = NodeProperties::GetEffectInput(node); Node* control = NodeProperties::GetControlInput(node); Node* context = NodeProperties::GetContextInput(node); - ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType( - iterator_map->instance_type()); + ElementsKind elements_kind = + JSArrayIterator::ElementsKindForInstanceType(type); Node* array = effect = graph()->NewNode( simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()), @@ -725,65 +745,58 @@ Reduction JSBuiltinReducer::ReduceTypedArrayToStringTag(Node* node) { } Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) { - Handle receiver_map; - if (GetMapWitness(node).ToHandle(&receiver_map)) { - switch (receiver_map->instance_type()) { - case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE: - return ReduceTypedArrayIteratorNext(receiver_map, node, - IterationKind::kKeys); - - case JS_FAST_ARRAY_KEY_ITERATOR_TYPE: - return ReduceFastArrayIteratorNext(receiver_map, node, - IterationKind::kKeys); - - case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE: - return ReduceTypedArrayIteratorNext(receiver_map, node, - IterationKind::kEntries); - - case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE: - case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE: - return ReduceFastArrayIteratorNext(receiver_map, node, - IterationKind::kEntries); - - case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE: - case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE: - case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE: - case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE: - case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE: - case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE: - case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE: - case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE: - case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE: - return ReduceTypedArrayIteratorNext(receiver_map, node, - IterationKind::kValues); - - case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE: - case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE: - case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE: - case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE: - case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE: - case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE: - return ReduceFastArrayIteratorNext(receiver_map, node, - IterationKind::kValues); - - default: - // Slow array iterators are not reduced - return NoChange(); - } + Maybe maybe_type = GetInstanceTypeWitness(node); + if (!maybe_type.IsJust()) return NoChange(); + InstanceType type = maybe_type.FromJust(); + switch (type) { + case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE: + return ReduceTypedArrayIteratorNext(type, node, IterationKind::kKeys); + + case JS_FAST_ARRAY_KEY_ITERATOR_TYPE: + return ReduceFastArrayIteratorNext(type, node, IterationKind::kKeys); + + case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE: + return ReduceTypedArrayIteratorNext(type, node, IterationKind::kEntries); + + case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE: + case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE: + return ReduceFastArrayIteratorNext(type, node, IterationKind::kEntries); + + case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE: + case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE: + case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE: + case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE: + case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE: + case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE: + case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE: + case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE: + case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE: + return ReduceTypedArrayIteratorNext(type, node, IterationKind::kValues); + + case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE: + case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE: + case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE: + case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE: + case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE: + case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE: + return ReduceFastArrayIteratorNext(type, node, IterationKind::kValues); + + default: + // Slow array iterators are not reduced + return NoChange(); } - return NoChange(); } // ES6 section 22.1.2.2 Array.isArray ( arg ) diff --git a/src/compiler/js-builtin-reducer.h b/src/compiler/js-builtin-reducer.h index 2b22b0ce7ce7..2a3fac3b394b 100644 --- a/src/compiler/js-builtin-reducer.h +++ b/src/compiler/js-builtin-reducer.h @@ -47,9 +47,9 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final IterationKind kind, ArrayIteratorKind iter_kind); Reduction ReduceArrayIteratorNext(Node* node); - Reduction ReduceFastArrayIteratorNext(Handle iterator_map, Node* node, + Reduction ReduceFastArrayIteratorNext(InstanceType type, Node* node, IterationKind kind); - Reduction ReduceTypedArrayIteratorNext(Handle iterator_map, Node* node, + Reduction ReduceTypedArrayIteratorNext(InstanceType type, Node* node, IterationKind kind); Reduction ReduceTypedArrayToStringTag(Node* node); Reduction ReduceArrayIsArray(Node* node); diff --git a/src/compiler/node-properties.cc b/src/compiler/node-properties.cc index 51225bf8863a..22ba9364ef6f 100644 --- a/src/compiler/node-properties.cc +++ b/src/compiler/node-properties.cc @@ -461,6 +461,19 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps( if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0); break; } + case IrOpcode::kEffectPhi: { + Node* control = GetControlInput(effect); + if (control->opcode() != IrOpcode::kLoop) { + DCHECK_EQ(IrOpcode::kMerge, control->opcode()); + return kNoReceiverMaps; + } + + // Continue search for receiver map outside the loop. Since operations + // inside the loop may change the map, the result is unreliable. + effect = GetEffectInput(effect, 0); + result = kUnreliableReceiverMaps; + continue; + } default: { DCHECK_EQ(1, effect->op()->EffectOutputCount()); if (effect->op()->EffectInputCount() != 1) {