LCOV - code coverage report
Current view: top level - src/compiler - js-builtin-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 958 1086 88.2 %
Date: 2017-10-20 Functions: 76 92 82.6 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/js-builtin-reducer.h"
       6             : 
       7             : #include "src/base/bits.h"
       8             : #include "src/builtins/builtins-utils.h"
       9             : #include "src/code-factory.h"
      10             : #include "src/compilation-dependencies.h"
      11             : #include "src/compiler/access-builder.h"
      12             : #include "src/compiler/allocation-builder.h"
      13             : #include "src/compiler/js-graph.h"
      14             : #include "src/compiler/linkage.h"
      15             : #include "src/compiler/node-matchers.h"
      16             : #include "src/compiler/node-properties.h"
      17             : #include "src/compiler/simplified-operator.h"
      18             : #include "src/compiler/type-cache.h"
      19             : #include "src/compiler/types.h"
      20             : #include "src/objects-inl.h"
      21             : 
      22             : namespace v8 {
      23             : namespace internal {
      24             : namespace compiler {
      25             : 
      26             : // Helper class to access JSCall nodes that are potential candidates
      27             : // for reduction when they have a BuiltinFunctionId associated with them.
      28             : class JSCallReduction {
      29             :  public:
      30    31994988 :   explicit JSCallReduction(Node* node) : node_(node) {}
      31             : 
      32             :   // Determines whether the node is a JSCall operation that targets a
      33             :   // constant callee being a well-known builtin with a BuiltinFunctionId.
      34    31934250 :   bool HasBuiltinFunctionId() {
      35    63868500 :     if (node_->opcode() != IrOpcode::kJSCall) return false;
      36      509615 :     HeapObjectMatcher m(NodeProperties::GetValueInput(node_, 0));
      37      731576 :     if (!m.HasValue() || !m.Value()->IsJSFunction()) return false;
      38             :     Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
      39      221905 :     return function->shared()->HasBuiltinFunctionId();
      40             :   }
      41             : 
      42             :   // Retrieves the BuiltinFunctionId as described above.
      43       70911 :   BuiltinFunctionId GetBuiltinFunctionId() {
      44             :     DCHECK_EQ(IrOpcode::kJSCall, node_->opcode());
      45       70911 :     HeapObjectMatcher m(NodeProperties::GetValueInput(node_, 0));
      46             :     Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
      47       70911 :     return function->shared()->builtin_function_id();
      48             :   }
      49             : 
      50             :   bool ReceiverMatches(Type* type) {
      51             :     return NodeProperties::GetType(receiver())->Is(type);
      52             :   }
      53             : 
      54             :   // Determines whether the call takes zero inputs.
      55             :   bool InputsMatchZero() { return GetJSCallArity() == 0; }
      56             : 
      57             :   // Determines whether the call takes one input of the given type.
      58       57471 :   bool InputsMatchOne(Type* t1) {
      59      114861 :     return GetJSCallArity() == 1 &&
      60       57471 :            NodeProperties::GetType(GetJSCallInput(0))->Is(t1);
      61             :   }
      62             : 
      63             :   // Determines whether the call takes two inputs of the given types.
      64        3355 :   bool InputsMatchTwo(Type* t1, Type* t2) {
      65        2616 :     return GetJSCallArity() == 2 &&
      66        4920 :            NodeProperties::GetType(GetJSCallInput(0))->Is(t1) &&
      67        3355 :            NodeProperties::GetType(GetJSCallInput(1))->Is(t2);
      68             :   }
      69             : 
      70             :   // Determines whether the call takes inputs all of the given type.
      71         923 :   bool InputsMatchAll(Type* t) {
      72        4912 :     for (int i = 0; i < GetJSCallArity(); i++) {
      73        1709 :       if (!NodeProperties::GetType(GetJSCallInput(i))->Is(t)) {
      74             :         return false;
      75             :       }
      76             :     }
      77             :     return true;
      78             :   }
      79             : 
      80             :   Node* receiver() { return NodeProperties::GetValueInput(node_, 1); }
      81             :   Node* left() { return GetJSCallInput(0); }
      82             :   Node* right() { return GetJSCallInput(1); }
      83             : 
      84             :   int GetJSCallArity() {
      85             :     DCHECK_EQ(IrOpcode::kJSCall, node_->opcode());
      86             :     // Skip first (i.e. callee) and second (i.e. receiver) operand.
      87       69753 :     return node_->op()->ValueInputCount() - 2;
      88             :   }
      89             : 
      90             :   Node* GetJSCallInput(int index) {
      91             :     DCHECK_EQ(IrOpcode::kJSCall, node_->opcode());
      92             :     DCHECK_LT(index, GetJSCallArity());
      93             :     // Skip first (i.e. callee) and second (i.e. receiver) operand.
      94       88956 :     return NodeProperties::GetValueInput(node_, index + 2);
      95             :   }
      96             : 
      97             :  private:
      98             :   Node* node_;
      99             : };
     100             : 
     101      444099 : JSBuiltinReducer::JSBuiltinReducer(Editor* editor, JSGraph* jsgraph,
     102             :                                    CompilationDependencies* dependencies,
     103             :                                    Handle<Context> native_context)
     104             :     : AdvancedReducer(editor),
     105             :       dependencies_(dependencies),
     106             :       jsgraph_(jsgraph),
     107             :       native_context_(native_context),
     108      444099 :       type_cache_(TypeCache::Get()) {}
     109             : 
     110             : namespace {
     111             : 
     112        1789 : MaybeHandle<Map> GetMapWitness(Node* node) {
     113             :   ZoneHandleSet<Map> maps;
     114        1789 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     115        1789 :   Node* effect = NodeProperties::GetEffectInput(node);
     116             :   NodeProperties::InferReceiverMapsResult result =
     117        1789 :       NodeProperties::InferReceiverMaps(receiver, effect, &maps);
     118        3424 :   if (result == NodeProperties::kReliableReceiverMaps && maps.size() == 1) {
     119        1630 :     return maps[0];
     120             :   }
     121         159 :   return MaybeHandle<Map>();
     122             : }
     123             : 
     124             : // TODO(turbofan): This was copied from Crankshaft, might be too restrictive.
     125        1699 : bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map) {
     126             :   DCHECK(!jsarray_map->is_dictionary_map());
     127             :   Isolate* isolate = jsarray_map->GetIsolate();
     128             :   Handle<Name> length_string = isolate->factory()->length_string();
     129             :   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
     130             :   int number =
     131             :       descriptors->SearchWithCache(isolate, *length_string, *jsarray_map);
     132             :   DCHECK_NE(DescriptorArray::kNotFound, number);
     133        3398 :   return descriptors->GetDetails(number).IsReadOnly();
     134             : }
     135             : 
     136             : // TODO(turbofan): This was copied from Crankshaft, might be too restrictive.
     137        2632 : bool CanInlineArrayResizeOperation(Handle<Map> receiver_map) {
     138             :   Isolate* const isolate = receiver_map->GetIsolate();
     139        2632 :   if (!receiver_map->prototype()->IsJSArray()) return false;
     140             :   Handle<JSArray> receiver_prototype(JSArray::cast(receiver_map->prototype()),
     141             :                                      isolate);
     142             :   // Ensure that all prototypes of the {receiver} are stable.
     143        7429 :   for (PrototypeIterator it(isolate, receiver_prototype, kStartAtReceiver);
     144        3705 :        !it.IsAtEnd(); it.Advance()) {
     145             :     Handle<JSReceiver> current = PrototypeIterator::GetCurrent<JSReceiver>(it);
     146        3724 :     if (!current->map()->is_stable()) return false;
     147             :   }
     148        1835 :   return receiver_map->instance_type() == JS_ARRAY_TYPE &&
     149        1787 :          IsFastElementsKind(receiver_map->elements_kind()) &&
     150        3574 :          !receiver_map->is_dictionary_map() && receiver_map->is_extensible() &&
     151        1787 :          (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
     152        3478 :          isolate->IsFastArrayConstructorPrototypeChainIntact() &&
     153        5241 :          isolate->IsAnyInitialArrayPrototype(receiver_prototype) &&
     154        3542 :          !IsReadOnlyLengthDescriptor(receiver_map);
     155             : }
     156             : 
     157         494 : bool CanInlineJSArrayIteration(Handle<Map> receiver_map) {
     158             :   Isolate* const isolate = receiver_map->GetIsolate();
     159             :   // Ensure that the [[Prototype]] is actually an exotic Array
     160         494 :   if (!receiver_map->prototype()->IsJSArray()) return false;
     161             : 
     162             :   // Don't inline JSArrays with slow elements of any kind
     163         494 :   if (!IsFastElementsKind(receiver_map->elements_kind())) return false;
     164             : 
     165             :   // If the receiver map has packed elements, no need to check the prototype.
     166             :   // This requires a MapCheck where this is used.
     167         494 :   if (!IsHoleyElementsKind(receiver_map->elements_kind())) return true;
     168             : 
     169             :   Handle<JSArray> receiver_prototype(JSArray::cast(receiver_map->prototype()),
     170             :                                      isolate);
     171             :   // Ensure all prototypes of the {receiver} are stable.
     172         113 :   for (PrototypeIterator it(isolate, receiver_prototype, kStartAtReceiver);
     173          55 :        !it.IsAtEnd(); it.Advance()) {
     174             :     Handle<JSReceiver> current = PrototypeIterator::GetCurrent<JSReceiver>(it);
     175          58 :     if (!current->map()->is_stable()) return false;
     176             :   }
     177             : 
     178             :   // For holey Arrays, ensure that the array_protector cell is valid (must be
     179             :   // a CompilationDependency), and the JSArray prototype has not been altered.
     180          26 :   return receiver_map->instance_type() == JS_ARRAY_TYPE &&
     181          26 :          (!receiver_map->is_dictionary_map() || receiver_map->is_stable()) &&
     182          78 :          isolate->IsFastArrayConstructorPrototypeChainIntact() &&
     183          52 :          isolate->IsAnyInitialArrayPrototype(receiver_prototype);
     184             : }
     185             : 
     186             : }  // namespace
     187             : 
     188         610 : Reduction JSBuiltinReducer::ReduceArrayIterator(Node* node,
     189             :                                                 IterationKind kind) {
     190             :   Handle<Map> receiver_map;
     191        1220 :   if (GetMapWitness(node).ToHandle(&receiver_map)) {
     192             :     return ReduceArrayIterator(receiver_map, node, kind,
     193         502 :                                ArrayIteratorKind::kArray);
     194             :   }
     195             :   return NoChange();
     196             : }
     197             : 
     198          50 : Reduction JSBuiltinReducer::ReduceTypedArrayIterator(Node* node,
     199             :                                                      IterationKind kind) {
     200             :   Handle<Map> receiver_map;
     201         150 :   if (GetMapWitness(node).ToHandle(&receiver_map) &&
     202             :       receiver_map->instance_type() == JS_TYPED_ARRAY_TYPE) {
     203             :     return ReduceArrayIterator(receiver_map, node, kind,
     204          50 :                                ArrayIteratorKind::kTypedArray);
     205             :   }
     206             :   return NoChange();
     207             : }
     208             : 
     209         552 : Reduction JSBuiltinReducer::ReduceArrayIterator(Handle<Map> receiver_map,
     210             :                                                 Node* node, IterationKind kind,
     211        3288 :                                                 ArrayIteratorKind iter_kind) {
     212         552 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     213         552 :   Node* effect = NodeProperties::GetEffectInput(node);
     214         552 :   Node* control = NodeProperties::GetControlInput(node);
     215             : 
     216         552 :   if (iter_kind == ArrayIteratorKind::kTypedArray) {
     217             :     // See if we can skip the neutering check.
     218          50 :     if (isolate()->IsArrayBufferNeuteringIntact()) {
     219             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
     220             :       // gets neutered.
     221             :       dependencies()->AssumePropertyCell(
     222             :           factory()->array_buffer_neutering_protector());
     223             :     } else {
     224             :       // For JSTypedArray iterator methods, deopt if the buffer is neutered.
     225             :       // This is potentially a deopt loop, but should be extremely unlikely.
     226             :       DCHECK_EQ(JS_TYPED_ARRAY_TYPE, receiver_map->instance_type());
     227             :       Node* buffer = effect = graph()->NewNode(
     228             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
     229         117 :           receiver, effect, control);
     230             : 
     231             :       // Deoptimize if the {buffer} has been neutered.
     232             :       Node* check = effect = graph()->NewNode(
     233          39 :           simplified()->ArrayBufferWasNeutered(), buffer, effect, control);
     234          39 :       check = graph()->NewNode(simplified()->BooleanNot(), check);
     235             :       effect = graph()->NewNode(
     236             :           simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasNeutered),
     237          39 :           check, effect, control);
     238             :     }
     239             :   }
     240             : 
     241             :   int map_index = -1;
     242         552 :   Node* object_map = jsgraph()->UndefinedConstant();
     243         552 :   switch (receiver_map->instance_type()) {
     244             :     case JS_ARRAY_TYPE:
     245         502 :       if (kind == IterationKind::kKeys) {
     246             :         map_index = Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX;
     247             :       } else {
     248             :         map_index = kind == IterationKind::kValues
     249             :                         ? Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX
     250         494 :                         : Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
     251             : 
     252         494 :         if (CanInlineJSArrayIteration(receiver_map)) {
     253             :           // Use `generic` elements for holey arrays if there may be elements
     254             :           // on the prototype chain.
     255         491 :           map_index += static_cast<int>(receiver_map->elements_kind());
     256         491 :           object_map = jsgraph()->Constant(receiver_map);
     257         491 :           if (IsHoleyElementsKind(receiver_map->elements_kind())) {
     258             :             Handle<JSObject> initial_array_prototype(
     259             :                 native_context()->initial_array_prototype(), isolate());
     260             :             dependencies()->AssumePrototypeMapsStable(receiver_map,
     261          26 :                                                       initial_array_prototype);
     262             :           }
     263             :         } else {
     264             :           map_index += (Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
     265           3 :                         Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX);
     266             :         }
     267             :       }
     268             :       break;
     269             :     case JS_TYPED_ARRAY_TYPE:
     270          50 :       if (kind == IterationKind::kKeys) {
     271             :         map_index = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
     272             :       } else {
     273             :         DCHECK_GE(receiver_map->elements_kind(), UINT8_ELEMENTS);
     274             :         DCHECK_LE(receiver_map->elements_kind(), UINT8_CLAMPED_ELEMENTS);
     275             :         map_index = (kind == IterationKind::kValues
     276             :                          ? Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX
     277          50 :                          : Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX) +
     278          50 :                     (receiver_map->elements_kind() - UINT8_ELEMENTS);
     279             :       }
     280             :       break;
     281             :     default:
     282           0 :       if (kind == IterationKind::kKeys) {
     283             :         map_index = Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX;
     284           0 :       } else if (kind == IterationKind::kValues) {
     285             :         map_index = Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX;
     286             :       } else {
     287             :         map_index = Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
     288             :       }
     289             :       break;
     290             :   }
     291             : 
     292             :   DCHECK_GE(map_index, Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX);
     293             :   DCHECK_LE(map_index, Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX);
     294             : 
     295             :   Handle<Map> map(Map::cast(native_context()->get(map_index)), isolate());
     296             : 
     297             :   // Allocate new iterator and attach the iterator to this object.
     298             :   AllocationBuilder a(jsgraph(), effect, control);
     299         552 :   a.Allocate(JSArrayIterator::kSize, NOT_TENURED, Type::OtherObject());
     300         552 :   a.Store(AccessBuilder::ForMap(), map);
     301             :   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
     302         552 :           jsgraph()->EmptyFixedArrayConstant());
     303             :   a.Store(AccessBuilder::ForJSObjectElements(),
     304         552 :           jsgraph()->EmptyFixedArrayConstant());
     305         552 :   a.Store(AccessBuilder::ForJSArrayIteratorObject(), receiver);
     306         552 :   a.Store(AccessBuilder::ForJSArrayIteratorIndex(), jsgraph()->ZeroConstant());
     307         552 :   a.Store(AccessBuilder::ForJSArrayIteratorObjectMap(), object_map);
     308         552 :   Node* value = effect = a.Finish();
     309             : 
     310             :   // Replace it.
     311         552 :   ReplaceWithValue(node, value, effect, control);
     312         552 :   return Replace(value);
     313             : }
     314             : 
     315         669 : Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext(
     316        4458 :     Handle<Map> iterator_map, Node* node, IterationKind kind) {
     317         669 :   Node* iterator = NodeProperties::GetValueInput(node, 1);
     318         669 :   Node* effect = NodeProperties::GetEffectInput(node);
     319         669 :   Node* control = NodeProperties::GetControlInput(node);
     320         669 :   Node* context = NodeProperties::GetContextInput(node);
     321             : 
     322        1330 :   if (kind != IterationKind::kKeys &&
     323             :       !isolate()->IsFastArrayIterationIntact()) {
     324             :     // Avoid deopt loops for non-key iteration if the
     325             :     // fast_array_iteration_protector cell has been invalidated.
     326             :     return NoChange();
     327             :   }
     328             : 
     329             :   ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
     330         633 :       iterator_map->instance_type());
     331             : 
     332         633 :   if (IsHoleyElementsKind(elements_kind)) {
     333          27 :     if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
     334             :       return NoChange();
     335             :     } else {
     336             :       Handle<JSObject> initial_array_prototype(
     337             :           native_context()->initial_array_prototype(), isolate());
     338             :       dependencies()->AssumePropertyCell(factory()->array_protector());
     339             :     }
     340             :   }
     341             : 
     342             :   Node* array = effect = graph()->NewNode(
     343             :       simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
     344        1899 :       iterator, effect, control);
     345             :   Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
     346        1266 :                                   jsgraph()->UndefinedConstant());
     347             :   Node* branch0 =
     348         633 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
     349             : 
     350             :   Node* vdone_false0;
     351             :   Node* vfalse0;
     352             :   Node* efalse0 = effect;
     353         633 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
     354             :   {
     355             :     // iterator.[[IteratedObject]] !== undefined, continue iterating.
     356             :     Node* index = efalse0 = graph()->NewNode(
     357             :         simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
     358             :             JS_ARRAY_TYPE, elements_kind)),
     359        1899 :         iterator, efalse0, if_false0);
     360             : 
     361             :     Node* length = efalse0 = graph()->NewNode(
     362             :         simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
     363        1899 :         array, efalse0, if_false0);
     364             :     Node* check1 =
     365         633 :         graph()->NewNode(simplified()->NumberLessThan(), index, length);
     366             :     Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
     367         633 :                                      check1, if_false0);
     368             : 
     369             :     Node* vdone_true1;
     370             :     Node* vtrue1;
     371             :     Node* etrue1 = efalse0;
     372         633 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
     373             :     {
     374             :       // iterator.[[NextIndex]] < array.length, continue iterating
     375         633 :       vdone_true1 = jsgraph()->FalseConstant();
     376         633 :       if (kind == IterationKind::kKeys) {
     377             :         vtrue1 = index;
     378             :       } else {
     379             :         // For value/entry iteration, first step is a mapcheck to ensure
     380             :         // inlining is still valid.
     381             :         Node* array_map = etrue1 =
     382             :             graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
     383        1875 :                              array, etrue1, if_true1);
     384             :         Node* orig_map = etrue1 =
     385             :             graph()->NewNode(simplified()->LoadField(
     386             :                                  AccessBuilder::ForJSArrayIteratorObjectMap()),
     387        1875 :                              iterator, etrue1, if_true1);
     388             :         Node* check_map = graph()->NewNode(simplified()->ReferenceEqual(),
     389         625 :                                            array_map, orig_map);
     390             :         etrue1 =
     391             :             graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongMap),
     392         625 :                              check_map, etrue1, if_true1);
     393             :       }
     394             : 
     395         633 :       if (kind != IterationKind::kKeys) {
     396             :         Node* elements = etrue1 = graph()->NewNode(
     397             :             simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
     398        1875 :             array, etrue1, if_true1);
     399             :         Node* value = etrue1 = graph()->NewNode(
     400             :             simplified()->LoadElement(
     401             :                 AccessBuilder::ForFixedArrayElement(elements_kind)),
     402        1875 :             elements, index, etrue1, if_true1);
     403             : 
     404             :         // Convert hole to undefined if needed.
     405         625 :         if (elements_kind == HOLEY_ELEMENTS ||
     406             :             elements_kind == HOLEY_SMI_ELEMENTS) {
     407             :           value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(),
     408          19 :                                    value);
     409         606 :         } else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
     410             :           // TODO(6587): avoid deopt if not all uses of value are truncated.
     411             :           CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
     412             :           value = etrue1 = graph()->NewNode(
     413           8 :               simplified()->CheckFloat64Hole(mode), value, etrue1, if_true1);
     414             :         }
     415             : 
     416         625 :         if (kind == IterationKind::kEntries) {
     417             :           // Allocate elements for key/value pair
     418             :           vtrue1 = etrue1 =
     419             :               graph()->NewNode(javascript()->CreateKeyValueArray(), index,
     420           7 :                                value, context, etrue1);
     421             :         } else {
     422             :           DCHECK_EQ(kind, IterationKind::kValues);
     423             :           vtrue1 = value;
     424             :         }
     425             :       }
     426             : 
     427             :       Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
     428        1266 :                                           jsgraph()->OneConstant());
     429         633 :       next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
     430             : 
     431             :       etrue1 = graph()->NewNode(
     432             :           simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
     433             :               JS_ARRAY_TYPE, elements_kind)),
     434        1899 :           iterator, next_index, etrue1, if_true1);
     435             :     }
     436             : 
     437             :     Node* vdone_false1;
     438             :     Node* vfalse1;
     439             :     Node* efalse1 = efalse0;
     440         633 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
     441             :     {
     442             :       // iterator.[[NextIndex]] >= array.length, stop iterating.
     443         633 :       vdone_false1 = jsgraph()->TrueConstant();
     444         633 :       vfalse1 = jsgraph()->UndefinedConstant();
     445             :       efalse1 = graph()->NewNode(
     446             :           simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
     447        1899 :           iterator, vfalse1, efalse1, if_false1);
     448             :     }
     449             : 
     450         633 :     if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
     451             :     efalse0 =
     452         633 :         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
     453             :     vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     454         633 :                                vtrue1, vfalse1, if_false0);
     455             :     vdone_false0 =
     456             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     457         633 :                          vdone_true1, vdone_false1, if_false0);
     458             :   }
     459             : 
     460             :   Node* vdone_true0;
     461             :   Node* vtrue0;
     462             :   Node* etrue0 = effect;
     463         633 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
     464             :   {
     465             :     // iterator.[[IteratedObject]] === undefined, the iterator is done.
     466         633 :     vdone_true0 = jsgraph()->TrueConstant();
     467         633 :     vtrue0 = jsgraph()->UndefinedConstant();
     468             :   }
     469             : 
     470         633 :   control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
     471         633 :   effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
     472             :   Node* value =
     473             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     474         633 :                        vfalse0, vtrue0, control);
     475             :   Node* done =
     476             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     477         633 :                        vdone_false0, vdone_true0, control);
     478             : 
     479             :   // Create IteratorResult object.
     480             :   value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
     481         633 :                                     value, done, context, effect);
     482         633 :   ReplaceWithValue(node, value, effect, control);
     483             :   return Replace(value);
     484             : }
     485             : 
     486          50 : Reduction JSBuiltinReducer::ReduceTypedArrayIteratorNext(
     487         361 :     Handle<Map> iterator_map, Node* node, IterationKind kind) {
     488          50 :   Node* iterator = NodeProperties::GetValueInput(node, 1);
     489          50 :   Node* effect = NodeProperties::GetEffectInput(node);
     490          50 :   Node* control = NodeProperties::GetControlInput(node);
     491          50 :   Node* context = NodeProperties::GetContextInput(node);
     492             : 
     493             :   ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
     494          50 :       iterator_map->instance_type());
     495             : 
     496             :   Node* array = effect = graph()->NewNode(
     497             :       simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
     498         150 :       iterator, effect, control);
     499             :   Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
     500         100 :                                   jsgraph()->UndefinedConstant());
     501             :   Node* branch0 =
     502          50 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
     503             : 
     504             :   Node* vdone_false0;
     505             :   Node* vfalse0;
     506             :   Node* efalse0 = effect;
     507          50 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
     508             :   {
     509             :     // iterator.[[IteratedObject]] !== undefined, continue iterating.
     510             :     Node* index = efalse0 = graph()->NewNode(
     511             :         simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
     512             :             JS_TYPED_ARRAY_TYPE, elements_kind)),
     513         150 :         iterator, efalse0, if_false0);
     514             : 
     515             :     // typedarray.[[ViewedArrayBuffer]]
     516             :     Node* buffer = efalse0 = graph()->NewNode(
     517             :         simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
     518         150 :         array, efalse0, if_false0);
     519             : 
     520             :     // See if we can skip the neutering check.
     521          50 :     if (isolate()->IsArrayBufferNeuteringIntact()) {
     522             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
     523             :       // gets neutered.
     524             :       dependencies()->AssumePropertyCell(
     525             :           factory()->array_buffer_neutering_protector());
     526             :     } else {
     527             :       // Deoptimize if the array buffer was neutered.
     528             :       Node* check1 = efalse0 = graph()->NewNode(
     529          39 :           simplified()->ArrayBufferWasNeutered(), buffer, efalse0, if_false0);
     530          39 :       check1 = graph()->NewNode(simplified()->BooleanNot(), check1);
     531             :       efalse0 = graph()->NewNode(
     532             :           simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasNeutered),
     533          39 :           check1, efalse0, if_false0);
     534             :     }
     535             : 
     536             :     Node* length = efalse0 = graph()->NewNode(
     537             :         simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()), array,
     538         150 :         efalse0, if_false0);
     539             : 
     540             :     Node* check2 =
     541          50 :         graph()->NewNode(simplified()->NumberLessThan(), index, length);
     542             :     Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
     543          50 :                                      check2, if_false0);
     544             : 
     545             :     Node* vdone_true2;
     546             :     Node* vtrue2;
     547             :     Node* etrue2 = efalse0;
     548          50 :     Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
     549             :     {
     550             :       // iterator.[[NextIndex]] < array.length, continue iterating
     551          50 :       vdone_true2 = jsgraph()->FalseConstant();
     552          50 :       if (kind == IterationKind::kKeys) {
     553             :         vtrue2 = index;
     554             :       }
     555             : 
     556             :       Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
     557         100 :                                           jsgraph()->OneConstant());
     558          50 :       next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
     559             : 
     560             :       etrue2 = graph()->NewNode(
     561             :           simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
     562             :               JS_TYPED_ARRAY_TYPE, elements_kind)),
     563         150 :           iterator, next_index, etrue2, if_true2);
     564             : 
     565          50 :       if (kind != IterationKind::kKeys) {
     566             :         Node* elements = etrue2 = graph()->NewNode(
     567             :             simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
     568         150 :             array, etrue2, if_true2);
     569             :         Node* base_ptr = etrue2 = graph()->NewNode(
     570             :             simplified()->LoadField(
     571             :                 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
     572         150 :             elements, etrue2, if_true2);
     573             :         Node* external_ptr = etrue2 = graph()->NewNode(
     574             :             simplified()->LoadField(
     575             :                 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
     576         150 :             elements, etrue2, if_true2);
     577             : 
     578          50 :         ExternalArrayType array_type = kExternalInt8Array;
     579          50 :         switch (elements_kind) {
     580             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
     581             :   case TYPE##_ELEMENTS:                                 \
     582             :     array_type = kExternal##Type##Array;                \
     583             :     break;
     584          18 :           TYPED_ARRAYS(TYPED_ARRAY_CASE)
     585             :           default:
     586           0 :             UNREACHABLE();
     587             : #undef TYPED_ARRAY_CASE
     588             :         }
     589             : 
     590             :         Node* value = etrue2 =
     591             :             graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
     592          50 :                              base_ptr, external_ptr, index, etrue2, if_true2);
     593             : 
     594          50 :         if (kind == IterationKind::kEntries) {
     595             :           // Allocate elements for key/value pair
     596             :           vtrue2 = etrue2 =
     597             :               graph()->NewNode(javascript()->CreateKeyValueArray(), index,
     598           7 :                                value, context, etrue2);
     599             :         } else {
     600             :           DCHECK_EQ(IterationKind::kValues, kind);
     601             :           vtrue2 = value;
     602             :         }
     603             :       }
     604             :     }
     605             : 
     606             :     Node* vdone_false2;
     607             :     Node* vfalse2;
     608             :     Node* efalse2 = efalse0;
     609          50 :     Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
     610             :     {
     611             :       // iterator.[[NextIndex]] >= array.length, stop iterating.
     612          50 :       vdone_false2 = jsgraph()->TrueConstant();
     613          50 :       vfalse2 = jsgraph()->UndefinedConstant();
     614             :       efalse2 = graph()->NewNode(
     615             :           simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
     616         150 :           iterator, vfalse2, efalse2, if_false2);
     617             :     }
     618             : 
     619          50 :     if_false0 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
     620             :     efalse0 =
     621          50 :         graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_false0);
     622             :     vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     623          50 :                                vtrue2, vfalse2, if_false0);
     624             :     vdone_false0 =
     625             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     626          50 :                          vdone_true2, vdone_false2, if_false0);
     627             :   }
     628             : 
     629             :   Node* vdone_true0;
     630             :   Node* vtrue0;
     631             :   Node* etrue0 = effect;
     632          50 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
     633             :   {
     634             :     // iterator.[[IteratedObject]] === undefined, the iterator is done.
     635          50 :     vdone_true0 = jsgraph()->TrueConstant();
     636          50 :     vtrue0 = jsgraph()->UndefinedConstant();
     637             :   }
     638             : 
     639          50 :   control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
     640          50 :   effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
     641             :   Node* value =
     642             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     643          50 :                        vfalse0, vtrue0, control);
     644             :   Node* done =
     645             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     646          50 :                        vdone_false0, vdone_true0, control);
     647             : 
     648             :   // Create IteratorResult object.
     649             :   value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
     650          50 :                                     value, done, context, effect);
     651          50 :   ReplaceWithValue(node, value, effect, control);
     652          50 :   return Replace(value);
     653             : }
     654             : 
     655             : // ES #sec-get-%typedarray%.prototype-@@tostringtag
     656         504 : Reduction JSBuiltinReducer::ReduceTypedArrayToStringTag(Node* node) {
     657          21 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     658          21 :   Node* effect = NodeProperties::GetEffectInput(node);
     659          21 :   Node* control = NodeProperties::GetControlInput(node);
     660             : 
     661          21 :   NodeVector values(graph()->zone());
     662          21 :   NodeVector effects(graph()->zone());
     663          21 :   NodeVector controls(graph()->zone());
     664             : 
     665          21 :   Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
     666             :   control =
     667          63 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
     668             : 
     669          42 :   values.push_back(jsgraph()->UndefinedConstant());
     670          21 :   effects.push_back(effect);
     671          84 :   controls.push_back(graph()->NewNode(common()->IfTrue(), control));
     672             : 
     673          63 :   control = graph()->NewNode(common()->IfFalse(), control);
     674             :   Node* receiver_map = effect =
     675             :       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
     676          63 :                        receiver, effect, control);
     677             :   Node* receiver_bit_field2 = effect = graph()->NewNode(
     678             :       simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map,
     679          63 :       effect, control);
     680             :   Node* receiver_elements_kind = graph()->NewNode(
     681             :       simplified()->NumberShiftRightLogical(),
     682             :       graph()->NewNode(simplified()->NumberBitwiseAnd(), receiver_bit_field2,
     683             :                        jsgraph()->Constant(Map::ElementsKindBits::kMask)),
     684          84 :       jsgraph()->Constant(Map::ElementsKindBits::kShift));
     685             : 
     686             :   // Offset the elements kind by FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
     687             :   // so that the branch cascade below is turned into a simple table
     688             :   // switch by the ControlFlowOptimizer later.
     689             :   receiver_elements_kind = graph()->NewNode(
     690             :       simplified()->NumberSubtract(), receiver_elements_kind,
     691          42 :       jsgraph()->Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));
     692             : 
     693             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                \
     694             :   do {                                                                 \
     695             :     Node* check = graph()->NewNode(                                    \
     696             :         simplified()->NumberEqual(), receiver_elements_kind,           \
     697             :         jsgraph()->Constant(TYPE##_ELEMENTS -                          \
     698             :                             FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));   \
     699             :     control = graph()->NewNode(common()->Branch(), check, control);    \
     700             :     values.push_back(jsgraph()->HeapConstant(                          \
     701             :         factory()->InternalizeUtf8String(#Type "Array")));             \
     702             :     effects.push_back(effect);                                         \
     703             :     controls.push_back(graph()->NewNode(common()->IfTrue(), control)); \
     704             :     control = graph()->NewNode(common()->IfFalse(), control);          \
     705             :   } while (false);
     706        2457 :   TYPED_ARRAYS(TYPED_ARRAY_CASE)
     707             : #undef TYPED_ARRAY_CASE
     708             : 
     709          42 :   values.push_back(jsgraph()->UndefinedConstant());
     710          21 :   effects.push_back(effect);
     711          21 :   controls.push_back(control);
     712             : 
     713          42 :   int const count = static_cast<int>(controls.size());
     714          42 :   control = graph()->NewNode(common()->Merge(count), count, &controls.front());
     715          21 :   effects.push_back(control);
     716             :   effect =
     717          63 :       graph()->NewNode(common()->EffectPhi(count), count + 1, &effects.front());
     718          21 :   values.push_back(control);
     719             :   Node* value =
     720             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
     721          42 :                        count + 1, &values.front());
     722          21 :   ReplaceWithValue(node, value, effect, control);
     723          21 :   return Replace(value);
     724             : }
     725             : 
     726         728 : Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) {
     727             :   Handle<Map> receiver_map;
     728        1456 :   if (GetMapWitness(node).ToHandle(&receiver_map)) {
     729         719 :     switch (receiver_map->instance_type()) {
     730             :       case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
     731             :         return ReduceTypedArrayIteratorNext(receiver_map, node,
     732           0 :                                             IterationKind::kKeys);
     733             : 
     734             :       case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
     735             :         return ReduceFastArrayIteratorNext(receiver_map, node,
     736           8 :                                            IterationKind::kKeys);
     737             : 
     738             :       case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     739             :       case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     740             :       case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     741             :       case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     742             :       case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     743             :       case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     744             :       case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     745             :       case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     746             :       case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     747             :         return ReduceTypedArrayIteratorNext(receiver_map, node,
     748           7 :                                             IterationKind::kEntries);
     749             : 
     750             :       case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     751             :       case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     752             :       case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     753             :       case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     754             :       case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     755             :       case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     756             :         return ReduceFastArrayIteratorNext(receiver_map, node,
     757           7 :                                            IterationKind::kEntries);
     758             : 
     759             :       case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
     760             :       case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
     761             :       case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
     762             :       case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
     763             :       case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
     764             :       case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
     765             :       case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
     766             :       case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
     767             :       case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
     768             :         return ReduceTypedArrayIteratorNext(receiver_map, node,
     769          43 :                                             IterationKind::kValues);
     770             : 
     771             :       case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
     772             :       case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
     773             :       case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
     774             :       case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
     775             :       case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
     776             :       case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
     777             :         return ReduceFastArrayIteratorNext(receiver_map, node,
     778         654 :                                            IterationKind::kValues);
     779             : 
     780             :       default:
     781             :         // Slow array iterators are not reduced
     782             :         return NoChange();
     783             :     }
     784             :   }
     785             :   return NoChange();
     786             : }
     787             : 
     788             : // ES6 section 22.1.2.2 Array.isArray ( arg )
     789          52 : Reduction JSBuiltinReducer::ReduceArrayIsArray(Node* node) {
     790             :   // We certainly know that undefined is not an array.
     791          28 :   if (node->op()->ValueInputCount() < 3) {
     792           0 :     Node* value = jsgraph()->FalseConstant();
     793          14 :     ReplaceWithValue(node, value);
     794             :     return Replace(value);
     795             :   }
     796          14 :   Node* value = NodeProperties::GetValueInput(node, 2);
     797             :   Type* value_type = NodeProperties::GetType(value);
     798          14 :   Node* context = NodeProperties::GetContextInput(node);
     799          14 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     800          14 :   Node* effect = NodeProperties::GetEffectInput(node);
     801          14 :   Node* control = NodeProperties::GetControlInput(node);
     802             : 
     803             :   // Constant-fold based on {value} type.
     804          14 :   if (value_type->Is(Type::Array())) {
     805           8 :     Node* value = jsgraph()->TrueConstant();
     806             :     ReplaceWithValue(node, value);
     807             :     return Replace(value);
     808           6 :   } else if (!value_type->Maybe(Type::ArrayOrProxy())) {
     809           0 :     Node* value = jsgraph()->FalseConstant();
     810             :     ReplaceWithValue(node, value);
     811             :     return Replace(value);
     812             :   }
     813             : 
     814             :   int count = 0;
     815             :   Node* values[5];
     816             :   Node* effects[5];
     817             :   Node* controls[4];
     818             : 
     819             :   // Check if the {value} is a Smi.
     820           6 :   Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
     821             :   control =
     822           6 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
     823             : 
     824             :   // The {value} is a Smi.
     825          12 :   controls[count] = graph()->NewNode(common()->IfTrue(), control);
     826           6 :   effects[count] = effect;
     827           6 :   values[count] = jsgraph()->FalseConstant();
     828             :   count++;
     829             : 
     830           6 :   control = graph()->NewNode(common()->IfFalse(), control);
     831             : 
     832             :   // Load the {value}s instance type.
     833             :   Node* value_map = effect = graph()->NewNode(
     834          18 :       simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
     835             :   Node* value_instance_type = effect = graph()->NewNode(
     836             :       simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
     837          18 :       effect, control);
     838             : 
     839             :   // Check if the {value} is a JSArray.
     840             :   check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type,
     841          12 :                            jsgraph()->Constant(JS_ARRAY_TYPE));
     842           6 :   control = graph()->NewNode(common()->Branch(), check, control);
     843             : 
     844             :   // The {value} is a JSArray.
     845          12 :   controls[count] = graph()->NewNode(common()->IfTrue(), control);
     846           6 :   effects[count] = effect;
     847           6 :   values[count] = jsgraph()->TrueConstant();
     848             :   count++;
     849             : 
     850           6 :   control = graph()->NewNode(common()->IfFalse(), control);
     851             : 
     852             :   // Check if the {value} is a JSProxy.
     853             :   check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type,
     854          12 :                            jsgraph()->Constant(JS_PROXY_TYPE));
     855             :   control =
     856           6 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
     857             : 
     858             :   // The {value} is neither a JSArray nor a JSProxy.
     859          12 :   controls[count] = graph()->NewNode(common()->IfFalse(), control);
     860           6 :   effects[count] = effect;
     861           6 :   values[count] = jsgraph()->FalseConstant();
     862             :   count++;
     863             : 
     864           6 :   control = graph()->NewNode(common()->IfTrue(), control);
     865             : 
     866             :   // Let the %ArrayIsArray runtime function deal with the JSProxy {value}.
     867             :   value = effect = control =
     868             :       graph()->NewNode(javascript()->CallRuntime(Runtime::kArrayIsArray), value,
     869           6 :                        context, frame_state, effect, control);
     870             :   NodeProperties::SetType(value, Type::Boolean());
     871             : 
     872             :   // Update potential {IfException} uses of {node} to point to the above
     873             :   // %ArrayIsArray runtime call node instead.
     874           6 :   Node* on_exception = nullptr;
     875           6 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
     876           0 :     NodeProperties::ReplaceControlInput(on_exception, control);
     877           0 :     NodeProperties::ReplaceEffectInput(on_exception, effect);
     878           0 :     control = graph()->NewNode(common()->IfSuccess(), control);
     879           0 :     Revisit(on_exception);
     880             :   }
     881             : 
     882             :   // The {value} is neither a JSArray nor a JSProxy.
     883           6 :   controls[count] = control;
     884           6 :   effects[count] = effect;
     885           6 :   values[count] = value;
     886             :   count++;
     887             : 
     888          12 :   control = graph()->NewNode(common()->Merge(count), count, controls);
     889           6 :   effects[count] = control;
     890           6 :   values[count] = control;
     891          12 :   effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects);
     892             :   value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
     893          12 :                            count + 1, values);
     894             :   ReplaceWithValue(node, value, effect, control);
     895             :   return Replace(value);
     896             : }
     897             : 
     898             : // ES6 section 22.1.3.17 Array.prototype.pop ( )
     899         870 : Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) {
     900             :   Handle<Map> receiver_map;
     901         198 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     902         198 :   Node* effect = NodeProperties::GetEffectInput(node);
     903         198 :   Node* control = NodeProperties::GetControlInput(node);
     904             :   // TODO(turbofan): Extend this to also handle fast holey double elements
     905             :   // once we got the hole NaN mess sorted out in TurboFan/V8.
     906         589 :   if (GetMapWitness(node).ToHandle(&receiver_map) &&
     907         310 :       CanInlineArrayResizeOperation(receiver_map) &&
     908             :       receiver_map->elements_kind() != HOLEY_DOUBLE_ELEMENTS) {
     909             :     // Install code dependencies on the {receiver} prototype maps and the
     910             :     // global array protector cell.
     911             :     dependencies()->AssumePropertyCell(factory()->array_protector());
     912         112 :     dependencies()->AssumePrototypeMapsStable(receiver_map);
     913             : 
     914             :     // Load the "length" property of the {receiver}.
     915             :     Node* length = effect = graph()->NewNode(
     916             :         simplified()->LoadField(
     917             :             AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
     918         336 :         receiver, effect, control);
     919             : 
     920             :     // Check if the {receiver} has any elements.
     921             :     Node* check = graph()->NewNode(simplified()->NumberEqual(), length,
     922         224 :                                    jsgraph()->ZeroConstant());
     923             :     Node* branch =
     924         112 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
     925             : 
     926         112 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
     927             :     Node* etrue = effect;
     928         112 :     Node* vtrue = jsgraph()->UndefinedConstant();
     929             : 
     930         112 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
     931             :     Node* efalse = effect;
     932             :     Node* vfalse;
     933             :     {
     934             :       // TODO(tebbi): We should trim the backing store if the capacity is too
     935             :       // big, as implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
     936             : 
     937             :       // Load the elements backing store from the {receiver}.
     938             :       Node* elements = efalse = graph()->NewNode(
     939             :           simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
     940         336 :           receiver, efalse, if_false);
     941             : 
     942             :       // Ensure that we aren't popping from a copy-on-write backing store.
     943         112 :       if (IsSmiOrObjectElementsKind(receiver_map->elements_kind())) {
     944             :         elements = efalse =
     945             :             graph()->NewNode(simplified()->EnsureWritableFastElements(),
     946          78 :                              receiver, elements, efalse, if_false);
     947             :       }
     948             : 
     949             :       // Compute the new {length}.
     950             :       length = graph()->NewNode(simplified()->NumberSubtract(), length,
     951         224 :                                 jsgraph()->OneConstant());
     952             : 
     953             :       // Store the new {length} to the {receiver}.
     954             :       efalse = graph()->NewNode(
     955             :           simplified()->StoreField(
     956             :               AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
     957         336 :           receiver, length, efalse, if_false);
     958             : 
     959             :       // Load the last entry from the {elements}.
     960             :       vfalse = efalse = graph()->NewNode(
     961             :           simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(
     962             :               receiver_map->elements_kind())),
     963         336 :           elements, length, efalse, if_false);
     964             : 
     965             :       // Store a hole to the element we just removed from the {receiver}.
     966             :       efalse = graph()->NewNode(
     967             :           simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(
     968             :               GetHoleyElementsKind(receiver_map->elements_kind()))),
     969         448 :           elements, length, jsgraph()->TheHoleConstant(), efalse, if_false);
     970             :     }
     971             : 
     972         112 :     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
     973         112 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
     974             :     Node* value =
     975             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     976         112 :                          vtrue, vfalse, control);
     977             : 
     978             :     // Convert the hole to undefined. Do this last, so that we can optimize
     979             :     // conversion operator via some smart strength reduction in many cases.
     980         112 :     if (IsHoleyElementsKind(receiver_map->elements_kind())) {
     981             :       value =
     982          22 :           graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
     983             :     }
     984             : 
     985         112 :     ReplaceWithValue(node, value, effect, control);
     986             :     return Replace(value);
     987             :   }
     988             :   return NoChange();
     989             : }
     990             : 
     991             : // ES6 section 22.1.3.18 Array.prototype.push ( )
     992        9814 : Reduction JSBuiltinReducer::ReduceArrayPush(Node* node) {
     993             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     994        4952 :   int const num_values = node->op()->ValueInputCount() - 2;
     995        2476 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     996        2476 :   Node* effect = NodeProperties::GetEffectInput(node);
     997        2476 :   Node* control = NodeProperties::GetControlInput(node);
     998             :   ZoneHandleSet<Map> receiver_maps;
     999             :   NodeProperties::InferReceiverMapsResult result =
    1000        2476 :       NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
    1001        2476 :   if (receiver_maps.size() != 1) return NoChange();
    1002             :   DCHECK_NE(NodeProperties::kNoReceiverMaps, result);
    1003             : 
    1004             :   // TODO(turbofan): Relax this to deal with multiple {receiver} maps.
    1005             :   Handle<Map> receiver_map = receiver_maps[0];
    1006        2273 :   if (CanInlineArrayResizeOperation(receiver_map)) {
    1007             :     // Collect the value inputs to push.
    1008        1454 :     std::vector<Node*> values(num_values);
    1009        3076 :     for (int i = 0; i < num_values; ++i) {
    1010        3244 :       values[i] = NodeProperties::GetValueInput(node, 2 + i);
    1011             :     }
    1012             : 
    1013             :     // Install code dependencies on the {receiver} prototype maps and the
    1014             :     // global array protector cell.
    1015             :     dependencies()->AssumePropertyCell(factory()->array_protector());
    1016        1454 :     dependencies()->AssumePrototypeMapsStable(receiver_map);
    1017             : 
    1018             :     // If the {receiver_maps} information is not reliable, we need
    1019             :     // to check that the {receiver} still has one of these maps.
    1020        1454 :     if (result == NodeProperties::kUnreliableReceiverMaps) {
    1021         306 :       if (receiver_map->is_stable()) {
    1022           0 :         dependencies()->AssumeMapStable(receiver_map);
    1023             :       } else {
    1024             :         // TODO(turbofan): This is a potential - yet unlikely - deoptimization
    1025             :         // loop, since we might not learn from this deoptimization in baseline
    1026             :         // code. We need a way to learn from deoptimizations in optimized to
    1027             :         // address these problems.
    1028             :         effect = graph()->NewNode(
    1029             :             simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps),
    1030         612 :             receiver, effect, control);
    1031             :       }
    1032             :     }
    1033             : 
    1034             :     // TODO(turbofan): Perform type checks on the {values}. We are not
    1035             :     // guaranteed to learn from these checks in case they fail, as the witness
    1036             :     // (i.e. the map check from the LoadIC for a.push) might not be executed in
    1037             :     // baseline code (after we stored the value in the builtin and thereby
    1038             :     // changed the elements kind of a) before be decide to optimize this
    1039             :     // function again. We currently don't have a proper way to deal with this;
    1040             :     // the proper solution here is to learn on deopt, i.e. disable
    1041             :     // Array.prototype.push inlining for this function.
    1042        4530 :     for (auto& value : values) {
    1043        1622 :       if (IsSmiElementsKind(receiver_map->elements_kind())) {
    1044             :         value = effect =
    1045        2688 :             graph()->NewNode(simplified()->CheckSmi(), value, effect, control);
    1046         726 :       } else if (IsDoubleElementsKind(receiver_map->elements_kind())) {
    1047             :         value = effect = graph()->NewNode(simplified()->CheckNumber(), value,
    1048         648 :                                           effect, control);
    1049             :         // Make sure we do not store signaling NaNs into double arrays.
    1050         432 :         value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
    1051             :       }
    1052             :     }
    1053             : 
    1054             :     // Load the "length" property of the {receiver}.
    1055             :     Node* length = effect = graph()->NewNode(
    1056             :         simplified()->LoadField(
    1057             :             AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
    1058        4362 :         receiver, effect, control);
    1059             :     Node* value = length;
    1060             : 
    1061             :     // Check if we have any {values} to push.
    1062        1454 :     if (num_values > 0) {
    1063             :       // Compute the resulting "length" of the {receiver}.
    1064             :       Node* new_length = value = graph()->NewNode(
    1065        2808 :           simplified()->NumberAdd(), length, jsgraph()->Constant(num_values));
    1066             : 
    1067             :       // Load the elements backing store of the {receiver}.
    1068             :       Node* elements = effect = graph()->NewNode(
    1069             :           simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
    1070        4212 :           receiver, effect, control);
    1071             :       Node* elements_length = effect = graph()->NewNode(
    1072             :           simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
    1073        4212 :           elements, effect, control);
    1074             : 
    1075             :       // TODO(turbofan): Check if we need to grow the {elements} backing store.
    1076             :       // This will deopt if we cannot grow the array further, and we currently
    1077             :       // don't necessarily learn from it. See the comment on the value type
    1078             :       // check above.
    1079             :       GrowFastElementsMode mode =
    1080             :           IsDoubleElementsKind(receiver_map->elements_kind())
    1081             :               ? GrowFastElementsMode::kDoubleElements
    1082        1404 :               : GrowFastElementsMode::kSmiOrObjectElements;
    1083             :       elements = effect = graph()->NewNode(
    1084             :           simplified()->MaybeGrowFastElements(mode), receiver, elements,
    1085             :           graph()->NewNode(simplified()->NumberAdd(), length,
    1086             :                            jsgraph()->Constant(num_values - 1)),
    1087        5616 :           elements_length, effect, control);
    1088             : 
    1089             :       // Update the JSArray::length field. Since this is observable,
    1090             :       // there must be no other check after this.
    1091             :       effect = graph()->NewNode(
    1092             :           simplified()->StoreField(
    1093             :               AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
    1094        4212 :           receiver, new_length, effect, control);
    1095             : 
    1096             :       // Append the {values} to the {elements}.
    1097        3026 :       for (int i = 0; i < num_values; ++i) {
    1098        3244 :         Node* value = values[i];
    1099             :         Node* index = graph()->NewNode(simplified()->NumberAdd(), length,
    1100        3244 :                                        jsgraph()->Constant(i));
    1101             :         effect = graph()->NewNode(
    1102             :             simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(
    1103             :                 receiver_map->elements_kind())),
    1104        4866 :             elements, index, value, effect, control);
    1105             :       }
    1106             :     }
    1107             : 
    1108        1454 :     ReplaceWithValue(node, value, effect, control);
    1109             :     return Replace(value);
    1110             :   }
    1111             :   return NoChange();
    1112             : }
    1113             : 
    1114             : // ES6 section 22.1.3.22 Array.prototype.shift ( )
    1115        1643 : Reduction JSBuiltinReducer::ReduceArrayShift(Node* node) {
    1116         203 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1117         203 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1118         203 :   Node* context = NodeProperties::GetContextInput(node);
    1119         203 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    1120         203 :   Node* effect = NodeProperties::GetEffectInput(node);
    1121         203 :   Node* control = NodeProperties::GetControlInput(node);
    1122             : 
    1123             :   // TODO(turbofan): Extend this to also handle fast holey double elements
    1124             :   // once we got the hole NaN mess sorted out in TurboFan/V8.
    1125             :   Handle<Map> receiver_map;
    1126         572 :   if (GetMapWitness(node).ToHandle(&receiver_map) &&
    1127         291 :       CanInlineArrayResizeOperation(receiver_map) &&
    1128             :       receiver_map->elements_kind() != HOLEY_DOUBLE_ELEMENTS) {
    1129             :     // Install code dependencies on the {receiver} prototype maps and the
    1130             :     // global array protector cell.
    1131             :     dependencies()->AssumePropertyCell(factory()->array_protector());
    1132          80 :     dependencies()->AssumePrototypeMapsStable(receiver_map);
    1133             : 
    1134             :     // Load length of the {receiver}.
    1135             :     Node* length = effect = graph()->NewNode(
    1136             :         simplified()->LoadField(
    1137             :             AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
    1138         240 :         receiver, effect, control);
    1139             : 
    1140             :     // Return undefined if {receiver} has no elements.
    1141             :     Node* check0 = graph()->NewNode(simplified()->NumberEqual(), length,
    1142         160 :                                     jsgraph()->ZeroConstant());
    1143             :     Node* branch0 =
    1144          80 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
    1145             : 
    1146          80 :     Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    1147             :     Node* etrue0 = effect;
    1148          80 :     Node* vtrue0 = jsgraph()->UndefinedConstant();
    1149             : 
    1150          80 :     Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    1151             :     Node* efalse0 = effect;
    1152             :     Node* vfalse0;
    1153             :     {
    1154             :       // Check if we should take the fast-path.
    1155             :       Node* check1 =
    1156             :           graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
    1157         160 :                            jsgraph()->Constant(JSArray::kMaxCopyElements));
    1158             :       Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1159          80 :                                        check1, if_false0);
    1160             : 
    1161          80 :       Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    1162             :       Node* etrue1 = efalse0;
    1163             :       Node* vtrue1;
    1164             :       {
    1165             :         Node* elements = etrue1 = graph()->NewNode(
    1166             :             simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
    1167         240 :             receiver, etrue1, if_true1);
    1168             : 
    1169             :         // Load the first element here, which we return below.
    1170             :         vtrue1 = etrue1 = graph()->NewNode(
    1171             :             simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(
    1172             :                 receiver_map->elements_kind())),
    1173         320 :             elements, jsgraph()->ZeroConstant(), etrue1, if_true1);
    1174             : 
    1175             :         // Ensure that we aren't shifting a copy-on-write backing store.
    1176          80 :         if (IsSmiOrObjectElementsKind(receiver_map->elements_kind())) {
    1177             :           elements = etrue1 =
    1178             :               graph()->NewNode(simplified()->EnsureWritableFastElements(),
    1179          68 :                                receiver, elements, etrue1, if_true1);
    1180             :         }
    1181             : 
    1182             :         // Shift the remaining {elements} by one towards the start.
    1183          80 :         Node* loop = graph()->NewNode(common()->Loop(2), if_true1, if_true1);
    1184             :         Node* eloop =
    1185          80 :             graph()->NewNode(common()->EffectPhi(2), etrue1, etrue1, loop);
    1186             :         Node* index = graph()->NewNode(
    1187             :             common()->Phi(MachineRepresentation::kTagged, 2),
    1188             :             jsgraph()->OneConstant(),
    1189         240 :             jsgraph()->Constant(JSArray::kMaxCopyElements - 1), loop);
    1190             : 
    1191             :         {
    1192             :           Node* check2 =
    1193          80 :               graph()->NewNode(simplified()->NumberLessThan(), index, length);
    1194          80 :           Node* branch2 = graph()->NewNode(common()->Branch(), check2, loop);
    1195             : 
    1196          80 :           if_true1 = graph()->NewNode(common()->IfFalse(), branch2);
    1197             :           etrue1 = eloop;
    1198             : 
    1199          80 :           Node* control = graph()->NewNode(common()->IfTrue(), branch2);
    1200             :           Node* effect = etrue1;
    1201             : 
    1202             :           ElementAccess const access = AccessBuilder::ForFixedArrayElement(
    1203          80 :               receiver_map->elements_kind());
    1204             :           Node* value = effect =
    1205             :               graph()->NewNode(simplified()->LoadElement(access), elements,
    1206          80 :                                index, effect, control);
    1207             :           effect = graph()->NewNode(
    1208             :               simplified()->StoreElement(access), elements,
    1209             :               graph()->NewNode(simplified()->NumberSubtract(), index,
    1210             :                                jsgraph()->OneConstant()),
    1211         240 :               value, effect, control);
    1212             : 
    1213          80 :           loop->ReplaceInput(1, control);
    1214          80 :           eloop->ReplaceInput(1, effect);
    1215             :           index->ReplaceInput(1,
    1216             :                               graph()->NewNode(simplified()->NumberAdd(), index,
    1217         240 :                                                jsgraph()->OneConstant()));
    1218             :         }
    1219             : 
    1220             :         // Compute the new {length}.
    1221             :         length = graph()->NewNode(simplified()->NumberSubtract(), length,
    1222         160 :                                   jsgraph()->OneConstant());
    1223             : 
    1224             :         // Store the new {length} to the {receiver}.
    1225             :         etrue1 = graph()->NewNode(
    1226             :             simplified()->StoreField(
    1227             :                 AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
    1228         240 :             receiver, length, etrue1, if_true1);
    1229             : 
    1230             :         // Store a hole to the element we just removed from the {receiver}.
    1231             :         etrue1 = graph()->NewNode(
    1232             :             simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(
    1233             :                 GetHoleyElementsKind(receiver_map->elements_kind()))),
    1234         320 :             elements, length, jsgraph()->TheHoleConstant(), etrue1, if_true1);
    1235             :       }
    1236             : 
    1237          80 :       Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    1238             :       Node* efalse1 = efalse0;
    1239             :       Node* vfalse1;
    1240             :       {
    1241             :         // Call the generic C++ implementation.
    1242             :         const int builtin_index = Builtins::kArrayShift;
    1243             :         CallDescriptor const* const desc = Linkage::GetCEntryStubCallDescriptor(
    1244             :             graph()->zone(), 1, BuiltinArguments::kNumExtraArgsWithReceiver,
    1245             :             Builtins::name(builtin_index), node->op()->properties(),
    1246         160 :             CallDescriptor::kNeedsFrameState);
    1247             :         Node* stub_code = jsgraph()->CEntryStubConstant(1, kDontSaveFPRegs,
    1248          80 :                                                         kArgvOnStack, true);
    1249          80 :         Address builtin_entry = Builtins::CppEntryOf(builtin_index);
    1250             :         Node* entry = jsgraph()->ExternalConstant(
    1251         160 :             ExternalReference(builtin_entry, isolate()));
    1252             :         Node* argc =
    1253          80 :             jsgraph()->Constant(BuiltinArguments::kNumExtraArgsWithReceiver);
    1254             :         if_false1 = efalse1 = vfalse1 =
    1255             :             graph()->NewNode(common()->Call(desc), stub_code, receiver,
    1256             :                              jsgraph()->PaddingConstant(), argc, target,
    1257             :                              jsgraph()->UndefinedConstant(), entry, argc,
    1258         160 :                              context, frame_state, efalse1, if_false1);
    1259             :       }
    1260             : 
    1261          80 :       if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
    1262             :       efalse0 =
    1263          80 :           graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
    1264             :       vfalse0 =
    1265             :           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    1266          80 :                            vtrue1, vfalse1, if_false0);
    1267             :     }
    1268             : 
    1269          80 :     control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
    1270          80 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
    1271             :     Node* value =
    1272             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    1273          80 :                          vtrue0, vfalse0, control);
    1274             : 
    1275             :     // Convert the hole to undefined. Do this last, so that we can optimize
    1276             :     // conversion operator via some smart strength reduction in many cases.
    1277          80 :     if (IsHoleyElementsKind(receiver_map->elements_kind())) {
    1278             :       value =
    1279          14 :           graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
    1280             :     }
    1281             : 
    1282          80 :     ReplaceWithValue(node, value, effect, control);
    1283             :     return Replace(value);
    1284             :   }
    1285             :   return NoChange();
    1286             : }
    1287             : 
    1288             : namespace {
    1289             : 
    1290         514 : bool HasInstanceTypeWitness(Node* receiver, Node* effect,
    1291             :                             InstanceType instance_type) {
    1292             :   ZoneHandleSet<Map> receiver_maps;
    1293             :   NodeProperties::InferReceiverMapsResult result =
    1294         514 :       NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
    1295         514 :   switch (result) {
    1296             :     case NodeProperties::kUnreliableReceiverMaps:
    1297             :     case NodeProperties::kReliableReceiverMaps:
    1298             :       DCHECK_NE(0, receiver_maps.size());
    1299        1956 :       for (size_t i = 0; i < receiver_maps.size(); ++i) {
    1300         721 :         if (receiver_maps[i]->instance_type() != instance_type) return false;
    1301             :       }
    1302             :       return true;
    1303             : 
    1304             :     case NodeProperties::kNoReceiverMaps:
    1305             :       return false;
    1306             :   }
    1307           0 :   UNREACHABLE();
    1308             : }
    1309             : 
    1310             : }  // namespace
    1311             : 
    1312         142 : Reduction JSBuiltinReducer::ReduceCollectionIterator(
    1313             :     Node* node, InstanceType collection_instance_type,
    1314         568 :     int collection_iterator_map_index) {
    1315             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1316         142 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1317         142 :   Node* effect = NodeProperties::GetEffectInput(node);
    1318         142 :   Node* control = NodeProperties::GetControlInput(node);
    1319         142 :   if (HasInstanceTypeWitness(receiver, effect, collection_instance_type)) {
    1320             :     // Figure out the proper collection iterator map.
    1321             :     Handle<Map> collection_iterator_map(
    1322             :         Map::cast(native_context()->get(collection_iterator_map_index)),
    1323             :         isolate());
    1324             : 
    1325             :     // Load the OrderedHashTable from the {receiver}.
    1326             :     Node* table = effect = graph()->NewNode(
    1327             :         simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
    1328         426 :         receiver, effect, control);
    1329             : 
    1330             :     // Create the JSCollectionIterator result.
    1331             :     AllocationBuilder a(jsgraph(), effect, control);
    1332         142 :     a.Allocate(JSCollectionIterator::kSize, NOT_TENURED, Type::OtherObject());
    1333         142 :     a.Store(AccessBuilder::ForMap(), collection_iterator_map);
    1334             :     a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
    1335         142 :             jsgraph()->EmptyFixedArrayConstant());
    1336             :     a.Store(AccessBuilder::ForJSObjectElements(),
    1337         142 :             jsgraph()->EmptyFixedArrayConstant());
    1338         142 :     a.Store(AccessBuilder::ForJSCollectionIteratorTable(), table);
    1339             :     a.Store(AccessBuilder::ForJSCollectionIteratorIndex(),
    1340         142 :             jsgraph()->ZeroConstant());
    1341         142 :     Node* value = effect = a.Finish();
    1342         142 :     ReplaceWithValue(node, value, effect, control);
    1343             :     return Replace(value);
    1344             :   }
    1345             :   return NoChange();
    1346             : }
    1347             : 
    1348           0 : Reduction JSBuiltinReducer::ReduceCollectionSize(
    1349             :     Node* node, InstanceType collection_instance_type) {
    1350             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1351           0 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1352           0 :   Node* effect = NodeProperties::GetEffectInput(node);
    1353           0 :   Node* control = NodeProperties::GetControlInput(node);
    1354           0 :   if (HasInstanceTypeWitness(receiver, effect, collection_instance_type)) {
    1355             :     Node* table = effect = graph()->NewNode(
    1356             :         simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
    1357           0 :         receiver, effect, control);
    1358             :     Node* value = effect = graph()->NewNode(
    1359             :         simplified()->LoadField(
    1360             :             AccessBuilder::ForOrderedHashTableBaseNumberOfElements()),
    1361           0 :         table, effect, control);
    1362           0 :     ReplaceWithValue(node, value, effect, control);
    1363             :     return Replace(value);
    1364             :   }
    1365             :   return NoChange();
    1366             : }
    1367             : 
    1368         266 : Reduction JSBuiltinReducer::ReduceCollectionIteratorNext(
    1369             :     Node* node, int entry_size,
    1370             :     InstanceType collection_iterator_instance_type_first,
    1371        2464 :     InstanceType collection_iterator_instance_type_last) {
    1372             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1373         266 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1374         266 :   Node* context = NodeProperties::GetContextInput(node);
    1375         266 :   Node* effect = NodeProperties::GetEffectInput(node);
    1376         266 :   Node* control = NodeProperties::GetControlInput(node);
    1377             : 
    1378             :   // A word of warning to begin with: This whole method might look a bit
    1379             :   // strange at times, but that's mostly because it was carefully handcrafted
    1380             :   // to allow for full escape analysis and scalar replacement of both the
    1381             :   // collection iterator object and the iterator results, including the
    1382             :   // key-value arrays in case of Set/Map entry iteration.
    1383             :   //
    1384             :   // TODO(turbofan): Currently the escape analysis (and the store-load
    1385             :   // forwarding) is unable to eliminate the allocations for the key-value
    1386             :   // arrays in case of Set/Map entry iteration, and we should investigate
    1387             :   // how to update the escape analysis / arrange the graph in a way that
    1388             :   // this becomes possible.
    1389             : 
    1390             :   // Infer the {receiver} instance type.
    1391             :   InstanceType receiver_instance_type;
    1392             :   ZoneHandleSet<Map> receiver_maps;
    1393             :   NodeProperties::InferReceiverMapsResult result =
    1394         266 :       NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
    1395         266 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    1396             :   DCHECK_NE(0, receiver_maps.size());
    1397             :   receiver_instance_type = receiver_maps[0]->instance_type();
    1398         532 :   for (size_t i = 1; i < receiver_maps.size(); ++i) {
    1399           0 :     if (receiver_maps[i]->instance_type() != receiver_instance_type) {
    1400             :       return NoChange();
    1401             :     }
    1402             :   }
    1403         532 :   if (receiver_instance_type < collection_iterator_instance_type_first ||
    1404         266 :       receiver_instance_type > collection_iterator_instance_type_last) {
    1405             :     return NoChange();
    1406             :   }
    1407             : 
    1408             :   // Transition the JSCollectionIterator {receiver} if necessary
    1409             :   // (i.e. there were certain mutations while we're iterating).
    1410             :   {
    1411             :     Node* done_loop;
    1412             :     Node* done_eloop;
    1413             :     Node* loop = control =
    1414         266 :         graph()->NewNode(common()->Loop(2), control, control);
    1415             :     Node* eloop = effect =
    1416         266 :         graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    1417             : 
    1418             :     // Check if reached the final table of the {receiver}.
    1419             :     Node* table = effect = graph()->NewNode(
    1420             :         simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
    1421         798 :         receiver, effect, control);
    1422             :     Node* next_table = effect =
    1423             :         graph()->NewNode(simplified()->LoadField(
    1424             :                              AccessBuilder::ForOrderedHashTableBaseNextTable()),
    1425         798 :                          table, effect, control);
    1426         266 :     Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), next_table);
    1427             :     control =
    1428         266 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    1429             : 
    1430             :     // Abort the {loop} when we reach the final table.
    1431         266 :     done_loop = graph()->NewNode(common()->IfTrue(), control);
    1432             :     done_eloop = effect;
    1433             : 
    1434             :     // Migrate to the {next_table} otherwise.
    1435         266 :     control = graph()->NewNode(common()->IfFalse(), control);
    1436             : 
    1437             :     // Self-heal the {receiver}s index.
    1438             :     Node* index = effect = graph()->NewNode(
    1439             :         simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
    1440         798 :         receiver, effect, control);
    1441             :     Callable const callable =
    1442         266 :         Builtins::CallableFor(isolate(), Builtins::kOrderedHashTableHealIndex);
    1443             :     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    1444             :         isolate(), graph()->zone(), callable.descriptor(), 0,
    1445         798 :         CallDescriptor::kNoFlags, Operator::kEliminatable);
    1446             :     index = effect = graph()->NewNode(
    1447             :         common()->Call(desc), jsgraph()->HeapConstant(callable.code()), table,
    1448         798 :         index, jsgraph()->NoContextConstant(), effect);
    1449             : 
    1450             :     // Update the {index} and {table} on the {receiver}.
    1451             :     effect = graph()->NewNode(
    1452             :         simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorIndex()),
    1453         798 :         receiver, index, effect, control);
    1454             :     effect = graph()->NewNode(
    1455             :         simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorTable()),
    1456         798 :         receiver, next_table, effect, control);
    1457             : 
    1458             :     // Tie the knot.
    1459         266 :     loop->ReplaceInput(1, control);
    1460         266 :     eloop->ReplaceInput(1, effect);
    1461             : 
    1462             :     control = done_loop;
    1463             :     effect = done_eloop;
    1464             :   }
    1465             : 
    1466             :   // Get current index and table from the JSCollectionIterator {receiver}.
    1467             :   Node* index = effect = graph()->NewNode(
    1468             :       simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
    1469         798 :       receiver, effect, control);
    1470             :   Node* table = effect = graph()->NewNode(
    1471             :       simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
    1472         798 :       receiver, effect, control);
    1473             : 
    1474             :   // Create the {JSIteratorResult} first to ensure that we always have
    1475             :   // a dominating Allocate node for the allocation folding phase.
    1476             :   Node* iterator_result = effect = graph()->NewNode(
    1477             :       javascript()->CreateIterResultObject(), jsgraph()->UndefinedConstant(),
    1478         798 :       jsgraph()->TrueConstant(), context, effect);
    1479             : 
    1480             :   // Look for the next non-holey key, starting from {index} in the {table}.
    1481             :   Node* controls[2];
    1482             :   Node* effects[3];
    1483             :   {
    1484             :     // Compute the currently used capacity.
    1485             :     Node* number_of_buckets = effect = graph()->NewNode(
    1486             :         simplified()->LoadField(
    1487             :             AccessBuilder::ForOrderedHashTableBaseNumberOfBuckets()),
    1488         798 :         table, effect, control);
    1489             :     Node* number_of_elements = effect = graph()->NewNode(
    1490             :         simplified()->LoadField(
    1491             :             AccessBuilder::ForOrderedHashTableBaseNumberOfElements()),
    1492         798 :         table, effect, control);
    1493             :     Node* number_of_deleted_elements = effect = graph()->NewNode(
    1494             :         simplified()->LoadField(
    1495             :             AccessBuilder::ForOrderedHashTableBaseNumberOfDeletedElements()),
    1496         798 :         table, effect, control);
    1497             :     Node* used_capacity =
    1498             :         graph()->NewNode(simplified()->NumberAdd(), number_of_elements,
    1499         266 :                          number_of_deleted_elements);
    1500             : 
    1501             :     // Skip holes and update the {index}.
    1502         266 :     Node* loop = graph()->NewNode(common()->Loop(2), control, control);
    1503             :     Node* eloop =
    1504         266 :         graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    1505             :     Node* iloop = graph()->NewNode(
    1506         266 :         common()->Phi(MachineRepresentation::kTagged, 2), index, index, loop);
    1507         266 :     NodeProperties::SetType(iloop, type_cache_.kFixedArrayLengthType);
    1508             :     {
    1509             :       Node* check0 = graph()->NewNode(simplified()->NumberLessThan(), iloop,
    1510         266 :                                       used_capacity);
    1511             :       Node* branch0 =
    1512         266 :           graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, loop);
    1513             : 
    1514         266 :       Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    1515             :       Node* efalse0 = eloop;
    1516             :       {
    1517             :         // Mark the {receiver} as exhausted.
    1518             :         efalse0 = graph()->NewNode(
    1519             :             simplified()->StoreField(
    1520             :                 AccessBuilder::ForJSCollectionIteratorTable()),
    1521             :             receiver,
    1522             :             jsgraph()->HeapConstant(factory()->empty_ordered_hash_table()),
    1523         798 :             efalse0, if_false0);
    1524             : 
    1525         266 :         controls[0] = if_false0;
    1526         266 :         effects[0] = efalse0;
    1527             :       }
    1528             : 
    1529         266 :       Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    1530             :       Node* etrue0 = eloop;
    1531             :       {
    1532             :         // Load the key of the entry.
    1533             :         Node* entry_start_position = graph()->NewNode(
    1534             :             simplified()->NumberAdd(),
    1535             :             graph()->NewNode(
    1536             :                 simplified()->NumberAdd(),
    1537             :                 graph()->NewNode(simplified()->NumberMultiply(), iloop,
    1538             :                                  jsgraph()->Constant(entry_size)),
    1539             :                 number_of_buckets),
    1540        1330 :             jsgraph()->Constant(OrderedHashTableBase::kHashTableStartIndex));
    1541             :         Node* entry_key = etrue0 = graph()->NewNode(
    1542             :             simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
    1543         798 :             table, entry_start_position, etrue0, if_true0);
    1544             : 
    1545             :         // Advance the index.
    1546             :         Node* index = graph()->NewNode(simplified()->NumberAdd(), iloop,
    1547         532 :                                        jsgraph()->OneConstant());
    1548             : 
    1549             :         Node* check1 =
    1550             :             graph()->NewNode(simplified()->ReferenceEqual(), entry_key,
    1551         532 :                              jsgraph()->TheHoleConstant());
    1552             :         Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
    1553         266 :                                          check1, if_true0);
    1554             : 
    1555             :         {
    1556             :           // Abort loop with resulting value.
    1557         266 :           Node* control = graph()->NewNode(common()->IfFalse(), branch1);
    1558             :           Node* effect = etrue0;
    1559             :           Node* value = graph()->NewNode(
    1560         266 :               common()->TypeGuard(Type::NonInternal()), entry_key, control);
    1561         266 :           Node* done = jsgraph()->FalseConstant();
    1562             : 
    1563             :           // Advance the index on the {receiver}.
    1564             :           effect = graph()->NewNode(
    1565             :               simplified()->StoreField(
    1566             :                   AccessBuilder::ForJSCollectionIteratorIndex()),
    1567         798 :               receiver, index, effect, control);
    1568             : 
    1569             :           // The actual {value} depends on the {receiver} iteration type.
    1570         266 :           switch (receiver_instance_type) {
    1571             :             case JS_MAP_KEY_ITERATOR_TYPE:
    1572             :             case JS_SET_VALUE_ITERATOR_TYPE:
    1573             :               break;
    1574             : 
    1575             :             case JS_SET_KEY_VALUE_ITERATOR_TYPE:
    1576             :               value = effect =
    1577             :                   graph()->NewNode(javascript()->CreateKeyValueArray(), value,
    1578          35 :                                    value, context, effect);
    1579          35 :               break;
    1580             : 
    1581             :             case JS_MAP_VALUE_ITERATOR_TYPE:
    1582             :               value = effect = graph()->NewNode(
    1583             :                   simplified()->LoadElement(
    1584             :                       AccessBuilder::ForFixedArrayElement()),
    1585             :                   table,
    1586             :                   graph()->NewNode(
    1587             :                       simplified()->NumberAdd(), entry_start_position,
    1588             :                       jsgraph()->Constant(OrderedHashMap::kValueOffset)),
    1589         175 :                   effect, control);
    1590          35 :               break;
    1591             : 
    1592             :             case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
    1593             :               value = effect = graph()->NewNode(
    1594             :                   simplified()->LoadElement(
    1595             :                       AccessBuilder::ForFixedArrayElement()),
    1596             :                   table,
    1597             :                   graph()->NewNode(
    1598             :                       simplified()->NumberAdd(), entry_start_position,
    1599             :                       jsgraph()->Constant(OrderedHashMap::kValueOffset)),
    1600         175 :                   effect, control);
    1601             :               value = effect =
    1602             :                   graph()->NewNode(javascript()->CreateKeyValueArray(),
    1603          35 :                                    entry_key, value, context, effect);
    1604          35 :               break;
    1605             : 
    1606             :             default:
    1607           0 :               UNREACHABLE();
    1608             :               break;
    1609             :           }
    1610             : 
    1611             :           // Store final {value} and {done} into the {iterator_result}.
    1612             :           effect =
    1613             :               graph()->NewNode(simplified()->StoreField(
    1614             :                                    AccessBuilder::ForJSIteratorResultValue()),
    1615         798 :                                iterator_result, value, effect, control);
    1616             :           effect =
    1617             :               graph()->NewNode(simplified()->StoreField(
    1618             :                                    AccessBuilder::ForJSIteratorResultDone()),
    1619         798 :                                iterator_result, done, effect, control);
    1620             : 
    1621         266 :           controls[1] = control;
    1622         266 :           effects[1] = effect;
    1623             :         }
    1624             : 
    1625             :         // Continue with next loop index.
    1626         532 :         loop->ReplaceInput(1, graph()->NewNode(common()->IfTrue(), branch1));
    1627         266 :         eloop->ReplaceInput(1, etrue0);
    1628         266 :         iloop->ReplaceInput(1, index);
    1629             :       }
    1630             :     }
    1631             : 
    1632         532 :     control = effects[2] = graph()->NewNode(common()->Merge(2), 2, controls);
    1633         532 :     effect = graph()->NewNode(common()->EffectPhi(2), 3, effects);
    1634             :   }
    1635             : 
    1636             :   // Yield the final {iterator_result}.
    1637         266 :   ReplaceWithValue(node, iterator_result, effect, control);
    1638             :   return Replace(iterator_result);
    1639             : }
    1640             : 
    1641             : // ES6 section 20.3.3.1 Date.now ( )
    1642           8 : Reduction JSBuiltinReducer::ReduceDateNow(Node* node) {
    1643           8 :   NodeProperties::RemoveValueInputs(node);
    1644             :   NodeProperties::ChangeOp(
    1645           8 :       node, javascript()->CallRuntime(Runtime::kDateCurrentTime));
    1646           8 :   return Changed(node);
    1647             : }
    1648             : 
    1649             : // ES6 section 20.3.4.10 Date.prototype.getTime ( )
    1650           0 : Reduction JSBuiltinReducer::ReduceDateGetTime(Node* node) {
    1651           0 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1652           0 :   Node* effect = NodeProperties::GetEffectInput(node);
    1653           0 :   Node* control = NodeProperties::GetControlInput(node);
    1654           0 :   if (HasInstanceTypeWitness(receiver, effect, JS_DATE_TYPE)) {
    1655             :     Node* value = effect = graph()->NewNode(
    1656             :         simplified()->LoadField(AccessBuilder::ForJSDateValue()), receiver,
    1657           0 :         effect, control);
    1658           0 :     ReplaceWithValue(node, value, effect, control);
    1659             :     return Replace(value);
    1660             :   }
    1661             :   return NoChange();
    1662             : }
    1663             : 
    1664             : // ES6 section 18.2.2 isFinite ( number )
    1665          54 : Reduction JSBuiltinReducer::ReduceGlobalIsFinite(Node* node) {
    1666             :   JSCallReduction r(node);
    1667          54 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1668             :     // isFinite(a:plain-primitive) -> NumberEqual(a', a')
    1669             :     // where a' = NumberSubtract(ToNumber(a), ToNumber(a))
    1670          37 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1671          37 :     Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, input);
    1672          37 :     Node* value = graph()->NewNode(simplified()->NumberEqual(), diff, diff);
    1673             :     return Replace(value);
    1674             :   }
    1675             :   return NoChange();
    1676             : }
    1677             : 
    1678             : // ES6 section 18.2.3 isNaN ( number )
    1679       11096 : Reduction JSBuiltinReducer::ReduceGlobalIsNaN(Node* node) {
    1680             :   JSCallReduction r(node);
    1681       11096 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1682             :     // isNaN(a:plain-primitive) -> BooleanNot(NumberEqual(a', a'))
    1683             :     // where a' = ToNumber(a)
    1684        2954 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1685        2954 :     Node* check = graph()->NewNode(simplified()->NumberEqual(), input, input);
    1686        2954 :     Node* value = graph()->NewNode(simplified()->BooleanNot(), check);
    1687             :     return Replace(value);
    1688             :   }
    1689             :   return NoChange();
    1690             : }
    1691             : 
    1692          24 : Reduction JSBuiltinReducer::ReduceMapGet(Node* node) {
    1693             :   // We only optimize if we have target, receiver and key parameters.
    1694           8 :   if (node->op()->ValueInputCount() != 3) return NoChange();
    1695           8 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1696           8 :   Node* effect = NodeProperties::GetEffectInput(node);
    1697           8 :   Node* control = NodeProperties::GetControlInput(node);
    1698           8 :   Node* key = NodeProperties::GetValueInput(node, 2);
    1699             : 
    1700           8 :   if (!HasInstanceTypeWitness(receiver, effect, JS_MAP_TYPE)) return NoChange();
    1701             : 
    1702             :   Node* table = effect = graph()->NewNode(
    1703             :       simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
    1704          24 :       effect, control);
    1705             : 
    1706             :   Node* entry = effect = graph()->NewNode(
    1707           8 :       simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
    1708             : 
    1709             :   Node* check = graph()->NewNode(simplified()->NumberEqual(), entry,
    1710          16 :                                  jsgraph()->MinusOneConstant());
    1711             : 
    1712           8 :   Node* branch = graph()->NewNode(common()->Branch(), check, control);
    1713             : 
    1714             :   // Key not found.
    1715           8 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1716             :   Node* etrue = effect;
    1717           8 :   Node* vtrue = jsgraph()->UndefinedConstant();
    1718             : 
    1719             :   // Key found.
    1720           8 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1721             :   Node* efalse = effect;
    1722             :   Node* vfalse = efalse = graph()->NewNode(
    1723             :       simplified()->LoadElement(AccessBuilder::ForOrderedHashMapEntryValue()),
    1724          24 :       table, entry, efalse, if_false);
    1725             : 
    1726           8 :   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1727             :   Node* value = graph()->NewNode(
    1728           8 :       common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control);
    1729           8 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    1730             : 
    1731           8 :   ReplaceWithValue(node, value, effect, control);
    1732             :   return Replace(value);
    1733             : }
    1734             : 
    1735           0 : Reduction JSBuiltinReducer::ReduceMapHas(Node* node) {
    1736             :   // We only optimize if we have target, receiver and key parameters.
    1737           0 :   if (node->op()->ValueInputCount() != 3) return NoChange();
    1738           0 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1739           0 :   Node* effect = NodeProperties::GetEffectInput(node);
    1740           0 :   Node* control = NodeProperties::GetControlInput(node);
    1741           0 :   Node* key = NodeProperties::GetValueInput(node, 2);
    1742             : 
    1743           0 :   if (!HasInstanceTypeWitness(receiver, effect, JS_MAP_TYPE)) return NoChange();
    1744             : 
    1745             :   Node* table = effect = graph()->NewNode(
    1746             :       simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
    1747           0 :       effect, control);
    1748             : 
    1749             :   Node* index = effect = graph()->NewNode(
    1750           0 :       simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
    1751             : 
    1752             :   Node* value = graph()->NewNode(simplified()->NumberEqual(), index,
    1753           0 :                                  jsgraph()->MinusOneConstant());
    1754           0 :   value = graph()->NewNode(simplified()->BooleanNot(), value);
    1755             : 
    1756           0 :   ReplaceWithValue(node, value, effect, control);
    1757             :   return Replace(value);
    1758             : }
    1759             : 
    1760             : // ES6 section 20.2.2.1 Math.abs ( x )
    1761         466 : Reduction JSBuiltinReducer::ReduceMathAbs(Node* node) {
    1762             :   JSCallReduction r(node);
    1763         466 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1764             :     // Math.abs(a:plain-primitive) -> NumberAbs(ToNumber(a))
    1765         390 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1766         390 :     Node* value = graph()->NewNode(simplified()->NumberAbs(), input);
    1767             :     return Replace(value);
    1768             :   }
    1769             :   return NoChange();
    1770             : }
    1771             : 
    1772             : // ES6 section 20.2.2.2 Math.acos ( x )
    1773          14 : Reduction JSBuiltinReducer::ReduceMathAcos(Node* node) {
    1774             :   JSCallReduction r(node);
    1775          14 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1776             :     // Math.acos(a:plain-primitive) -> NumberAcos(ToNumber(a))
    1777          14 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1778          14 :     Node* value = graph()->NewNode(simplified()->NumberAcos(), input);
    1779             :     return Replace(value);
    1780             :   }
    1781             :   return NoChange();
    1782             : }
    1783             : 
    1784             : // ES6 section 20.2.2.3 Math.acosh ( x )
    1785          13 : Reduction JSBuiltinReducer::ReduceMathAcosh(Node* node) {
    1786             :   JSCallReduction r(node);
    1787          13 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1788             :     // Math.acosh(a:plain-primitive) -> NumberAcosh(ToNumber(a))
    1789          13 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1790          13 :     Node* value = graph()->NewNode(simplified()->NumberAcosh(), input);
    1791             :     return Replace(value);
    1792             :   }
    1793             :   return NoChange();
    1794             : }
    1795             : 
    1796             : // ES6 section 20.2.2.4 Math.asin ( x )
    1797          14 : Reduction JSBuiltinReducer::ReduceMathAsin(Node* node) {
    1798             :   JSCallReduction r(node);
    1799          14 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1800             :     // Math.asin(a:plain-primitive) -> NumberAsin(ToNumber(a))
    1801          14 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1802          14 :     Node* value = graph()->NewNode(simplified()->NumberAsin(), input);
    1803             :     return Replace(value);
    1804             :   }
    1805             :   return NoChange();
    1806             : }
    1807             : 
    1808             : // ES6 section 20.2.2.5 Math.asinh ( x )
    1809          13 : Reduction JSBuiltinReducer::ReduceMathAsinh(Node* node) {
    1810             :   JSCallReduction r(node);
    1811          13 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1812             :     // Math.asinh(a:plain-primitive) -> NumberAsinh(ToNumber(a))
    1813          13 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1814          13 :     Node* value = graph()->NewNode(simplified()->NumberAsinh(), input);
    1815             :     return Replace(value);
    1816             :   }
    1817             :   return NoChange();
    1818             : }
    1819             : 
    1820             : // ES6 section 20.2.2.6 Math.atan ( x )
    1821          14 : Reduction JSBuiltinReducer::ReduceMathAtan(Node* node) {
    1822             :   JSCallReduction r(node);
    1823          14 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1824             :     // Math.atan(a:plain-primitive) -> NumberAtan(ToNumber(a))
    1825          14 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1826          14 :     Node* value = graph()->NewNode(simplified()->NumberAtan(), input);
    1827             :     return Replace(value);
    1828             :   }
    1829             :   return NoChange();
    1830             : }
    1831             : 
    1832             : // ES6 section 20.2.2.7 Math.atanh ( x )
    1833          13 : Reduction JSBuiltinReducer::ReduceMathAtanh(Node* node) {
    1834             :   JSCallReduction r(node);
    1835          13 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1836             :     // Math.atanh(a:plain-primitive) -> NumberAtanh(ToNumber(a))
    1837          13 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1838          13 :     Node* value = graph()->NewNode(simplified()->NumberAtanh(), input);
    1839             :     return Replace(value);
    1840             :   }
    1841             :   return NoChange();
    1842             : }
    1843             : 
    1844             : // ES6 section 20.2.2.8 Math.atan2 ( y, x )
    1845         162 : Reduction JSBuiltinReducer::ReduceMathAtan2(Node* node) {
    1846             :   JSCallReduction r(node);
    1847         162 :   if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
    1848             :     // Math.atan2(a:plain-primitive,
    1849             :     //            b:plain-primitive) -> NumberAtan2(ToNumber(a),
    1850             :     //                                              ToNumber(b))
    1851         162 :     Node* left = ToNumber(r.left());
    1852         162 :     Node* right = ToNumber(r.right());
    1853         162 :     Node* value = graph()->NewNode(simplified()->NumberAtan2(), left, right);
    1854             :     return Replace(value);
    1855             :   }
    1856             :   return NoChange();
    1857             : }
    1858             : 
    1859             : // ES6 section 20.2.2.10 Math.ceil ( x )
    1860        7252 : Reduction JSBuiltinReducer::ReduceMathCeil(Node* node) {
    1861             :   JSCallReduction r(node);
    1862        7252 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1863             :     // Math.ceil(a:plain-primitive) -> NumberCeil(ToNumber(a))
    1864        5424 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1865        5424 :     Node* value = graph()->NewNode(simplified()->NumberCeil(), input);
    1866             :     return Replace(value);
    1867             :   }
    1868             :   return NoChange();
    1869             : }
    1870             : 
    1871             : // ES6 section 20.2.2.11 Math.clz32 ( x )
    1872          46 : Reduction JSBuiltinReducer::ReduceMathClz32(Node* node) {
    1873             :   JSCallReduction r(node);
    1874          46 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1875             :     // Math.clz32(a:plain-primitive) -> NumberClz32(ToUint32(a))
    1876          17 :     Node* input = ToUint32(r.GetJSCallInput(0));
    1877          17 :     Node* value = graph()->NewNode(simplified()->NumberClz32(), input);
    1878             :     return Replace(value);
    1879             :   }
    1880             :   return NoChange();
    1881             : }
    1882             : 
    1883             : // ES6 section 20.2.2.12 Math.cos ( x )
    1884          34 : Reduction JSBuiltinReducer::ReduceMathCos(Node* node) {
    1885             :   JSCallReduction r(node);
    1886          34 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1887             :     // Math.cos(a:plain-primitive) -> NumberCos(ToNumber(a))
    1888          14 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1889          14 :     Node* value = graph()->NewNode(simplified()->NumberCos(), input);
    1890             :     return Replace(value);
    1891             :   }
    1892             :   return NoChange();
    1893             : }
    1894             : 
    1895             : // ES6 section 20.2.2.13 Math.cosh ( x )
    1896          21 : Reduction JSBuiltinReducer::ReduceMathCosh(Node* node) {
    1897             :   JSCallReduction r(node);
    1898          21 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1899             :     // Math.cosh(a:plain-primitive) -> NumberCosh(ToNumber(a))
    1900          21 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1901          21 :     Node* value = graph()->NewNode(simplified()->NumberCosh(), input);
    1902             :     return Replace(value);
    1903             :   }
    1904             :   return NoChange();
    1905             : }
    1906             : 
    1907             : // ES6 section 20.2.2.14 Math.exp ( x )
    1908          64 : Reduction JSBuiltinReducer::ReduceMathExp(Node* node) {
    1909             :   JSCallReduction r(node);
    1910          64 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1911             :     // Math.exp(a:plain-primitive) -> NumberExp(ToNumber(a))
    1912          49 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1913          49 :     Node* value = graph()->NewNode(simplified()->NumberExp(), input);
    1914             :     return Replace(value);
    1915             :   }
    1916             :   return NoChange();
    1917             : }
    1918             : 
    1919             : // ES6 section 20.2.2.15 Math.expm1 ( x )
    1920           0 : Reduction JSBuiltinReducer::ReduceMathExpm1(Node* node) {
    1921             :   JSCallReduction r(node);
    1922           0 :   if (r.InputsMatchOne(Type::Number())) {
    1923             :     // Math.expm1(a:number) -> NumberExpm1(a)
    1924           0 :     Node* value = graph()->NewNode(simplified()->NumberExpm1(), r.left());
    1925             :     return Replace(value);
    1926             :   }
    1927             :   return NoChange();
    1928             : }
    1929             : 
    1930             : // ES6 section 20.2.2.16 Math.floor ( x )
    1931       27376 : Reduction JSBuiltinReducer::ReduceMathFloor(Node* node) {
    1932             :   JSCallReduction r(node);
    1933       27376 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1934             :     // Math.floor(a:plain-primitive) -> NumberFloor(ToNumber(a))
    1935        9306 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1936        9306 :     Node* value = graph()->NewNode(simplified()->NumberFloor(), input);
    1937             :     return Replace(value);
    1938             :   }
    1939             :   return NoChange();
    1940             : }
    1941             : 
    1942             : // ES6 section 20.2.2.17 Math.fround ( x )
    1943        1295 : Reduction JSBuiltinReducer::ReduceMathFround(Node* node) {
    1944             :   JSCallReduction r(node);
    1945        1295 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1946             :     // Math.fround(a:plain-primitive) -> NumberFround(ToNumber(a))
    1947         802 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1948         802 :     Node* value = graph()->NewNode(simplified()->NumberFround(), input);
    1949             :     return Replace(value);
    1950             :   }
    1951             :   return NoChange();
    1952             : }
    1953             : 
    1954             : // ES6 section 20.2.2.19 Math.imul ( x, y )
    1955         851 : Reduction JSBuiltinReducer::ReduceMathImul(Node* node) {
    1956             :   JSCallReduction r(node);
    1957         851 :   if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
    1958             :     // Math.imul(a:plain-primitive,
    1959             :     //           b:plain-primitive) -> NumberImul(ToUint32(a),
    1960             :     //                                            ToUint32(b))
    1961          33 :     Node* left = ToUint32(r.left());
    1962          33 :     Node* right = ToUint32(r.right());
    1963          33 :     Node* value = graph()->NewNode(simplified()->NumberImul(), left, right);
    1964             :     return Replace(value);
    1965             :   }
    1966             :   return NoChange();
    1967             : }
    1968             : 
    1969             : // ES6 section 20.2.2.20 Math.log ( x )
    1970         205 : Reduction JSBuiltinReducer::ReduceMathLog(Node* node) {
    1971             :   JSCallReduction r(node);
    1972         205 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1973             :     // Math.log(a:plain-primitive) -> NumberLog(ToNumber(a))
    1974         198 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1975         198 :     Node* value = graph()->NewNode(simplified()->NumberLog(), input);
    1976             :     return Replace(value);
    1977             :   }
    1978             :   return NoChange();
    1979             : }
    1980             : 
    1981             : // ES6 section 20.2.2.21 Math.log1p ( x )
    1982          13 : Reduction JSBuiltinReducer::ReduceMathLog1p(Node* node) {
    1983             :   JSCallReduction r(node);
    1984          13 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1985             :     // Math.log1p(a:plain-primitive) -> NumberLog1p(ToNumber(a))
    1986          13 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1987          13 :     Node* value = graph()->NewNode(simplified()->NumberLog1p(), input);
    1988             :     return Replace(value);
    1989             :   }
    1990             :   return NoChange();
    1991             : }
    1992             : 
    1993             : // ES6 section 20.2.2.22 Math.log10 ( x )
    1994           0 : Reduction JSBuiltinReducer::ReduceMathLog10(Node* node) {
    1995             :   JSCallReduction r(node);
    1996           0 :   if (r.InputsMatchOne(Type::Number())) {
    1997             :     // Math.log10(a:number) -> NumberLog10(a)
    1998           0 :     Node* value = graph()->NewNode(simplified()->NumberLog10(), r.left());
    1999             :     return Replace(value);
    2000             :   }
    2001             :   return NoChange();
    2002             : }
    2003             : 
    2004             : // ES6 section 20.2.2.23 Math.log2 ( x )
    2005           0 : Reduction JSBuiltinReducer::ReduceMathLog2(Node* node) {
    2006             :   JSCallReduction r(node);
    2007           0 :   if (r.InputsMatchOne(Type::Number())) {
    2008             :     // Math.log2(a:number) -> NumberLog(a)
    2009           0 :     Node* value = graph()->NewNode(simplified()->NumberLog2(), r.left());
    2010             :     return Replace(value);
    2011             :   }
    2012             :   return NoChange();
    2013             : }
    2014             : 
    2015             : // ES6 section 20.2.2.24 Math.max ( value1, value2, ...values )
    2016         484 : Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
    2017             :   JSCallReduction r(node);
    2018         483 :   if (r.InputsMatchZero()) {
    2019             :     // Math.max() -> -Infinity
    2020           1 :     return Replace(jsgraph()->Constant(-V8_INFINITY));
    2021             :   }
    2022         482 :   if (r.InputsMatchAll(Type::PlainPrimitive())) {
    2023             :     // Math.max(a:plain-primitive, b:plain-primitive, ...)
    2024         343 :     Node* value = ToNumber(r.GetJSCallInput(0));
    2025        1348 :     for (int i = 1; i < r.GetJSCallArity(); i++) {
    2026         331 :       Node* input = ToNumber(r.GetJSCallInput(i));
    2027         331 :       value = graph()->NewNode(simplified()->NumberMax(), value, input);
    2028             :     }
    2029             :     return Replace(value);
    2030             :   }
    2031             :   return NoChange();
    2032             : }
    2033             : 
    2034             : // ES6 section 20.2.2.25 Math.min ( value1, value2, ...values )
    2035         443 : Reduction JSBuiltinReducer::ReduceMathMin(Node* node) {
    2036             :   JSCallReduction r(node);
    2037         442 :   if (r.InputsMatchZero()) {
    2038             :     // Math.min() -> Infinity
    2039           1 :     return Replace(jsgraph()->Constant(V8_INFINITY));
    2040             :   }
    2041         441 :   if (r.InputsMatchAll(Type::PlainPrimitive())) {
    2042             :     // Math.min(a:plain-primitive, b:plain-primitive, ...)
    2043         404 :     Node* value = ToNumber(r.GetJSCallInput(0));
    2044        1592 :     for (int i = 1; i < r.GetJSCallArity(); i++) {
    2045         392 :       Node* input = ToNumber(r.GetJSCallInput(i));
    2046         392 :       value = graph()->NewNode(simplified()->NumberMin(), value, input);
    2047             :     }
    2048             :     return Replace(value);
    2049             :   }
    2050             :   return NoChange();
    2051             : }
    2052             : 
    2053             : // ES6 section 20.2.2.26 Math.pow ( x, y )
    2054        1247 : Reduction JSBuiltinReducer::ReduceMathPow(Node* node) {
    2055             :   JSCallReduction r(node);
    2056        1247 :   if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
    2057             :     // Math.pow(a:plain-primitive,
    2058             :     //          b:plain-primitive) -> NumberPow(ToNumber(a), ToNumber(b))
    2059        1205 :     Node* left = ToNumber(r.left());
    2060        1205 :     Node* right = ToNumber(r.right());
    2061        1205 :     Node* value = graph()->NewNode(simplified()->NumberPow(), left, right);
    2062             :     return Replace(value);
    2063             :   }
    2064             :   return NoChange();
    2065             : }
    2066             : 
    2067             : // ES6 section 20.2.2.28 Math.round ( x )
    2068        1578 : Reduction JSBuiltinReducer::ReduceMathRound(Node* node) {
    2069             :   JSCallReduction r(node);
    2070        1578 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2071             :     // Math.round(a:plain-primitive) -> NumberRound(ToNumber(a))
    2072         120 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2073         120 :     Node* value = graph()->NewNode(simplified()->NumberRound(), input);
    2074             :     return Replace(value);
    2075             :   }
    2076             :   return NoChange();
    2077             : }
    2078             : 
    2079             : // ES6 section 20.2.2.9 Math.cbrt ( x )
    2080           0 : Reduction JSBuiltinReducer::ReduceMathCbrt(Node* node) {
    2081             :   JSCallReduction r(node);
    2082           0 :   if (r.InputsMatchOne(Type::Number())) {
    2083             :     // Math.cbrt(a:number) -> NumberCbrt(a)
    2084           0 :     Node* value = graph()->NewNode(simplified()->NumberCbrt(), r.left());
    2085             :     return Replace(value);
    2086             :   }
    2087             :   return NoChange();
    2088             : }
    2089             : 
    2090             : // ES6 section 20.2.2.29 Math.sign ( x )
    2091          34 : Reduction JSBuiltinReducer::ReduceMathSign(Node* node) {
    2092             :   JSCallReduction r(node);
    2093          34 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2094             :     // Math.sign(a:plain-primitive) -> NumberSign(ToNumber(a))
    2095          34 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2096          34 :     Node* value = graph()->NewNode(simplified()->NumberSign(), input);
    2097             :     return Replace(value);
    2098             :   }
    2099             :   return NoChange();
    2100             : }
    2101             : 
    2102             : // ES6 section 20.2.2.30 Math.sin ( x )
    2103          58 : Reduction JSBuiltinReducer::ReduceMathSin(Node* node) {
    2104             :   JSCallReduction r(node);
    2105          58 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2106             :     // Math.sin(a:plain-primitive) -> NumberSin(ToNumber(a))
    2107          49 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2108          49 :     Node* value = graph()->NewNode(simplified()->NumberSin(), input);
    2109             :     return Replace(value);
    2110             :   }
    2111             :   return NoChange();
    2112             : }
    2113             : 
    2114             : // ES6 section 20.2.2.31 Math.sinh ( x )
    2115          21 : Reduction JSBuiltinReducer::ReduceMathSinh(Node* node) {
    2116             :   JSCallReduction r(node);
    2117          21 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2118             :     // Math.sinh(a:plain-primitive) -> NumberSinh(ToNumber(a))
    2119          21 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2120          21 :     Node* value = graph()->NewNode(simplified()->NumberSinh(), input);
    2121             :     return Replace(value);
    2122             :   }
    2123             :   return NoChange();
    2124             : }
    2125             : 
    2126             : // ES6 section 20.2.2.32 Math.sqrt ( x )
    2127          93 : Reduction JSBuiltinReducer::ReduceMathSqrt(Node* node) {
    2128             :   JSCallReduction r(node);
    2129          93 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2130             :     // Math.sqrt(a:plain-primitive) -> NumberSqrt(ToNumber(a))
    2131          58 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2132          58 :     Node* value = graph()->NewNode(simplified()->NumberSqrt(), input);
    2133             :     return Replace(value);
    2134             :   }
    2135             :   return NoChange();
    2136             : }
    2137             : 
    2138             : // ES6 section 20.2.2.33 Math.tan ( x )
    2139          63 : Reduction JSBuiltinReducer::ReduceMathTan(Node* node) {
    2140             :   JSCallReduction r(node);
    2141          63 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2142             :     // Math.tan(a:plain-primitive) -> NumberTan(ToNumber(a))
    2143          22 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2144          22 :     Node* value = graph()->NewNode(simplified()->NumberTan(), input);
    2145             :     return Replace(value);
    2146             :   }
    2147             :   return NoChange();
    2148             : }
    2149             : 
    2150             : // ES6 section 20.2.2.34 Math.tanh ( x )
    2151          21 : Reduction JSBuiltinReducer::ReduceMathTanh(Node* node) {
    2152             :   JSCallReduction r(node);
    2153          21 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2154             :     // Math.tanh(a:plain-primitive) -> NumberTanh(ToNumber(a))
    2155          21 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2156          21 :     Node* value = graph()->NewNode(simplified()->NumberTanh(), input);
    2157             :     return Replace(value);
    2158             :   }
    2159             :   return NoChange();
    2160             : }
    2161             : 
    2162             : // ES6 section 20.2.2.35 Math.trunc ( x )
    2163        6951 : Reduction JSBuiltinReducer::ReduceMathTrunc(Node* node) {
    2164             :   JSCallReduction r(node);
    2165        6951 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2166             :     // Math.trunc(a:plain-primitive) -> NumberTrunc(ToNumber(a))
    2167        1343 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2168        1343 :     Node* value = graph()->NewNode(simplified()->NumberTrunc(), input);
    2169             :     return Replace(value);
    2170             :   }
    2171             :   return NoChange();
    2172             : }
    2173             : 
    2174             : // ES6 section 20.1.2.2 Number.isFinite ( number )
    2175          19 : Reduction JSBuiltinReducer::ReduceNumberIsFinite(Node* node) {
    2176             :   JSCallReduction r(node);
    2177          19 :   if (r.InputsMatchOne(Type::Number())) {
    2178             :     // Number.isFinite(a:number) -> NumberEqual(a', a')
    2179             :     // where a' = NumberSubtract(a, a)
    2180             :     Node* input = r.GetJSCallInput(0);
    2181          19 :     Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, input);
    2182          19 :     Node* value = graph()->NewNode(simplified()->NumberEqual(), diff, diff);
    2183             :     return Replace(value);
    2184             :   }
    2185             :   return NoChange();
    2186             : }
    2187             : 
    2188             : // ES6 section 20.1.2.3 Number.isInteger ( number )
    2189          38 : Reduction JSBuiltinReducer::ReduceNumberIsInteger(Node* node) {
    2190             :   JSCallReduction r(node);
    2191          19 :   if (r.InputsMatchOne(Type::Number())) {
    2192             :     // Number.isInteger(x:number) -> NumberEqual(NumberSubtract(x, x'), #0)
    2193             :     // where x' = NumberTrunc(x)
    2194             :     Node* input = r.GetJSCallInput(0);
    2195          19 :     Node* trunc = graph()->NewNode(simplified()->NumberTrunc(), input);
    2196          19 :     Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, trunc);
    2197             :     Node* value = graph()->NewNode(simplified()->NumberEqual(), diff,
    2198          38 :                                    jsgraph()->ZeroConstant());
    2199             :     return Replace(value);
    2200             :   }
    2201             :   return NoChange();
    2202             : }
    2203             : 
    2204             : // ES6 section 20.1.2.4 Number.isNaN ( number )
    2205          75 : Reduction JSBuiltinReducer::ReduceNumberIsNaN(Node* node) {
    2206             :   JSCallReduction r(node);
    2207          67 :   if (r.InputsMatchZero()) {
    2208             :     // Number.isNaN() -> #false
    2209           8 :     Node* value = jsgraph()->FalseConstant();
    2210             :     return Replace(value);
    2211             :   }
    2212             :   // Number.isNaN(a:number) -> ObjectIsNaN(a)
    2213             :   Node* input = r.GetJSCallInput(0);
    2214          59 :   Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
    2215             :   return Replace(value);
    2216             : }
    2217             : 
    2218             : // ES6 section 20.1.2.5 Number.isSafeInteger ( number )
    2219          21 : Reduction JSBuiltinReducer::ReduceNumberIsSafeInteger(Node* node) {
    2220             :   JSCallReduction r(node);
    2221          14 :   if (r.InputsMatchOne(type_cache_.kSafeInteger)) {
    2222             :     // Number.isInteger(x:safe-integer) -> #true
    2223           7 :     Node* value = jsgraph()->TrueConstant();
    2224             :     return Replace(value);
    2225             :   }
    2226             :   return NoChange();
    2227             : }
    2228             : 
    2229             : // ES6 section 20.1.2.13 Number.parseInt ( string, radix )
    2230         415 : Reduction JSBuiltinReducer::ReduceNumberParseInt(Node* node) {
    2231             :   JSCallReduction r(node);
    2232        1230 :   if (r.InputsMatchOne(type_cache_.kSafeInteger) ||
    2233             :       r.InputsMatchTwo(type_cache_.kSafeInteger,
    2234         794 :                        type_cache_.kZeroOrUndefined) ||
    2235         379 :       r.InputsMatchTwo(type_cache_.kSafeInteger, type_cache_.kTenOrUndefined)) {
    2236             :     // Number.parseInt(a:safe-integer) -> a
    2237             :     // Number.parseInt(a:safe-integer,b:#0\/undefined) -> a
    2238             :     // Number.parseInt(a:safe-integer,b:#10\/undefined) -> a
    2239             :     Node* value = r.GetJSCallInput(0);
    2240             :     return Replace(value);
    2241             :   }
    2242             :   return NoChange();
    2243             : }
    2244             : 
    2245             : // ES6 section #sec-object.create Object.create(proto, properties)
    2246          58 : Reduction JSBuiltinReducer::ReduceObjectCreate(Node* node) {
    2247             :   // We need exactly target, receiver and value parameters.
    2248          58 :   int arg_count = node->op()->ValueInputCount();
    2249          58 :   if (arg_count != 3) return NoChange();
    2250          58 :   Node* effect = NodeProperties::GetEffectInput(node);
    2251          58 :   Node* control = NodeProperties::GetControlInput(node);
    2252          58 :   Node* prototype = NodeProperties::GetValueInput(node, 2);
    2253             :   Type* prototype_type = NodeProperties::GetType(prototype);
    2254             :   Handle<Map> instance_map;
    2255          58 :   if (!prototype_type->IsHeapConstant()) return NoChange();
    2256             :   Handle<HeapObject> prototype_const =
    2257             :       prototype_type->AsHeapConstant()->Value();
    2258           0 :   if (!prototype_const->IsNull(isolate()) && !prototype_const->IsJSReceiver()) {
    2259             :     return NoChange();
    2260             :   }
    2261           0 :   instance_map = Map::GetObjectCreateMap(prototype_const);
    2262           0 :   Node* properties = jsgraph()->EmptyFixedArrayConstant();
    2263           0 :   if (instance_map->is_dictionary_map()) {
    2264             :     // Allocated an empty NameDictionary as backing store for the properties.
    2265           0 :     Handle<Map> map(isolate()->heap()->hash_table_map(), isolate());
    2266             :     int capacity =
    2267             :         NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
    2268             :     DCHECK(base::bits::IsPowerOfTwo(capacity));
    2269             :     int length = NameDictionary::EntryToIndex(capacity);
    2270             :     int size = NameDictionary::SizeFor(length);
    2271             : 
    2272             :     AllocationBuilder a(jsgraph(), effect, control);
    2273           0 :     a.Allocate(size, NOT_TENURED, Type::Any());
    2274           0 :     a.Store(AccessBuilder::ForMap(), map);
    2275             :     // Initialize FixedArray fields.
    2276             :     a.Store(AccessBuilder::ForFixedArrayLength(),
    2277           0 :             jsgraph()->SmiConstant(length));
    2278             :     // Initialize HashTable fields.
    2279             :     a.Store(AccessBuilder::ForHashTableBaseNumberOfElements(),
    2280           0 :             jsgraph()->SmiConstant(0));
    2281             :     a.Store(AccessBuilder::ForHashTableBaseNumberOfDeletedElement(),
    2282           0 :             jsgraph()->SmiConstant(0));
    2283             :     a.Store(AccessBuilder::ForHashTableBaseCapacity(),
    2284           0 :             jsgraph()->SmiConstant(capacity));
    2285             :     // Initialize Dictionary fields.
    2286             :     a.Store(AccessBuilder::ForDictionaryNextEnumerationIndex(),
    2287           0 :             jsgraph()->SmiConstant(PropertyDetails::kInitialIndex));
    2288             :     a.Store(AccessBuilder::ForDictionaryObjectHashIndex(),
    2289           0 :             jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel));
    2290             :     // Initialize the Properties fields.
    2291           0 :     Node* undefined = jsgraph()->UndefinedConstant();
    2292             :     STATIC_ASSERT(NameDictionary::kElementsStartIndex ==
    2293             :                   NameDictionary::kObjectHashIndex + 1);
    2294           0 :     for (int index = NameDictionary::kElementsStartIndex; index < length;
    2295             :          index++) {
    2296           0 :       a.Store(AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier),
    2297           0 :               undefined);
    2298             :     }
    2299           0 :     properties = effect = a.Finish();
    2300             :   }
    2301             : 
    2302             :   int const instance_size = instance_map->instance_size();
    2303           0 :   if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
    2304             :   dependencies()->AssumeInitialMapCantChange(instance_map);
    2305             : 
    2306             :   // Emit code to allocate the JSObject instance for the given
    2307             :   // {instance_map}.
    2308             :   AllocationBuilder a(jsgraph(), effect, control);
    2309           0 :   a.Allocate(instance_size, NOT_TENURED, Type::Any());
    2310           0 :   a.Store(AccessBuilder::ForMap(), instance_map);
    2311           0 :   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
    2312             :   a.Store(AccessBuilder::ForJSObjectElements(),
    2313           0 :           jsgraph()->EmptyFixedArrayConstant());
    2314             :   // Initialize Object fields.
    2315           0 :   Node* undefined = jsgraph()->UndefinedConstant();
    2316           0 :   for (int offset = JSObject::kHeaderSize; offset < instance_size;
    2317             :        offset += kPointerSize) {
    2318             :     a.Store(AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier),
    2319           0 :             undefined);
    2320             :   }
    2321           0 :   Node* value = effect = a.Finish();
    2322             : 
    2323             :   // replace it
    2324           0 :   ReplaceWithValue(node, value, effect, control);
    2325             :   return Replace(value);
    2326             : }
    2327             : 
    2328             : // ES #sec-object.is
    2329          90 : Reduction JSBuiltinReducer::ReduceObjectIs(Node* node) {
    2330             :   // TODO(turbofan): At some point we should probably introduce a new
    2331             :   // SameValue simplified operator (and also a StrictEqual simplified
    2332             :   // operator) and create unified handling in SimplifiedLowering.
    2333             :   JSCallReduction r(node);
    2334         158 :   if (r.GetJSCallArity() == 2 && r.left() == r.right()) {
    2335             :     // Object.is(x,x) => #true
    2336           7 :     Node* value = jsgraph()->TrueConstant();
    2337             :     return Replace(value);
    2338          76 :   } else if (r.InputsMatchTwo(Type::Unique(), Type::Unique())) {
    2339             :     // Object.is(x:Unique,y:Unique) => ReferenceEqual(x,y)
    2340             :     Node* left = r.GetJSCallInput(0);
    2341             :     Node* right = r.GetJSCallInput(1);
    2342           0 :     Node* value = graph()->NewNode(simplified()->ReferenceEqual(), left, right);
    2343             :     return Replace(value);
    2344          76 :   } else if (r.InputsMatchTwo(Type::MinusZero(), Type::Any())) {
    2345             :     // Object.is(x:MinusZero,y) => ObjectIsMinusZero(y)
    2346             :     Node* input = r.GetJSCallInput(1);
    2347          14 :     Node* value = graph()->NewNode(simplified()->ObjectIsMinusZero(), input);
    2348             :     return Replace(value);
    2349          62 :   } else if (r.InputsMatchTwo(Type::Any(), Type::MinusZero())) {
    2350             :     // Object.is(x,y:MinusZero) => ObjectIsMinusZero(x)
    2351             :     Node* input = r.GetJSCallInput(0);
    2352          14 :     Node* value = graph()->NewNode(simplified()->ObjectIsMinusZero(), input);
    2353             :     return Replace(value);
    2354          48 :   } else if (r.InputsMatchTwo(Type::NaN(), Type::Any())) {
    2355             :     // Object.is(x:NaN,y) => ObjectIsNaN(y)
    2356             :     Node* input = r.GetJSCallInput(1);
    2357          14 :     Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
    2358             :     return Replace(value);
    2359          34 :   } else if (r.InputsMatchTwo(Type::Any(), Type::NaN())) {
    2360             :     // Object.is(x,y:NaN) => ObjectIsNaN(x)
    2361             :     Node* input = r.GetJSCallInput(0);
    2362          14 :     Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
    2363             :     return Replace(value);
    2364          20 :   } else if (r.InputsMatchTwo(Type::String(), Type::String())) {
    2365             :     // Object.is(x:String,y:String) => StringEqual(x,y)
    2366             :     Node* left = r.GetJSCallInput(0);
    2367             :     Node* right = r.GetJSCallInput(1);
    2368           7 :     Node* value = graph()->NewNode(simplified()->StringEqual(), left, right);
    2369             :     return Replace(value);
    2370             :   }
    2371             :   return NoChange();
    2372             : }
    2373             : 
    2374             : // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
    2375         181 : Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) {
    2376             :   JSCallReduction r(node);
    2377         181 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2378             :     // String.fromCharCode(a:plain-primitive) -> StringFromCharCode(a)
    2379         154 :     Node* input = ToNumber(r.GetJSCallInput(0));
    2380         154 :     Node* value = graph()->NewNode(simplified()->StringFromCharCode(), input);
    2381             :     return Replace(value);
    2382             :   }
    2383             :   return NoChange();
    2384             : }
    2385             : 
    2386             : namespace {
    2387             : 
    2388         673 : Node* GetStringWitness(Node* node) {
    2389         673 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    2390             :   Type* receiver_type = NodeProperties::GetType(receiver);
    2391         673 :   Node* effect = NodeProperties::GetEffectInput(node);
    2392         673 :   if (receiver_type->Is(Type::String())) return receiver;
    2393             :   // Check if the {node} is dominated by a CheckString renaming for
    2394             :   // it's {receiver}, and if so use that renaming as {receiver} for
    2395             :   // the lowering below.
    2396         547 :   for (Node* dominator = effect;;) {
    2397         716 :     if ((dominator->opcode() == IrOpcode::kCheckString ||
    2398         303 :          dominator->opcode() == IrOpcode::kCheckInternalizedString ||
    2399         692 :          dominator->opcode() == IrOpcode::kCheckSeqString) &&
    2400         279 :         NodeProperties::IsSame(dominator->InputAt(0), receiver)) {
    2401             :       return dominator;
    2402             :     }
    2403         134 :     if (dominator->op()->EffectInputCount() != 1) {
    2404             :       // Didn't find any appropriate CheckString node.
    2405             :       return nullptr;
    2406             :     }
    2407         131 :     dominator = NodeProperties::GetEffectInput(dominator);
    2408         131 :   }
    2409             : }
    2410             : 
    2411             : }  // namespace
    2412             : 
    2413             : // ES6 section 21.1.3.1 String.prototype.charAt ( pos )
    2414         179 : Reduction JSBuiltinReducer::ReduceStringCharAt(Node* node) {
    2415             :   // We need at least target, receiver and index parameters.
    2416         210 :   if (node->op()->ValueInputCount() >= 3) {
    2417         105 :     Node* index = NodeProperties::GetValueInput(node, 2);
    2418             :     Type* index_type = NodeProperties::GetType(index);
    2419         105 :     Node* effect = NodeProperties::GetEffectInput(node);
    2420         105 :     Node* control = NodeProperties::GetControlInput(node);
    2421             : 
    2422         105 :     if (index_type->Is(Type::Integral32OrMinusZeroOrNaN())) {
    2423          77 :       if (Node* receiver = GetStringWitness(node)) {
    2424          74 :         if (!index_type->Is(Type::Unsigned32())) {
    2425             :           // Map -0 and NaN to 0 (as per ToInteger), and the values in
    2426             :           // the [-2^31,-1] range to the [2^31,2^32-1] range, which will
    2427             :           // be considered out-of-bounds as well, because of the maximal
    2428             :           // String length limit in V8.
    2429             :           STATIC_ASSERT(String::kMaxLength <= kMaxInt);
    2430           5 :           index = graph()->NewNode(simplified()->NumberToUint32(), index);
    2431             :         }
    2432             : 
    2433             :         // Determine the {receiver} length.
    2434             :         Node* receiver_length = effect = graph()->NewNode(
    2435             :             simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
    2436         222 :             effect, control);
    2437             : 
    2438             :         // Check if {index} is less than {receiver} length.
    2439             :         Node* check = graph()->NewNode(simplified()->NumberLessThan(), index,
    2440          74 :                                        receiver_length);
    2441             :         Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2442          74 :                                         check, control);
    2443             : 
    2444             :         // Return the character from the {receiver} as single character string.
    2445          74 :         Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    2446             :         Node* vtrue = graph()->NewNode(simplified()->StringCharAt(), receiver,
    2447          74 :                                        index, if_true);
    2448             : 
    2449             :         // Return the empty string otherwise.
    2450          74 :         Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    2451          74 :         Node* vfalse = jsgraph()->EmptyStringConstant();
    2452             : 
    2453          74 :         control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    2454             :         Node* value =
    2455             :             graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2456          74 :                              vtrue, vfalse, control);
    2457             : 
    2458          74 :         ReplaceWithValue(node, value, effect, control);
    2459             :         return Replace(value);
    2460             :       }
    2461             :     }
    2462             :   }
    2463             : 
    2464             :   return NoChange();
    2465             : }
    2466             : 
    2467             : // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
    2468         798 : Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) {
    2469             :   // We need at least target, receiver and index parameters.
    2470         878 :   if (node->op()->ValueInputCount() >= 3) {
    2471         439 :     Node* index = NodeProperties::GetValueInput(node, 2);
    2472             :     Type* index_type = NodeProperties::GetType(index);
    2473         439 :     Node* effect = NodeProperties::GetEffectInput(node);
    2474         439 :     Node* control = NodeProperties::GetControlInput(node);
    2475             : 
    2476         439 :     if (index_type->Is(Type::Integral32OrMinusZeroOrNaN())) {
    2477         359 :       if (Node* receiver = GetStringWitness(node)) {
    2478         359 :         if (!index_type->Is(Type::Unsigned32())) {
    2479             :           // Map -0 and NaN to 0 (as per ToInteger), and the values in
    2480             :           // the [-2^31,-1] range to the [2^31,2^32-1] range, which will
    2481             :           // be considered out-of-bounds as well, because of the maximal
    2482             :           // String length limit in V8.
    2483             :           STATIC_ASSERT(String::kMaxLength <= kMaxInt);
    2484           5 :           index = graph()->NewNode(simplified()->NumberToUint32(), index);
    2485             :         }
    2486             : 
    2487             :         // Determine the {receiver} length.
    2488             :         Node* receiver_length = effect = graph()->NewNode(
    2489             :             simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
    2490        1077 :             effect, control);
    2491             : 
    2492             :         // Check if {index} is less than {receiver} length.
    2493             :         Node* check = graph()->NewNode(simplified()->NumberLessThan(), index,
    2494         359 :                                        receiver_length);
    2495             :         Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2496         359 :                                         check, control);
    2497             : 
    2498             :         // Load the character from the {receiver}.
    2499         359 :         Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    2500             :         Node* vtrue = graph()->NewNode(simplified()->StringCharCodeAt(),
    2501         359 :                                        receiver, index, if_true);
    2502             : 
    2503             :         // Return NaN otherwise.
    2504         359 :         Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    2505         359 :         Node* vfalse = jsgraph()->NaNConstant();
    2506             : 
    2507         359 :         control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    2508             :         Node* value =
    2509             :             graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2510         359 :                              vtrue, vfalse, control);
    2511             : 
    2512         359 :         ReplaceWithValue(node, value, effect, control);
    2513             :         return Replace(value);
    2514             :       }
    2515             :     }
    2516             :   }
    2517             : 
    2518             :   return NoChange();
    2519             : }
    2520             : 
    2521             : // ES6 String.prototype.concat(...args)
    2522             : // #sec-string.prototype.concat
    2523           1 : Reduction JSBuiltinReducer::ReduceStringConcat(Node* node) {
    2524           1 :   if (Node* receiver = GetStringWitness(node)) {
    2525             :     JSCallReduction r(node);
    2526           1 :     if (r.InputsMatchOne(Type::PlainPrimitive())) {
    2527             :       // String.prototype.concat(lhs:string, rhs:plain-primitive)
    2528             :       //   -> Call[StringAddStub](lhs, rhs)
    2529           0 :       StringAddFlags flags = r.InputsMatchOne(Type::String())
    2530             :                                  ? STRING_ADD_CHECK_NONE
    2531           0 :                                  : STRING_ADD_CONVERT_RIGHT;
    2532             :       // TODO(turbofan): Massage the FrameState of the {node} here once we
    2533             :       // have an artificial builtin frame type, so that it looks like the
    2534             :       // exception from StringAdd overflow came from String.prototype.concat
    2535             :       // builtin instead of the calling function.
    2536             :       Callable const callable =
    2537           0 :           CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
    2538             :       CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    2539             :           isolate(), graph()->zone(), callable.descriptor(), 0,
    2540             :           CallDescriptor::kNeedsFrameState,
    2541           0 :           Operator::kNoDeopt | Operator::kNoWrite);
    2542           0 :       node->ReplaceInput(0, jsgraph()->HeapConstant(callable.code()));
    2543           0 :       node->ReplaceInput(1, receiver);
    2544           0 :       NodeProperties::ChangeOp(node, common()->Call(desc));
    2545             :       return Changed(node);
    2546             :     }
    2547             :   }
    2548             : 
    2549             :   return NoChange();
    2550             : }
    2551             : 
    2552             : // ES6 String.prototype.indexOf(searchString [, position])
    2553             : // #sec-string.prototype.indexof
    2554         537 : Reduction JSBuiltinReducer::ReduceStringIndexOf(Node* node) {
    2555             :   // We need at least target, receiver and search_string parameters.
    2556         406 :   if (node->op()->ValueInputCount() >= 3) {
    2557         203 :     Node* search_string = NodeProperties::GetValueInput(node, 2);
    2558             :     Type* search_string_type = NodeProperties::GetType(search_string);
    2559         203 :     Node* position = (node->op()->ValueInputCount() >= 4)
    2560             :                          ? NodeProperties::GetValueInput(node, 3)
    2561         334 :                          : jsgraph()->ZeroConstant();
    2562             :     Type* position_type = NodeProperties::GetType(position);
    2563             : 
    2564         398 :     if (search_string_type->Is(Type::String()) &&
    2565             :         position_type->Is(Type::SignedSmall())) {
    2566         195 :       if (Node* receiver = GetStringWitness(node)) {
    2567             :         RelaxEffectsAndControls(node);
    2568         195 :         node->ReplaceInput(0, receiver);
    2569         195 :         node->ReplaceInput(1, search_string);
    2570         195 :         node->ReplaceInput(2, position);
    2571         195 :         node->TrimInputCount(3);
    2572         195 :         NodeProperties::ChangeOp(node, simplified()->StringIndexOf());
    2573             :         return Changed(node);
    2574             :       }
    2575             :     }
    2576             :   }
    2577             :   return NoChange();
    2578             : }
    2579             : 
    2580         246 : Reduction JSBuiltinReducer::ReduceStringIterator(Node* node) {
    2581          41 :   if (Node* receiver = GetStringWitness(node)) {
    2582          41 :     Node* effect = NodeProperties::GetEffectInput(node);
    2583          41 :     Node* control = NodeProperties::GetControlInput(node);
    2584             : 
    2585             :     Node* map = jsgraph()->HeapConstant(
    2586          41 :         handle(native_context()->string_iterator_map(), isolate()));
    2587             : 
    2588             :     // Allocate new iterator and attach the iterator to this string.
    2589             :     AllocationBuilder a(jsgraph(), effect, control);
    2590          41 :     a.Allocate(JSStringIterator::kSize, NOT_TENURED, Type::OtherObject());
    2591          41 :     a.Store(AccessBuilder::ForMap(), map);
    2592             :     a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
    2593          41 :             jsgraph()->EmptyFixedArrayConstant());
    2594             :     a.Store(AccessBuilder::ForJSObjectElements(),
    2595          41 :             jsgraph()->EmptyFixedArrayConstant());
    2596          41 :     a.Store(AccessBuilder::ForJSStringIteratorString(), receiver);
    2597             :     a.Store(AccessBuilder::ForJSStringIteratorIndex(),
    2598          41 :             jsgraph()->SmiConstant(0));
    2599          41 :     Node* value = effect = a.Finish();
    2600             : 
    2601             :     // Replace it.
    2602          41 :     ReplaceWithValue(node, value, effect, control);
    2603             :     return Replace(value);
    2604             :   }
    2605             :   return NoChange();
    2606             : }
    2607             : 
    2608         320 : Reduction JSBuiltinReducer::ReduceStringIteratorNext(Node* node) {
    2609          32 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    2610          32 :   Node* effect = NodeProperties::GetEffectInput(node);
    2611          32 :   Node* control = NodeProperties::GetControlInput(node);
    2612          32 :   Node* context = NodeProperties::GetContextInput(node);
    2613          32 :   if (HasInstanceTypeWitness(receiver, effect, JS_STRING_ITERATOR_TYPE)) {
    2614             :     Node* string = effect = graph()->NewNode(
    2615             :         simplified()->LoadField(AccessBuilder::ForJSStringIteratorString()),
    2616          96 :         receiver, effect, control);
    2617             :     Node* index = effect = graph()->NewNode(
    2618             :         simplified()->LoadField(AccessBuilder::ForJSStringIteratorIndex()),
    2619          96 :         receiver, effect, control);
    2620             :     Node* length = effect = graph()->NewNode(
    2621             :         simplified()->LoadField(AccessBuilder::ForStringLength()), string,
    2622          96 :         effect, control);
    2623             : 
    2624             :     // branch0: if (index < length)
    2625             :     Node* check0 =
    2626          32 :         graph()->NewNode(simplified()->NumberLessThan(), index, length);
    2627             :     Node* branch0 =
    2628          32 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
    2629             : 
    2630             :     Node* etrue0 = effect;
    2631          32 :     Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    2632             :     Node* done_true;
    2633             :     Node* vtrue0;
    2634             :     {
    2635          32 :       done_true = jsgraph()->FalseConstant();
    2636             :       Node* lead = graph()->NewNode(simplified()->StringCharCodeAt(), string,
    2637          32 :                                     index, if_true0);
    2638             : 
    2639             :       // branch1: if ((lead & 0xFC00) === 0xD800)
    2640             :       Node* check1 =
    2641             :           graph()->NewNode(simplified()->NumberEqual(),
    2642             :                            graph()->NewNode(simplified()->NumberBitwiseAnd(),
    2643             :                                             lead, jsgraph()->Constant(0xFC00)),
    2644         128 :                            jsgraph()->Constant(0xD800));
    2645             :       Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
    2646          32 :                                        check1, if_true0);
    2647          32 :       Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    2648             :       Node* vtrue1;
    2649             :       {
    2650             :         Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
    2651          64 :                                             jsgraph()->OneConstant());
    2652             :         // branch2: if ((index + 1) < length)
    2653             :         Node* check2 = graph()->NewNode(simplified()->NumberLessThan(),
    2654          32 :                                         next_index, length);
    2655             :         Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2656          32 :                                          check2, if_true1);
    2657          32 :         Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
    2658             :         Node* vtrue2;
    2659             :         {
    2660             :           Node* trail = graph()->NewNode(simplified()->StringCharCodeAt(),
    2661          32 :                                          string, next_index, if_true2);
    2662             :           // branch3: if ((trail & 0xFC00) === 0xDC00)
    2663             :           Node* check3 = graph()->NewNode(
    2664             :               simplified()->NumberEqual(),
    2665             :               graph()->NewNode(simplified()->NumberBitwiseAnd(), trail,
    2666             :                                jsgraph()->Constant(0xFC00)),
    2667         128 :               jsgraph()->Constant(0xDC00));
    2668             :           Node* branch3 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2669          32 :                                            check3, if_true2);
    2670          32 :           Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
    2671             :           Node* vtrue3;
    2672             :           {
    2673             :             vtrue3 = graph()->NewNode(
    2674             :                 simplified()->NumberBitwiseOr(),
    2675             : // Need to swap the order for big-endian platforms
    2676             : #if V8_TARGET_BIG_ENDIAN
    2677             :                 graph()->NewNode(simplified()->NumberShiftLeft(), lead,
    2678             :                                  jsgraph()->Constant(16)),
    2679             :                 trail);
    2680             : #else
    2681             :                 graph()->NewNode(simplified()->NumberShiftLeft(), trail,
    2682             :                                  jsgraph()->Constant(16)),
    2683          96 :                 lead);
    2684             : #endif
    2685             :           }
    2686             : 
    2687          32 :           Node* if_false3 = graph()->NewNode(common()->IfFalse(), branch3);
    2688             :           Node* vfalse3 = lead;
    2689          32 :           if_true2 = graph()->NewNode(common()->Merge(2), if_true3, if_false3);
    2690             :           vtrue2 =
    2691             :               graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
    2692          32 :                                vtrue3, vfalse3, if_true2);
    2693             :         }
    2694             : 
    2695          32 :         Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
    2696             :         Node* vfalse2 = lead;
    2697          32 :         if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
    2698             :         vtrue1 =
    2699             :             graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
    2700          32 :                              vtrue2, vfalse2, if_true1);
    2701             :       }
    2702             : 
    2703          32 :       Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    2704             :       Node* vfalse1 = lead;
    2705          32 :       if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
    2706             :       vtrue0 =
    2707             :           graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
    2708          32 :                            vtrue1, vfalse1, if_true0);
    2709             :       vtrue0 = graph()->NewNode(
    2710          32 :           simplified()->StringFromCodePoint(UnicodeEncoding::UTF16), vtrue0);
    2711             : 
    2712             :       // Update iterator.[[NextIndex]]
    2713             :       Node* char_length = etrue0 = graph()->NewNode(
    2714             :           simplified()->LoadField(AccessBuilder::ForStringLength()), vtrue0,
    2715          96 :           etrue0, if_true0);
    2716          32 :       index = graph()->NewNode(simplified()->NumberAdd(), index, char_length);
    2717             :       etrue0 = graph()->NewNode(
    2718             :           simplified()->StoreField(AccessBuilder::ForJSStringIteratorIndex()),
    2719          96 :           receiver, index, etrue0, if_true0);
    2720             :     }
    2721             : 
    2722          32 :     Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    2723             :     Node* done_false;
    2724             :     Node* vfalse0;
    2725             :     {
    2726          32 :       vfalse0 = jsgraph()->UndefinedConstant();
    2727          32 :       done_false = jsgraph()->TrueConstant();
    2728             :     }
    2729             : 
    2730          32 :     control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
    2731          32 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue0, effect, control);
    2732             :     Node* value =
    2733             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2734          32 :                          vtrue0, vfalse0, control);
    2735             :     Node* done =
    2736             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2737          32 :                          done_true, done_false, control);
    2738             : 
    2739             :     value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
    2740          32 :                                       value, done, context, effect);
    2741             : 
    2742          32 :     ReplaceWithValue(node, value, effect, control);
    2743             :     return Replace(value);
    2744             :   }
    2745             :   return NoChange();
    2746             : }
    2747             : 
    2748           0 : Reduction JSBuiltinReducer::ReduceStringToLowerCaseIntl(Node* node) {
    2749           0 :   if (Node* receiver = GetStringWitness(node)) {
    2750             :     RelaxEffectsAndControls(node);
    2751           0 :     node->ReplaceInput(0, receiver);
    2752           0 :     node->TrimInputCount(1);
    2753           0 :     NodeProperties::ChangeOp(node, simplified()->StringToLowerCaseIntl());
    2754             :     NodeProperties::SetType(node, Type::String());
    2755             :     return Changed(node);
    2756             :   }
    2757             :   return NoChange();
    2758             : }
    2759             : 
    2760           0 : Reduction JSBuiltinReducer::ReduceStringToUpperCaseIntl(Node* node) {
    2761           0 :   if (Node* receiver = GetStringWitness(node)) {
    2762             :     RelaxEffectsAndControls(node);
    2763           0 :     node->ReplaceInput(0, receiver);
    2764           0 :     node->TrimInputCount(1);
    2765           0 :     NodeProperties::ChangeOp(node, simplified()->StringToUpperCaseIntl());
    2766             :     NodeProperties::SetType(node, Type::String());
    2767             :     return Changed(node);
    2768             :   }
    2769             :   return NoChange();
    2770             : }
    2771             : 
    2772           0 : Reduction JSBuiltinReducer::ReduceArrayBufferIsView(Node* node) {
    2773           0 :   Node* value = node->op()->ValueInputCount() >= 3
    2774             :                     ? NodeProperties::GetValueInput(node, 2)
    2775           0 :                     : jsgraph()->UndefinedConstant();
    2776             :   RelaxEffectsAndControls(node);
    2777           0 :   node->ReplaceInput(0, value);
    2778           0 :   node->TrimInputCount(1);
    2779           0 :   NodeProperties::ChangeOp(node, simplified()->ObjectIsArrayBufferView());
    2780           0 :   return Changed(node);
    2781             : }
    2782             : 
    2783         332 : Reduction JSBuiltinReducer::ReduceArrayBufferViewAccessor(
    2784         332 :     Node* node, InstanceType instance_type, FieldAccess const& access) {
    2785         332 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    2786         332 :   Node* effect = NodeProperties::GetEffectInput(node);
    2787         332 :   Node* control = NodeProperties::GetControlInput(node);
    2788         332 :   if (HasInstanceTypeWitness(receiver, effect, instance_type)) {
    2789             :     // Load the {receiver}s field.
    2790             :     Node* value = effect = graph()->NewNode(simplified()->LoadField(access),
    2791         332 :                                             receiver, effect, control);
    2792             : 
    2793             :     // See if we can skip the neutering check.
    2794         332 :     if (isolate()->IsArrayBufferNeuteringIntact()) {
    2795             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
    2796             :       // gets neutered.
    2797             :       dependencies()->AssumePropertyCell(
    2798             :           factory()->array_buffer_neutering_protector());
    2799             :     } else {
    2800             :       // Check if the {receiver}s buffer was neutered.
    2801             :       Node* receiver_buffer = effect = graph()->NewNode(
    2802             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
    2803          63 :           receiver, effect, control);
    2804             :       Node* check = effect =
    2805             :           graph()->NewNode(simplified()->ArrayBufferWasNeutered(),
    2806          21 :                            receiver_buffer, effect, control);
    2807             : 
    2808             :       // Default to zero if the {receiver}s buffer was neutered.
    2809             :       value = graph()->NewNode(
    2810             :           common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
    2811          42 :           check, jsgraph()->ZeroConstant(), value);
    2812             :     }
    2813             : 
    2814         332 :     ReplaceWithValue(node, value, effect, control);
    2815             :     return Replace(value);
    2816             :   }
    2817             :   return NoChange();
    2818             : }
    2819             : 
    2820    31934249 : Reduction JSBuiltinReducer::Reduce(Node* node) {
    2821             :   Reduction reduction = NoChange();
    2822             :   JSCallReduction r(node);
    2823             : 
    2824             :   // Dispatch according to the BuiltinFunctionId if present.
    2825    31934249 :   if (!r.HasBuiltinFunctionId()) return NoChange();
    2826       70911 :   switch (r.GetBuiltinFunctionId()) {
    2827             :     case kArrayEntries:
    2828           7 :       return ReduceArrayIterator(node, IterationKind::kEntries);
    2829             :     case kArrayKeys:
    2830           8 :       return ReduceArrayIterator(node, IterationKind::kKeys);
    2831             :     case kArrayValues:
    2832         595 :       return ReduceArrayIterator(node, IterationKind::kValues);
    2833             :     case kArrayIteratorNext:
    2834         728 :       return ReduceArrayIteratorNext(node);
    2835             :     case kArrayIsArray:
    2836          14 :       return ReduceArrayIsArray(node);
    2837             :     case kArrayPop:
    2838         198 :       return ReduceArrayPop(node);
    2839             :     case kArrayPush:
    2840        2476 :       return ReduceArrayPush(node);
    2841             :     case kArrayShift:
    2842         203 :       return ReduceArrayShift(node);
    2843             :     case kDateNow:
    2844           8 :       return ReduceDateNow(node);
    2845             :     case kDateGetTime:
    2846           0 :       return ReduceDateGetTime(node);
    2847             :     case kGlobalIsFinite:
    2848          54 :       reduction = ReduceGlobalIsFinite(node);
    2849          54 :       break;
    2850             :     case kGlobalIsNaN:
    2851       11096 :       reduction = ReduceGlobalIsNaN(node);
    2852       11096 :       break;
    2853             :     case kMapEntries:
    2854             :       return ReduceCollectionIterator(
    2855          14 :           node, JS_MAP_TYPE, Context::MAP_KEY_VALUE_ITERATOR_MAP_INDEX);
    2856             :     case kMapGet:
    2857           8 :       reduction = ReduceMapGet(node);
    2858           8 :       break;
    2859             :     case kMapHas:
    2860           0 :       reduction = ReduceMapHas(node);
    2861           0 :       break;
    2862             :     case kMapKeys:
    2863             :       return ReduceCollectionIterator(node, JS_MAP_TYPE,
    2864          14 :                                       Context::MAP_KEY_ITERATOR_MAP_INDEX);
    2865             :     case kMapSize:
    2866           0 :       return ReduceCollectionSize(node, JS_MAP_TYPE);
    2867             :     case kMapValues:
    2868             :       return ReduceCollectionIterator(node, JS_MAP_TYPE,
    2869          35 :                                       Context::MAP_VALUE_ITERATOR_MAP_INDEX);
    2870             :     case kMapIteratorNext:
    2871             :       return ReduceCollectionIteratorNext(node, OrderedHashMap::kEntrySize,
    2872             :                                           FIRST_MAP_ITERATOR_TYPE,
    2873         105 :                                           LAST_MAP_ITERATOR_TYPE);
    2874             :     case kMathAbs:
    2875         466 :       reduction = ReduceMathAbs(node);
    2876         466 :       break;
    2877             :     case kMathAcos:
    2878          14 :       reduction = ReduceMathAcos(node);
    2879          14 :       break;
    2880             :     case kMathAcosh:
    2881          13 :       reduction = ReduceMathAcosh(node);
    2882          13 :       break;
    2883             :     case kMathAsin:
    2884          14 :       reduction = ReduceMathAsin(node);
    2885          14 :       break;
    2886             :     case kMathAsinh:
    2887          13 :       reduction = ReduceMathAsinh(node);
    2888          13 :       break;
    2889             :     case kMathAtan:
    2890          14 :       reduction = ReduceMathAtan(node);
    2891          14 :       break;
    2892             :     case kMathAtanh:
    2893          13 :       reduction = ReduceMathAtanh(node);
    2894          13 :       break;
    2895             :     case kMathAtan2:
    2896         162 :       reduction = ReduceMathAtan2(node);
    2897         162 :       break;
    2898             :     case kMathCbrt:
    2899           0 :       reduction = ReduceMathCbrt(node);
    2900           0 :       break;
    2901             :     case kMathCeil:
    2902        7252 :       reduction = ReduceMathCeil(node);
    2903        7252 :       break;
    2904             :     case kMathClz32:
    2905          46 :       reduction = ReduceMathClz32(node);
    2906          46 :       break;
    2907             :     case kMathCos:
    2908          34 :       reduction = ReduceMathCos(node);
    2909          34 :       break;
    2910             :     case kMathCosh:
    2911          21 :       reduction = ReduceMathCosh(node);
    2912          21 :       break;
    2913             :     case kMathExp:
    2914          64 :       reduction = ReduceMathExp(node);
    2915          64 :       break;
    2916             :     case kMathExpm1:
    2917           0 :       reduction = ReduceMathExpm1(node);
    2918           0 :       break;
    2919             :     case kMathFloor:
    2920       27376 :       reduction = ReduceMathFloor(node);
    2921       27376 :       break;
    2922             :     case kMathFround:
    2923        1295 :       reduction = ReduceMathFround(node);
    2924        1295 :       break;
    2925             :     case kMathImul:
    2926         851 :       reduction = ReduceMathImul(node);
    2927         851 :       break;
    2928             :     case kMathLog:
    2929         205 :       reduction = ReduceMathLog(node);
    2930         205 :       break;
    2931             :     case kMathLog1p:
    2932          13 :       reduction = ReduceMathLog1p(node);
    2933          13 :       break;
    2934             :     case kMathLog10:
    2935           0 :       reduction = ReduceMathLog10(node);
    2936           0 :       break;
    2937             :     case kMathLog2:
    2938           0 :       reduction = ReduceMathLog2(node);
    2939           0 :       break;
    2940             :     case kMathMax:
    2941         483 :       reduction = ReduceMathMax(node);
    2942         483 :       break;
    2943             :     case kMathMin:
    2944         442 :       reduction = ReduceMathMin(node);
    2945         442 :       break;
    2946             :     case kMathPow:
    2947        1247 :       reduction = ReduceMathPow(node);
    2948        1247 :       break;
    2949             :     case kMathRound:
    2950        1578 :       reduction = ReduceMathRound(node);
    2951        1578 :       break;
    2952             :     case kMathSign:
    2953          34 :       reduction = ReduceMathSign(node);
    2954          34 :       break;
    2955             :     case kMathSin:
    2956          58 :       reduction = ReduceMathSin(node);
    2957          58 :       break;
    2958             :     case kMathSinh:
    2959          21 :       reduction = ReduceMathSinh(node);
    2960          21 :       break;
    2961             :     case kMathSqrt:
    2962          93 :       reduction = ReduceMathSqrt(node);
    2963          93 :       break;
    2964             :     case kMathTan:
    2965          63 :       reduction = ReduceMathTan(node);
    2966          63 :       break;
    2967             :     case kMathTanh:
    2968          21 :       reduction = ReduceMathTanh(node);
    2969          21 :       break;
    2970             :     case kMathTrunc:
    2971        6951 :       reduction = ReduceMathTrunc(node);
    2972        6951 :       break;
    2973             :     case kNumberIsFinite:
    2974          19 :       reduction = ReduceNumberIsFinite(node);
    2975          19 :       break;
    2976             :     case kNumberIsInteger:
    2977          19 :       reduction = ReduceNumberIsInteger(node);
    2978          19 :       break;
    2979             :     case kNumberIsNaN:
    2980          67 :       reduction = ReduceNumberIsNaN(node);
    2981          67 :       break;
    2982             :     case kNumberIsSafeInteger:
    2983          14 :       reduction = ReduceNumberIsSafeInteger(node);
    2984          14 :       break;
    2985             :     case kNumberParseInt:
    2986         415 :       reduction = ReduceNumberParseInt(node);
    2987         415 :       break;
    2988             :     case kObjectCreate:
    2989          58 :       reduction = ReduceObjectCreate(node);
    2990          58 :       break;
    2991             :     case kObjectIs:
    2992          83 :       reduction = ReduceObjectIs(node);
    2993          83 :       break;
    2994             :     case kSetEntries:
    2995             :       return ReduceCollectionIterator(
    2996          14 :           node, JS_SET_TYPE, Context::SET_KEY_VALUE_ITERATOR_MAP_INDEX);
    2997             :     case kSetSize:
    2998           0 :       return ReduceCollectionSize(node, JS_SET_TYPE);
    2999             :     case kSetValues:
    3000             :       return ReduceCollectionIterator(node, JS_SET_TYPE,
    3001          65 :                                       Context::SET_VALUE_ITERATOR_MAP_INDEX);
    3002             :     case kSetIteratorNext:
    3003             :       return ReduceCollectionIteratorNext(node, OrderedHashSet::kEntrySize,
    3004             :                                           FIRST_SET_ITERATOR_TYPE,
    3005         161 :                                           LAST_SET_ITERATOR_TYPE);
    3006             :     case kStringFromCharCode:
    3007         181 :       reduction = ReduceStringFromCharCode(node);
    3008         181 :       break;
    3009             :     case kStringCharAt:
    3010         105 :       return ReduceStringCharAt(node);
    3011             :     case kStringCharCodeAt:
    3012         439 :       return ReduceStringCharCodeAt(node);
    3013             :     case kStringConcat:
    3014           1 :       return ReduceStringConcat(node);
    3015             :     case kStringIndexOf:
    3016         203 :       return ReduceStringIndexOf(node);
    3017             :     case kStringIterator:
    3018          41 :       return ReduceStringIterator(node);
    3019             :     case kStringIteratorNext:
    3020          32 :       return ReduceStringIteratorNext(node);
    3021             :     case kStringToLowerCaseIntl:
    3022           0 :       return ReduceStringToLowerCaseIntl(node);
    3023             :     case kStringToUpperCaseIntl:
    3024           0 :       return ReduceStringToUpperCaseIntl(node);
    3025             :     case kArrayBufferIsView:
    3026           0 :       return ReduceArrayBufferIsView(node);
    3027             :     case kDataViewByteLength:
    3028             :       return ReduceArrayBufferViewAccessor(
    3029             :           node, JS_DATA_VIEW_TYPE,
    3030           0 :           AccessBuilder::ForJSArrayBufferViewByteLength());
    3031             :     case kDataViewByteOffset:
    3032             :       return ReduceArrayBufferViewAccessor(
    3033             :           node, JS_DATA_VIEW_TYPE,
    3034           0 :           AccessBuilder::ForJSArrayBufferViewByteOffset());
    3035             :     case kTypedArrayByteLength:
    3036             :       return ReduceArrayBufferViewAccessor(
    3037             :           node, JS_TYPED_ARRAY_TYPE,
    3038           0 :           AccessBuilder::ForJSArrayBufferViewByteLength());
    3039             :     case kTypedArrayByteOffset:
    3040             :       return ReduceArrayBufferViewAccessor(
    3041             :           node, JS_TYPED_ARRAY_TYPE,
    3042           0 :           AccessBuilder::ForJSArrayBufferViewByteOffset());
    3043             :     case kTypedArrayLength:
    3044             :       return ReduceArrayBufferViewAccessor(
    3045         332 :           node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength());
    3046             :     case kTypedArrayEntries:
    3047           7 :       return ReduceTypedArrayIterator(node, IterationKind::kEntries);
    3048             :     case kTypedArrayKeys:
    3049           0 :       return ReduceTypedArrayIterator(node, IterationKind::kKeys);
    3050             :     case kTypedArrayValues:
    3051          43 :       return ReduceTypedArrayIterator(node, IterationKind::kValues);
    3052             :     case kTypedArrayToStringTag:
    3053          21 :       return ReduceTypedArrayToStringTag(node);
    3054             :     default:
    3055             :       break;
    3056             :   }
    3057             : 
    3058             :   // Replace builtin call assuming replacement nodes are pure values that don't
    3059             :   // produce an effect. Replaces {node} with {reduction} and relaxes effects.
    3060       65042 :   if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement());
    3061             : 
    3062       65042 :   return reduction;
    3063             : }
    3064             : 
    3065       25398 : Node* JSBuiltinReducer::ToNumber(Node* input) {
    3066             :   Type* input_type = NodeProperties::GetType(input);
    3067       25398 :   if (input_type->Is(Type::Number())) return input;
    3068        1254 :   return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), input);
    3069             : }
    3070             : 
    3071          83 : Node* JSBuiltinReducer::ToUint32(Node* input) {
    3072          83 :   input = ToNumber(input);
    3073             :   Type* input_type = NodeProperties::GetType(input);
    3074          83 :   if (input_type->Is(Type::Unsigned32())) return input;
    3075         134 :   return graph()->NewNode(simplified()->NumberToUint32(), input);
    3076             : }
    3077             : 
    3078       85123 : Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); }
    3079             : 
    3080           0 : Factory* JSBuiltinReducer::factory() const { return isolate()->factory(); }
    3081             : 
    3082        4648 : Isolate* JSBuiltinReducer::isolate() const { return jsgraph()->isolate(); }
    3083             : 
    3084             : 
    3085       20245 : CommonOperatorBuilder* JSBuiltinReducer::common() const {
    3086       20245 :   return jsgraph()->common();
    3087             : }
    3088             : 
    3089             : 
    3090       63533 : SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const {
    3091       63593 :   return jsgraph()->simplified();
    3092             : }
    3093             : 
    3094        1079 : JSOperatorBuilder* JSBuiltinReducer::javascript() const {
    3095        1079 :   return jsgraph()->javascript();
    3096             : }
    3097             : 
    3098             : }  // namespace compiler
    3099             : }  // namespace internal
    3100             : }  // namespace v8

Generated by: LCOV version 1.10