LCOV - code coverage report
Current view: top level - src/compiler - js-builtin-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 729 815 89.4 %
Date: 2017-04-26 Functions: 71 81 87.7 %

          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/code-factory.h"
       9             : #include "src/compilation-dependencies.h"
      10             : #include "src/compiler/access-builder.h"
      11             : #include "src/compiler/js-graph.h"
      12             : #include "src/compiler/linkage.h"
      13             : #include "src/compiler/node-matchers.h"
      14             : #include "src/compiler/node-properties.h"
      15             : #include "src/compiler/simplified-operator.h"
      16             : #include "src/compiler/type-cache.h"
      17             : #include "src/compiler/types.h"
      18             : #include "src/objects-inl.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace compiler {
      23             : 
      24             : // Helper class to access JSCall nodes that are potential candidates
      25             : // for reduction when they have a BuiltinFunctionId associated with them.
      26             : class JSCallReduction {
      27             :  public:
      28    32024535 :   explicit JSCallReduction(Node* node) : node_(node) {}
      29             : 
      30             :   // Determines whether the node is a JSCall operation that targets a
      31             :   // constant callee being a well-known builtin with a BuiltinFunctionId.
      32    31952291 :   bool HasBuiltinFunctionId() {
      33    63904582 :     if (node_->opcode() != IrOpcode::kJSCall) return false;
      34      223299 :     HeapObjectMatcher m(NodeProperties::GetValueInput(node_, 0));
      35      427841 :     if (!m.HasValue() || !m.Value()->IsJSFunction()) return false;
      36             :     Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
      37      204342 :     return function->shared()->HasBuiltinFunctionId();
      38             :   }
      39             : 
      40             :   // Retrieves the BuiltinFunctionId as described above.
      41       81877 :   BuiltinFunctionId GetBuiltinFunctionId() {
      42             :     DCHECK_EQ(IrOpcode::kJSCall, node_->opcode());
      43       81877 :     HeapObjectMatcher m(NodeProperties::GetValueInput(node_, 0));
      44             :     Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
      45       81877 :     return function->shared()->builtin_function_id();
      46             :   }
      47             : 
      48             :   bool ReceiverMatches(Type* type) {
      49             :     return NodeProperties::GetType(receiver())->Is(type);
      50             :   }
      51             : 
      52             :   // Determines whether the call takes zero inputs.
      53             :   bool InputsMatchZero() { return GetJSCallArity() == 0; }
      54             : 
      55             :   // Determines whether the call takes one input of the given type.
      56       70111 :   bool InputsMatchOne(Type* t1) {
      57      140119 :     return GetJSCallArity() == 1 &&
      58       70111 :            NodeProperties::GetType(GetJSCallInput(0))->Is(t1);
      59             :   }
      60             : 
      61             :   // Determines whether the call takes two inputs of the given types.
      62        2362 :   bool InputsMatchTwo(Type* t1, Type* t2) {
      63        1603 :     return GetJSCallArity() == 2 &&
      64        3767 :            NodeProperties::GetType(GetJSCallInput(0))->Is(t1) &&
      65        2362 :            NodeProperties::GetType(GetJSCallInput(1))->Is(t2);
      66             :   }
      67             : 
      68             :   // Determines whether the call takes inputs all of the given type.
      69         641 :   bool InputsMatchAll(Type* t) {
      70        3344 :     for (int i = 0; i < GetJSCallArity(); i++) {
      71        1171 :       if (!NodeProperties::GetType(GetJSCallInput(i))->Is(t)) {
      72             :         return false;
      73             :       }
      74             :     }
      75             :     return true;
      76             :   }
      77             : 
      78             :   Node* receiver() { return NodeProperties::GetValueInput(node_, 1); }
      79             :   Node* left() { return GetJSCallInput(0); }
      80             :   Node* right() { return GetJSCallInput(1); }
      81             : 
      82             :   int GetJSCallArity() {
      83             :     DCHECK_EQ(IrOpcode::kJSCall, node_->opcode());
      84             :     // Skip first (i.e. callee) and second (i.e. receiver) operand.
      85       78483 :     return node_->op()->ValueInputCount() - 2;
      86             :   }
      87             : 
      88             :   Node* GetJSCallInput(int index) {
      89             :     DCHECK_EQ(IrOpcode::kJSCall, node_->opcode());
      90             :     DCHECK_LT(index, GetJSCallArity());
      91             :     // Skip first (i.e. callee) and second (i.e. receiver) operand.
      92      105612 :     return NodeProperties::GetValueInput(node_, index + 2);
      93             :   }
      94             : 
      95             :  private:
      96             :   Node* node_;
      97             : };
      98             : 
      99      396062 : JSBuiltinReducer::JSBuiltinReducer(Editor* editor, JSGraph* jsgraph,
     100             :                                    Flags flags,
     101             :                                    CompilationDependencies* dependencies,
     102             :                                    Handle<Context> native_context)
     103             :     : AdvancedReducer(editor),
     104             :       dependencies_(dependencies),
     105             :       flags_(flags),
     106             :       jsgraph_(jsgraph),
     107             :       native_context_(native_context),
     108      396062 :       type_cache_(TypeCache::Get()) {}
     109             : 
     110             : namespace {
     111             : 
     112        3241 : MaybeHandle<Map> GetMapWitness(Node* node) {
     113             :   ZoneHandleSet<Map> maps;
     114        3241 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     115        3241 :   Node* effect = NodeProperties::GetEffectInput(node);
     116             :   NodeProperties::InferReceiverMapsResult result =
     117        3241 :       NodeProperties::InferReceiverMaps(receiver, effect, &maps);
     118        5703 :   if (result == NodeProperties::kReliableReceiverMaps && maps.size() == 1) {
     119             :     return maps[0];
     120             :   }
     121             :   return MaybeHandle<Map>();
     122             : }
     123             : 
     124             : // TODO(turbofan): This was copied from Crankshaft, might be too restrictive.
     125        1039 : 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        2078 :   return descriptors->GetDetails(number).IsReadOnly();
     134             : }
     135             : 
     136             : // TODO(turbofan): This was copied from Crankshaft, might be too restrictive.
     137        1639 : bool CanInlineArrayResizeOperation(Handle<Map> receiver_map) {
     138             :   Isolate* const isolate = receiver_map->GetIsolate();
     139        1639 :   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        4520 :   for (PrototypeIterator it(isolate, receiver_prototype, kStartAtReceiver);
     144        2252 :        !it.IsAtEnd(); it.Advance()) {
     145             :     Handle<JSReceiver> current = PrototypeIterator::GetCurrent<JSReceiver>(it);
     146        2268 :     if (!current->map()->is_stable()) return false;
     147             :   }
     148        1110 :   return receiver_map->instance_type() == JS_ARRAY_TYPE &&
     149        1078 :          IsFastElementsKind(receiver_map->elements_kind()) &&
     150        2156 :          !receiver_map->is_dictionary_map() && receiver_map->is_extensible() &&
     151        1078 :          (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
     152        2109 :          isolate->IsFastArrayConstructorPrototypeChainIntact() &&
     153        3196 :          isolate->IsAnyInitialArrayPrototype(receiver_prototype) &&
     154        2157 :          !IsReadOnlyLengthDescriptor(receiver_map);
     155             : }
     156             : 
     157         827 : bool CanInlineJSArrayIteration(Handle<Map> receiver_map) {
     158             :   Isolate* const isolate = receiver_map->GetIsolate();
     159             :   // Ensure that the [[Prototype]] is actually an exotic Array
     160         827 :   if (!receiver_map->prototype()->IsJSArray()) return false;
     161             : 
     162             :   // Don't inline JSArrays with slow elements of any kind
     163         777 :   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         777 :   if (!IsFastHoleyElementsKind(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           0 :   for (PrototypeIterator it(isolate, receiver_prototype, kStartAtReceiver);
     173           0 :        !it.IsAtEnd(); it.Advance()) {
     174             :     Handle<JSReceiver> current = PrototypeIterator::GetCurrent<JSReceiver>(it);
     175           0 :     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           0 :   return receiver_map->instance_type() == JS_ARRAY_TYPE &&
     181           0 :          (!receiver_map->is_dictionary_map() || receiver_map->is_stable()) &&
     182           0 :          isolate->IsFastArrayConstructorPrototypeChainIntact() &&
     183           0 :          isolate->IsAnyInitialArrayPrototype(receiver_prototype);
     184             : }
     185             : 
     186             : }  // namespace
     187             : 
     188        1512 : Reduction JSBuiltinReducer::ReduceArrayIterator(Node* node,
     189             :                                                 IterationKind kind) {
     190             :   Handle<Map> receiver_map;
     191        3024 :   if (GetMapWitness(node).ToHandle(&receiver_map)) {
     192             :     return ReduceArrayIterator(receiver_map, node, kind,
     193         840 :                                ArrayIteratorKind::kArray);
     194             :   }
     195             :   return NoChange();
     196             : }
     197             : 
     198          14 : Reduction JSBuiltinReducer::ReduceTypedArrayIterator(Node* node,
     199             :                                                      IterationKind kind) {
     200             :   Handle<Map> receiver_map;
     201          42 :   if (GetMapWitness(node).ToHandle(&receiver_map) &&
     202             :       receiver_map->instance_type() == JS_TYPED_ARRAY_TYPE) {
     203             :     return ReduceArrayIterator(receiver_map, node, kind,
     204          14 :                                ArrayIteratorKind::kTypedArray);
     205             :   }
     206             :   return NoChange();
     207             : }
     208             : 
     209         854 : Reduction JSBuiltinReducer::ReduceArrayIterator(Handle<Map> receiver_map,
     210             :                                                 Node* node, IterationKind kind,
     211        5908 :                                                 ArrayIteratorKind iter_kind) {
     212         854 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     213         854 :   Node* effect = NodeProperties::GetEffectInput(node);
     214         854 :   Node* control = NodeProperties::GetControlInput(node);
     215             : 
     216         854 :   if (iter_kind == ArrayIteratorKind::kTypedArray) {
     217             :     // See if we can skip the neutering check.
     218          14 :     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          21 :           receiver, effect, control);
     230             : 
     231             :       // Deoptimize if the {buffer} has been neutered.
     232             :       Node* check = effect = graph()->NewNode(
     233           7 :           simplified()->ArrayBufferWasNeutered(), buffer, effect, control);
     234           7 :       check = graph()->NewNode(simplified()->BooleanNot(), check);
     235             :       effect =
     236           7 :           graph()->NewNode(simplified()->CheckIf(), check, effect, control);
     237             :     }
     238             :   }
     239             : 
     240             :   int map_index = -1;
     241         854 :   Node* object_map = jsgraph()->UndefinedConstant();
     242         854 :   switch (receiver_map->instance_type()) {
     243             :     case JS_ARRAY_TYPE:
     244         840 :       if (kind == IterationKind::kKeys) {
     245             :         map_index = Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX;
     246             :       } else {
     247             :         map_index = kind == IterationKind::kValues
     248             :                         ? Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX
     249         827 :                         : Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
     250             : 
     251         827 :         if (CanInlineJSArrayIteration(receiver_map)) {
     252             :           // Use `generic` elements for holey arrays if there may be elements
     253             :           // on the prototype chain.
     254         777 :           map_index += static_cast<int>(receiver_map->elements_kind());
     255         777 :           object_map = jsgraph()->Constant(receiver_map);
     256         777 :           if (IsFastHoleyElementsKind(receiver_map->elements_kind())) {
     257             :             Handle<JSObject> initial_array_prototype(
     258             :                 native_context()->initial_array_prototype(), isolate());
     259             :             dependencies()->AssumePrototypeMapsStable(receiver_map,
     260           0 :                                                       initial_array_prototype);
     261             :           }
     262             :         } else {
     263             :           map_index += (Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
     264          50 :                         Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX);
     265             :         }
     266             :       }
     267             :       break;
     268             :     case JS_TYPED_ARRAY_TYPE:
     269          14 :       if (kind == IterationKind::kKeys) {
     270             :         map_index = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
     271             :       } else {
     272             :         DCHECK_GE(receiver_map->elements_kind(), UINT8_ELEMENTS);
     273             :         DCHECK_LE(receiver_map->elements_kind(), UINT8_CLAMPED_ELEMENTS);
     274             :         map_index = (kind == IterationKind::kValues
     275             :                          ? Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX
     276          14 :                          : Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX) +
     277          14 :                     (receiver_map->elements_kind() - UINT8_ELEMENTS);
     278             :       }
     279             :       break;
     280             :     default:
     281           0 :       if (kind == IterationKind::kKeys) {
     282             :         map_index = Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX;
     283           0 :       } else if (kind == IterationKind::kValues) {
     284             :         map_index = Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX;
     285             :       } else {
     286             :         map_index = Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
     287             :       }
     288             :       break;
     289             :   }
     290             : 
     291             :   DCHECK_GE(map_index, Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX);
     292             :   DCHECK_LE(map_index, Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX);
     293             : 
     294             :   Handle<Map> map(Map::cast(native_context()->get(map_index)), isolate());
     295             : 
     296             :   // allocate new iterator
     297             :   effect = graph()->NewNode(
     298         854 :       common()->BeginRegion(RegionObservability::kNotObservable), effect);
     299             :   Node* value = effect = graph()->NewNode(
     300             :       simplified()->Allocate(Type::OtherObject(), NOT_TENURED),
     301        1708 :       jsgraph()->Constant(JSArrayIterator::kSize), effect, control);
     302             :   effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
     303        2562 :                             value, jsgraph()->Constant(map), effect, control);
     304             :   effect = graph()->NewNode(
     305             :       simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
     306        2562 :       jsgraph()->EmptyFixedArrayConstant(), effect, control);
     307             :   effect = graph()->NewNode(
     308             :       simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
     309        2562 :       jsgraph()->EmptyFixedArrayConstant(), effect, control);
     310             : 
     311             :   // attach the iterator to this object
     312             :   effect = graph()->NewNode(
     313             :       simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
     314        2562 :       value, receiver, effect, control);
     315             :   effect = graph()->NewNode(
     316             :       simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex()), value,
     317        2562 :       jsgraph()->ZeroConstant(), effect, control);
     318             :   effect = graph()->NewNode(
     319             :       simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObjectMap()),
     320        2562 :       value, object_map, effect, control);
     321             : 
     322         854 :   value = effect = graph()->NewNode(common()->FinishRegion(), value, effect);
     323             : 
     324             :   // replace it
     325         854 :   ReplaceWithValue(node, value, effect, control);
     326         854 :   return Replace(value);
     327             : }
     328             : 
     329        1425 : Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext(
     330        9681 :     Handle<Map> iterator_map, Node* node, IterationKind kind) {
     331        1425 :   Node* iterator = NodeProperties::GetValueInput(node, 1);
     332        1425 :   Node* effect = NodeProperties::GetEffectInput(node);
     333        1425 :   Node* control = NodeProperties::GetControlInput(node);
     334        1425 :   Node* context = NodeProperties::GetContextInput(node);
     335             : 
     336        2837 :   if (kind != IterationKind::kKeys &&
     337             :       !isolate()->IsFastArrayIterationIntact()) {
     338             :     // Avoid deopt loops for non-key iteration if the
     339             :     // fast_array_iteration_protector cell has been invalidated.
     340             :     return NoChange();
     341             :   }
     342             : 
     343             :   ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
     344        1383 :       iterator_map->instance_type());
     345             : 
     346        1383 :   if (IsFastHoleyElementsKind(elements_kind)) {
     347           0 :     if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
     348             :       return NoChange();
     349             :     } else {
     350             :       Handle<JSObject> initial_array_prototype(
     351             :           native_context()->initial_array_prototype(), isolate());
     352             :       dependencies()->AssumePropertyCell(factory()->array_protector());
     353             :     }
     354             :   }
     355             : 
     356             :   Node* array = effect = graph()->NewNode(
     357             :       simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
     358        4149 :       iterator, effect, control);
     359             :   Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
     360        2766 :                                   jsgraph()->UndefinedConstant());
     361             :   Node* branch0 =
     362        1383 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
     363             : 
     364             :   Node* vdone_false0;
     365             :   Node* vfalse0;
     366             :   Node* efalse0 = effect;
     367        1383 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
     368             :   {
     369             :     // iterator.[[IteratedObject]] !== undefined, continue iterating.
     370             :     Node* index = efalse0 = graph()->NewNode(
     371             :         simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
     372             :             JS_ARRAY_TYPE, elements_kind)),
     373        4149 :         iterator, efalse0, if_false0);
     374             : 
     375             :     Node* length = efalse0 = graph()->NewNode(
     376             :         simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
     377        4149 :         array, efalse0, if_false0);
     378             :     Node* check1 =
     379        1383 :         graph()->NewNode(simplified()->NumberLessThan(), index, length);
     380             :     Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
     381        1383 :                                      check1, if_false0);
     382             : 
     383             :     Node* vdone_true1;
     384             :     Node* vtrue1;
     385             :     Node* etrue1 = efalse0;
     386        1383 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
     387             :     {
     388             :       // iterator.[[NextIndex]] < array.length, continue iterating
     389        1383 :       vdone_true1 = jsgraph()->FalseConstant();
     390        1383 :       if (kind == IterationKind::kKeys) {
     391             :         vtrue1 = index;
     392             :       } else {
     393             :         // For value/entry iteration, first step is a mapcheck to ensure
     394             :         // inlining is still valid.
     395             :         Node* array_map = etrue1 =
     396             :             graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
     397        4110 :                              array, etrue1, if_true1);
     398             :         Node* orig_map = etrue1 =
     399             :             graph()->NewNode(simplified()->LoadField(
     400             :                                  AccessBuilder::ForJSArrayIteratorObjectMap()),
     401        4110 :                              iterator, etrue1, if_true1);
     402             :         Node* check_map = graph()->NewNode(simplified()->ReferenceEqual(),
     403        1370 :                                            array_map, orig_map);
     404             :         etrue1 = graph()->NewNode(simplified()->CheckIf(), check_map, etrue1,
     405        1370 :                                   if_true1);
     406             :       }
     407             : 
     408        1383 :       if (kind != IterationKind::kKeys) {
     409             :         Node* elements = etrue1 = graph()->NewNode(
     410             :             simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
     411        4110 :             array, etrue1, if_true1);
     412             :         Node* value = etrue1 = graph()->NewNode(
     413             :             simplified()->LoadElement(
     414             :                 AccessBuilder::ForFixedArrayElement(elements_kind)),
     415        4110 :             elements, index, etrue1, if_true1);
     416             : 
     417             :         // Convert hole to undefined if needed.
     418        1370 :         if (elements_kind == FAST_HOLEY_ELEMENTS ||
     419             :             elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
     420             :           value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(),
     421           0 :                                    value);
     422        1370 :         } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
     423             :           // TODO(bmeurer): avoid deopt if not all uses of value are truncated.
     424             :           CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
     425             :           value = etrue1 = graph()->NewNode(
     426           0 :               simplified()->CheckFloat64Hole(mode), value, etrue1, if_true1);
     427             :         }
     428             : 
     429        1370 :         if (kind == IterationKind::kEntries) {
     430             :           // Allocate elements for key/value pair
     431             :           vtrue1 = etrue1 =
     432             :               graph()->NewNode(javascript()->CreateKeyValueArray(), index,
     433           7 :                                value, context, etrue1);
     434             :         } else {
     435             :           DCHECK_EQ(kind, IterationKind::kValues);
     436             :           vtrue1 = value;
     437             :         }
     438             :       }
     439             : 
     440             :       Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
     441        2766 :                                           jsgraph()->OneConstant());
     442        1383 :       next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
     443             : 
     444             :       etrue1 = graph()->NewNode(
     445             :           simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
     446             :               JS_ARRAY_TYPE, elements_kind)),
     447        4149 :           iterator, next_index, etrue1, if_true1);
     448             :     }
     449             : 
     450             :     Node* vdone_false1;
     451             :     Node* vfalse1;
     452             :     Node* efalse1 = efalse0;
     453        1383 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
     454             :     {
     455             :       // iterator.[[NextIndex]] >= array.length, stop iterating.
     456        1383 :       vdone_false1 = jsgraph()->TrueConstant();
     457        1383 :       vfalse1 = jsgraph()->UndefinedConstant();
     458             :       efalse1 = graph()->NewNode(
     459             :           simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
     460        4149 :           iterator, vfalse1, efalse1, if_false1);
     461             :     }
     462             : 
     463        1383 :     if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
     464             :     efalse0 =
     465        1383 :         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
     466             :     vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     467        1383 :                                vtrue1, vfalse1, if_false0);
     468             :     vdone_false0 =
     469             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     470        1383 :                          vdone_true1, vdone_false1, if_false0);
     471             :   }
     472             : 
     473             :   Node* vdone_true0;
     474             :   Node* vtrue0;
     475             :   Node* etrue0 = effect;
     476        1383 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
     477             :   {
     478             :     // iterator.[[IteratedObject]] === undefined, the iterator is done.
     479        1383 :     vdone_true0 = jsgraph()->TrueConstant();
     480        1383 :     vtrue0 = jsgraph()->UndefinedConstant();
     481             :   }
     482             : 
     483        1383 :   control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
     484        1383 :   effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
     485             :   Node* value =
     486             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     487        1383 :                        vfalse0, vtrue0, control);
     488             :   Node* done =
     489             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     490        1383 :                        vdone_false0, vdone_true0, control);
     491             : 
     492             :   // Create IteratorResult object.
     493             :   value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
     494        1383 :                                     value, done, context, effect);
     495        1383 :   ReplaceWithValue(node, value, effect, control);
     496             :   return Replace(value);
     497             : }
     498             : 
     499          14 : Reduction JSBuiltinReducer::ReduceTypedArrayIteratorNext(
     500         105 :     Handle<Map> iterator_map, Node* node, IterationKind kind) {
     501          14 :   Node* iterator = NodeProperties::GetValueInput(node, 1);
     502          14 :   Node* effect = NodeProperties::GetEffectInput(node);
     503          14 :   Node* control = NodeProperties::GetControlInput(node);
     504          14 :   Node* context = NodeProperties::GetContextInput(node);
     505             : 
     506             :   ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
     507          14 :       iterator_map->instance_type());
     508             : 
     509             :   Node* array = effect = graph()->NewNode(
     510             :       simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
     511          42 :       iterator, effect, control);
     512             :   Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
     513          28 :                                   jsgraph()->UndefinedConstant());
     514             :   Node* branch0 =
     515          14 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
     516             : 
     517             :   Node* vdone_false0;
     518             :   Node* vfalse0;
     519             :   Node* efalse0 = effect;
     520          14 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
     521             :   {
     522             :     // iterator.[[IteratedObject]] !== undefined, continue iterating.
     523             :     Node* index = efalse0 = graph()->NewNode(
     524             :         simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
     525             :             JS_TYPED_ARRAY_TYPE, elements_kind)),
     526          42 :         iterator, efalse0, if_false0);
     527             : 
     528             :     // typedarray.[[ViewedArrayBuffer]]
     529             :     Node* buffer = efalse0 = graph()->NewNode(
     530             :         simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
     531          42 :         array, efalse0, if_false0);
     532             : 
     533             :     // See if we can skip the neutering check.
     534          14 :     if (isolate()->IsArrayBufferNeuteringIntact()) {
     535             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
     536             :       // gets neutered.
     537             :       dependencies()->AssumePropertyCell(
     538             :           factory()->array_buffer_neutering_protector());
     539             :     } else {
     540             :       // Deoptimize if the array buffer was neutered.
     541             :       Node* check1 = efalse0 = graph()->NewNode(
     542           7 :           simplified()->ArrayBufferWasNeutered(), buffer, efalse0, if_false0);
     543           7 :       check1 = graph()->NewNode(simplified()->BooleanNot(), check1);
     544             :       efalse0 =
     545           7 :           graph()->NewNode(simplified()->CheckIf(), check1, efalse0, if_false0);
     546             :     }
     547             : 
     548             :     Node* length = efalse0 = graph()->NewNode(
     549             :         simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()), array,
     550          42 :         efalse0, if_false0);
     551             : 
     552             :     Node* check2 =
     553          14 :         graph()->NewNode(simplified()->NumberLessThan(), index, length);
     554             :     Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
     555          14 :                                      check2, if_false0);
     556             : 
     557             :     Node* vdone_true2;
     558             :     Node* vtrue2;
     559             :     Node* etrue2 = efalse0;
     560          14 :     Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
     561             :     {
     562             :       // iterator.[[NextIndex]] < array.length, continue iterating
     563          14 :       vdone_true2 = jsgraph()->FalseConstant();
     564          14 :       if (kind == IterationKind::kKeys) {
     565             :         vtrue2 = index;
     566             :       }
     567             : 
     568             :       Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
     569          28 :                                           jsgraph()->OneConstant());
     570          14 :       next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
     571             : 
     572             :       etrue2 = graph()->NewNode(
     573             :           simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
     574             :               JS_TYPED_ARRAY_TYPE, elements_kind)),
     575          42 :           iterator, next_index, etrue2, if_true2);
     576             : 
     577          14 :       if (kind != IterationKind::kKeys) {
     578             :         Node* elements = etrue2 = graph()->NewNode(
     579             :             simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
     580          42 :             array, etrue2, if_true2);
     581             :         Node* base_ptr = etrue2 = graph()->NewNode(
     582             :             simplified()->LoadField(
     583             :                 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
     584          42 :             elements, etrue2, if_true2);
     585             :         Node* external_ptr = etrue2 = graph()->NewNode(
     586             :             simplified()->LoadField(
     587             :                 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
     588          42 :             elements, etrue2, if_true2);
     589             : 
     590          14 :         ExternalArrayType array_type = kExternalInt8Array;
     591          14 :         switch (elements_kind) {
     592             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
     593             :   case TYPE##_ELEMENTS:                                 \
     594             :     array_type = kExternal##Type##Array;                \
     595             :     break;
     596          14 :           TYPED_ARRAYS(TYPED_ARRAY_CASE)
     597             :           default:
     598           0 :             UNREACHABLE();
     599             : #undef TYPED_ARRAY_CASE
     600             :         }
     601             : 
     602             :         Node* value = etrue2 =
     603             :             graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
     604          14 :                              base_ptr, external_ptr, index, etrue2, if_true2);
     605             : 
     606          14 :         if (kind == IterationKind::kEntries) {
     607             :           // Allocate elements for key/value pair
     608             :           vtrue2 = etrue2 =
     609             :               graph()->NewNode(javascript()->CreateKeyValueArray(), index,
     610           7 :                                value, context, etrue2);
     611             :         } else {
     612             :           DCHECK(kind == IterationKind::kValues);
     613             :           vtrue2 = value;
     614             :         }
     615             :       }
     616             :     }
     617             : 
     618             :     Node* vdone_false2;
     619             :     Node* vfalse2;
     620             :     Node* efalse2 = efalse0;
     621          14 :     Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
     622             :     {
     623             :       // iterator.[[NextIndex]] >= array.length, stop iterating.
     624          14 :       vdone_false2 = jsgraph()->TrueConstant();
     625          14 :       vfalse2 = jsgraph()->UndefinedConstant();
     626             :       efalse2 = graph()->NewNode(
     627             :           simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
     628          42 :           iterator, vfalse2, efalse2, if_false2);
     629             :     }
     630             : 
     631          14 :     if_false0 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
     632             :     efalse0 =
     633          14 :         graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_false0);
     634             :     vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     635          14 :                                vtrue2, vfalse2, if_false0);
     636             :     vdone_false0 =
     637             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     638          14 :                          vdone_true2, vdone_false2, if_false0);
     639             :   }
     640             : 
     641             :   Node* vdone_true0;
     642             :   Node* vtrue0;
     643             :   Node* etrue0 = effect;
     644          14 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
     645             :   {
     646             :     // iterator.[[IteratedObject]] === undefined, the iterator is done.
     647          14 :     vdone_true0 = jsgraph()->TrueConstant();
     648          14 :     vtrue0 = jsgraph()->UndefinedConstant();
     649             :   }
     650             : 
     651          14 :   control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
     652          14 :   effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
     653             :   Node* value =
     654             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     655          14 :                        vfalse0, vtrue0, control);
     656             :   Node* done =
     657             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     658          14 :                        vdone_false0, vdone_true0, control);
     659             : 
     660             :   // Create IteratorResult object.
     661             :   value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
     662          14 :                                     value, done, context, effect);
     663          14 :   ReplaceWithValue(node, value, effect, control);
     664          14 :   return Replace(value);
     665             : }
     666             : 
     667        1562 : Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) {
     668             :   Handle<Map> receiver_map;
     669        3124 :   if (GetMapWitness(node).ToHandle(&receiver_map)) {
     670        1440 :     switch (receiver_map->instance_type()) {
     671             :       case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
     672             :         return ReduceTypedArrayIteratorNext(receiver_map, node,
     673           0 :                                             IterationKind::kKeys);
     674             : 
     675             :       case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
     676             :         return ReduceFastArrayIteratorNext(receiver_map, node,
     677          13 :                                            IterationKind::kKeys);
     678             : 
     679             :       case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     680             :       case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     681             :       case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     682             :       case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     683             :       case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     684             :       case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     685             :       case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     686             :       case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     687             :       case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     688             :         return ReduceTypedArrayIteratorNext(receiver_map, node,
     689           7 :                                             IterationKind::kEntries);
     690             : 
     691             :       case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     692             :       case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     693             :       case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     694             :       case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     695             :       case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     696             :       case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
     697             :         return ReduceFastArrayIteratorNext(receiver_map, node,
     698           7 :                                            IterationKind::kEntries);
     699             : 
     700             :       case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
     701             :       case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
     702             :       case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
     703             :       case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
     704             :       case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
     705             :       case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
     706             :       case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
     707             :       case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
     708             :       case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
     709             :         return ReduceTypedArrayIteratorNext(receiver_map, node,
     710           7 :                                             IterationKind::kValues);
     711             : 
     712             :       case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
     713             :       case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
     714             :       case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
     715             :       case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
     716             :       case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
     717             :       case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
     718             :         return ReduceFastArrayIteratorNext(receiver_map, node,
     719        1405 :                                            IterationKind::kValues);
     720             : 
     721             :       default:
     722             :         // Slow array iterators are not reduced
     723             :         return NoChange();
     724             :     }
     725             :   }
     726             :   return NoChange();
     727             : }
     728             : 
     729             : // ES6 section 22.1.2.2 Array.isArray ( arg )
     730          74 : Reduction JSBuiltinReducer::ReduceArrayIsArray(Node* node) {
     731             :   // We certainly know that undefined is not an array.
     732          42 :   if (node->op()->ValueInputCount() < 3) {
     733           0 :     Node* value = jsgraph()->FalseConstant();
     734          21 :     ReplaceWithValue(node, value);
     735             :     return Replace(value);
     736             :   }
     737          21 :   Node* value = NodeProperties::GetValueInput(node, 2);
     738             :   Type* value_type = NodeProperties::GetType(value);
     739          21 :   Node* context = NodeProperties::GetContextInput(node);
     740          21 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     741          21 :   Node* effect = NodeProperties::GetEffectInput(node);
     742          21 :   Node* control = NodeProperties::GetControlInput(node);
     743             : 
     744             :   // Constant-fold based on {value} type.
     745          21 :   if (value_type->Is(Type::Array())) {
     746          13 :     Node* value = jsgraph()->TrueConstant();
     747             :     ReplaceWithValue(node, value);
     748             :     return Replace(value);
     749           8 :   } else if (!value_type->Maybe(Type::ArrayOrProxy())) {
     750           0 :     Node* value = jsgraph()->FalseConstant();
     751             :     ReplaceWithValue(node, value);
     752             :     return Replace(value);
     753             :   }
     754             : 
     755             :   int count = 0;
     756             :   Node* values[5];
     757             :   Node* effects[5];
     758             :   Node* controls[4];
     759             : 
     760             :   // Check if the {value} is a Smi.
     761           8 :   Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
     762             :   control =
     763           8 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
     764             : 
     765             :   // The {value} is a Smi.
     766          16 :   controls[count] = graph()->NewNode(common()->IfTrue(), control);
     767           8 :   effects[count] = effect;
     768           8 :   values[count] = jsgraph()->FalseConstant();
     769             :   count++;
     770             : 
     771           8 :   control = graph()->NewNode(common()->IfFalse(), control);
     772             : 
     773             :   // Load the {value}s instance type.
     774             :   Node* value_map = effect = graph()->NewNode(
     775          24 :       simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
     776             :   Node* value_instance_type = effect = graph()->NewNode(
     777             :       simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
     778          24 :       effect, control);
     779             : 
     780             :   // Check if the {value} is a JSArray.
     781             :   check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type,
     782          16 :                            jsgraph()->Constant(JS_ARRAY_TYPE));
     783           8 :   control = graph()->NewNode(common()->Branch(), check, control);
     784             : 
     785             :   // The {value} is a JSArray.
     786          16 :   controls[count] = graph()->NewNode(common()->IfTrue(), control);
     787           8 :   effects[count] = effect;
     788           8 :   values[count] = jsgraph()->TrueConstant();
     789             :   count++;
     790             : 
     791           8 :   control = graph()->NewNode(common()->IfFalse(), control);
     792             : 
     793             :   // Check if the {value} is a JSProxy.
     794             :   check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type,
     795          16 :                            jsgraph()->Constant(JS_PROXY_TYPE));
     796             :   control =
     797           8 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
     798             : 
     799             :   // The {value} is neither a JSArray nor a JSProxy.
     800          16 :   controls[count] = graph()->NewNode(common()->IfFalse(), control);
     801           8 :   effects[count] = effect;
     802           8 :   values[count] = jsgraph()->FalseConstant();
     803             :   count++;
     804             : 
     805           8 :   control = graph()->NewNode(common()->IfTrue(), control);
     806             : 
     807             :   // Let the %ArrayIsArray runtime function deal with the JSProxy {value}.
     808             :   value = effect = control =
     809             :       graph()->NewNode(javascript()->CallRuntime(Runtime::kArrayIsArray), value,
     810           8 :                        context, frame_state, effect, control);
     811             :   NodeProperties::SetType(value, Type::Boolean());
     812             : 
     813             :   // Update potential {IfException} uses of {node} to point to the above
     814             :   // %ArrayIsArray runtime call node instead.
     815           8 :   Node* on_exception = nullptr;
     816           8 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
     817           0 :     NodeProperties::ReplaceControlInput(on_exception, control);
     818           0 :     NodeProperties::ReplaceEffectInput(on_exception, effect);
     819           0 :     control = graph()->NewNode(common()->IfSuccess(), control);
     820           0 :     Revisit(on_exception);
     821             :   }
     822             : 
     823             :   // The {value} is neither a JSArray nor a JSProxy.
     824           8 :   controls[count] = control;
     825           8 :   effects[count] = effect;
     826           8 :   values[count] = value;
     827             :   count++;
     828             : 
     829          16 :   control = graph()->NewNode(common()->Merge(count), count, controls);
     830           8 :   effects[count] = control;
     831           8 :   values[count] = control;
     832          16 :   effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects);
     833             :   value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
     834          16 :                            count + 1, values);
     835             :   ReplaceWithValue(node, value, effect, control);
     836             :   return Replace(value);
     837             : }
     838             : 
     839             : // ES6 section 22.1.3.17 Array.prototype.pop ( )
     840         549 : Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) {
     841             :   Handle<Map> receiver_map;
     842         153 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     843         153 :   Node* effect = NodeProperties::GetEffectInput(node);
     844         153 :   Node* control = NodeProperties::GetControlInput(node);
     845             :   // TODO(turbofan): Extend this to also handle fast (holey) double elements
     846             :   // once we got the hole NaN mess sorted out in TurboFan/V8.
     847         455 :   if (GetMapWitness(node).ToHandle(&receiver_map) &&
     848         234 :       CanInlineArrayResizeOperation(receiver_map) &&
     849             :       IsFastSmiOrObjectElementsKind(receiver_map->elements_kind())) {
     850             :     // Install code dependencies on the {receiver} prototype maps and the
     851             :     // global array protector cell.
     852             :     dependencies()->AssumePropertyCell(factory()->array_protector());
     853          66 :     dependencies()->AssumePrototypeMapsStable(receiver_map);
     854             : 
     855             :     // Load the "length" property of the {receiver}.
     856             :     Node* length = effect = graph()->NewNode(
     857             :         simplified()->LoadField(
     858             :             AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
     859         198 :         receiver, effect, control);
     860             : 
     861             :     // Check if the {receiver} has any elements.
     862             :     Node* check = graph()->NewNode(simplified()->NumberEqual(), length,
     863         132 :                                    jsgraph()->ZeroConstant());
     864             :     Node* branch =
     865          66 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
     866             : 
     867          66 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
     868             :     Node* etrue = effect;
     869          66 :     Node* vtrue = jsgraph()->UndefinedConstant();
     870             : 
     871          66 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
     872             :     Node* efalse = effect;
     873             :     Node* vfalse;
     874             :     {
     875             :       // Load the elements backing store from the {receiver}.
     876             :       Node* elements = efalse = graph()->NewNode(
     877             :           simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
     878         198 :           receiver, efalse, if_false);
     879             : 
     880             :       // Ensure that we aren't popping from a copy-on-write backing store.
     881             :       elements = efalse =
     882             :           graph()->NewNode(simplified()->EnsureWritableFastElements(), receiver,
     883          66 :                            elements, efalse, if_false);
     884             : 
     885             :       // Compute the new {length}.
     886             :       length = graph()->NewNode(simplified()->NumberSubtract(), length,
     887         132 :                                 jsgraph()->OneConstant());
     888             : 
     889             :       // Store the new {length} to the {receiver}.
     890             :       efalse = graph()->NewNode(
     891             :           simplified()->StoreField(
     892             :               AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
     893         198 :           receiver, length, efalse, if_false);
     894             : 
     895             :       // Load the last entry from the {elements}.
     896             :       vfalse = efalse = graph()->NewNode(
     897             :           simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(
     898             :               receiver_map->elements_kind())),
     899         198 :           elements, length, efalse, if_false);
     900             : 
     901             :       // Store a hole to the element we just removed from the {receiver}.
     902             :       efalse = graph()->NewNode(
     903             :           simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(
     904             :               GetHoleyElementsKind(receiver_map->elements_kind()))),
     905         264 :           elements, length, jsgraph()->TheHoleConstant(), efalse, if_false);
     906             :     }
     907             : 
     908          66 :     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
     909          66 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
     910             :     Node* value =
     911             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     912          66 :                          vtrue, vfalse, control);
     913             : 
     914             :     // Convert the hole to undefined. Do this last, so that we can optimize
     915             :     // conversion operator via some smart strength reduction in many cases.
     916          66 :     if (IsFastHoleyElementsKind(receiver_map->elements_kind())) {
     917             :       value =
     918          15 :           graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
     919             :     }
     920             : 
     921          66 :     ReplaceWithValue(node, value, effect, control);
     922             :     return Replace(value);
     923             :   }
     924             :   return NoChange();
     925             : }
     926             : 
     927             : // ES6 section 22.1.3.18 Array.prototype.push ( )
     928        4447 : Reduction JSBuiltinReducer::ReduceArrayPush(Node* node) {
     929             :   // We need exactly target, receiver and value parameters.
     930        1642 :   if (node->op()->ValueInputCount() != 3) return NoChange();
     931        1617 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     932        1617 :   Node* effect = NodeProperties::GetEffectInput(node);
     933        1617 :   Node* control = NodeProperties::GetControlInput(node);
     934        1617 :   Node* value = NodeProperties::GetValueInput(node, 2);
     935             :   ZoneHandleSet<Map> receiver_maps;
     936             :   NodeProperties::InferReceiverMapsResult result =
     937        1617 :       NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
     938        1617 :   if (receiver_maps.size() != 1) return NoChange();
     939             :   DCHECK_NE(NodeProperties::kNoReceiverMaps, result);
     940             : 
     941             :   // TODO(turbofan): Relax this to deal with multiple {receiver} maps.
     942             :   Handle<Map> receiver_map = receiver_maps[0];
     943        1490 :   if (CanInlineArrayResizeOperation(receiver_map)) {
     944             :     // Install code dependencies on the {receiver} prototype maps and the
     945             :     // global array protector cell.
     946             :     dependencies()->AssumePropertyCell(factory()->array_protector());
     947         935 :     dependencies()->AssumePrototypeMapsStable(receiver_map);
     948             : 
     949             :     // If the {receiver_maps} information is not reliable, we need
     950             :     // to check that the {receiver} still has one of these maps.
     951         935 :     if (result == NodeProperties::kUnreliableReceiverMaps) {
     952         250 :       if (receiver_map->is_stable()) {
     953           0 :         dependencies()->AssumeMapStable(receiver_map);
     954             :       } else {
     955             :         // TODO(turbofan): This is a potential - yet unlikely - deoptimization
     956             :         // loop, since we might not learn from this deoptimization in baseline
     957             :         // code. We need a way to learn from deoptimizations in optimized to
     958             :         // address these problems.
     959             :         effect = graph()->NewNode(
     960             :             simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps),
     961         500 :             receiver, effect, control);
     962             :       }
     963             :     }
     964             : 
     965             :     // TODO(turbofan): Perform type checks on the {value}. We are not guaranteed
     966             :     // to learn from these checks in case they fail, as the witness (i.e. the
     967             :     // map check from the LoadIC for a.push) might not be executed in baseline
     968             :     // code (after we stored the value in the builtin and thereby changed the
     969             :     // elements kind of a) before be decide to optimize this function again. We
     970             :     // currently don't have a proper way to deal with this; the proper solution
     971             :     // here is to learn on deopt, i.e. disable Array.prototype.push inlining
     972             :     // for this function.
     973         935 :     if (IsFastSmiElementsKind(receiver_map->elements_kind())) {
     974             :       value = effect =
     975         504 :           graph()->NewNode(simplified()->CheckSmi(), value, effect, control);
     976         431 :     } else if (IsFastDoubleElementsKind(receiver_map->elements_kind())) {
     977             :       value = effect =
     978          41 :           graph()->NewNode(simplified()->CheckNumber(), value, effect, control);
     979             :       // Make sure we do not store signaling NaNs into double arrays.
     980          41 :       value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
     981             :     }
     982             : 
     983             :     // Load the "length" property of the {receiver}.
     984             :     Node* length = effect = graph()->NewNode(
     985             :         simplified()->LoadField(
     986             :             AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
     987        2805 :         receiver, effect, control);
     988             : 
     989             :     // Load the elements backing store of the {receiver}.
     990             :     Node* elements = effect = graph()->NewNode(
     991             :         simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
     992        2805 :         effect, control);
     993             : 
     994             :     // TODO(turbofan): Check if we need to grow the {elements} backing store.
     995             :     // This will deopt if we cannot grow the array further, and we currently
     996             :     // don't necessarily learn from it. See the comment on the value type check
     997             :     // above.
     998             :     GrowFastElementsFlags flags = GrowFastElementsFlag::kArrayObject;
     999         935 :     if (IsFastDoubleElementsKind(receiver_map->elements_kind())) {
    1000             :       flags |= GrowFastElementsFlag::kDoubleElements;
    1001             :     }
    1002             :     elements = effect =
    1003             :         graph()->NewNode(simplified()->MaybeGrowFastElements(flags), receiver,
    1004         935 :                          elements, length, length, effect, control);
    1005             : 
    1006             :     // Append the value to the {elements}.
    1007             :     effect = graph()->NewNode(
    1008             :         simplified()->StoreElement(
    1009             :             AccessBuilder::ForFixedArrayElement(receiver_map->elements_kind())),
    1010        2805 :         elements, length, value, effect, control);
    1011             : 
    1012             :     // Return the new length of the {receiver}.
    1013             :     value = graph()->NewNode(simplified()->NumberAdd(), length,
    1014        1870 :                              jsgraph()->OneConstant());
    1015             : 
    1016         935 :     ReplaceWithValue(node, value, effect, control);
    1017             :     return Replace(value);
    1018             :   }
    1019             :   return NoChange();
    1020             : }
    1021             : 
    1022             : namespace {
    1023             : 
    1024         135 : bool HasInstanceTypeWitness(Node* receiver, Node* effect,
    1025             :                             InstanceType instance_type) {
    1026         310 :   for (Node* dominator = effect;;) {
    1027         286 :     if (dominator->opcode() == IrOpcode::kCheckMaps &&
    1028         131 :         NodeProperties::IsSame(dominator->InputAt(0), receiver)) {
    1029             :       ZoneHandleSet<Map> const& maps =
    1030         131 :           CheckMapsParametersOf(dominator->op()).maps();
    1031             :       // Check if all maps have the given {instance_type}.
    1032         604 :       for (size_t i = 0; i < maps.size(); ++i) {
    1033         171 :         if (maps[i]->instance_type() != instance_type) return false;
    1034             :       }
    1035             :       return true;
    1036             :     }
    1037             :     // The instance type doesn't change for JSReceiver values, so we
    1038             :     // don't need to pay attention to potentially side-effecting nodes
    1039             :     // here. Strings and internal structures like FixedArray and
    1040             :     // FixedDoubleArray are weird here, but we don't use this function then.
    1041             :     DCHECK_LE(FIRST_JS_RECEIVER_TYPE, instance_type);
    1042             :     DCHECK_EQ(1, dominator->op()->EffectOutputCount());
    1043          24 :     if (dominator->op()->EffectInputCount() != 1) {
    1044             :       // Didn't find any appropriate CheckMaps node.
    1045             :       return false;
    1046             :     }
    1047          20 :     dominator = NodeProperties::GetEffectInput(dominator);
    1048          20 :   }
    1049             : }
    1050             : 
    1051             : }  // namespace
    1052             : 
    1053             : // ES6 section 20.3.3.1 Date.now ( )
    1054           8 : Reduction JSBuiltinReducer::ReduceDateNow(Node* node) {
    1055           8 :   NodeProperties::RemoveValueInputs(node);
    1056             :   NodeProperties::ChangeOp(
    1057           8 :       node, javascript()->CallRuntime(Runtime::kDateCurrentTime));
    1058           8 :   return Changed(node);
    1059             : }
    1060             : 
    1061             : // ES6 section 20.3.4.10 Date.prototype.getTime ( )
    1062           4 : Reduction JSBuiltinReducer::ReduceDateGetTime(Node* node) {
    1063           4 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1064           4 :   Node* effect = NodeProperties::GetEffectInput(node);
    1065           4 :   Node* control = NodeProperties::GetControlInput(node);
    1066           4 :   if (HasInstanceTypeWitness(receiver, effect, JS_DATE_TYPE)) {
    1067             :     Node* value = effect = graph()->NewNode(
    1068             :         simplified()->LoadField(AccessBuilder::ForJSDateValue()), receiver,
    1069           0 :         effect, control);
    1070           0 :     ReplaceWithValue(node, value, effect, control);
    1071             :     return Replace(value);
    1072             :   }
    1073             :   return NoChange();
    1074             : }
    1075             : 
    1076             : // ES6 section 18.2.2 isFinite ( number )
    1077          51 : Reduction JSBuiltinReducer::ReduceGlobalIsFinite(Node* node) {
    1078             :   JSCallReduction r(node);
    1079          51 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1080             :     // isFinite(a:plain-primitive) -> NumberEqual(a', a')
    1081             :     // where a' = NumberSubtract(ToNumber(a), ToNumber(a))
    1082          36 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1083          36 :     Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, input);
    1084          36 :     Node* value = graph()->NewNode(simplified()->NumberEqual(), diff, diff);
    1085             :     return Replace(value);
    1086             :   }
    1087             :   return NoChange();
    1088             : }
    1089             : 
    1090             : // ES6 section 18.2.3 isNaN ( number )
    1091       21097 : Reduction JSBuiltinReducer::ReduceGlobalIsNaN(Node* node) {
    1092             :   JSCallReduction r(node);
    1093       21097 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1094             :     // isNaN(a:plain-primitive) -> BooleanNot(NumberEqual(a', a'))
    1095             :     // where a' = ToNumber(a)
    1096        8617 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1097        8617 :     Node* check = graph()->NewNode(simplified()->NumberEqual(), input, input);
    1098        8617 :     Node* value = graph()->NewNode(simplified()->BooleanNot(), check);
    1099             :     return Replace(value);
    1100             :   }
    1101             :   return NoChange();
    1102             : }
    1103             : 
    1104             : // ES6 section 20.2.2.1 Math.abs ( x )
    1105         401 : Reduction JSBuiltinReducer::ReduceMathAbs(Node* node) {
    1106             :   JSCallReduction r(node);
    1107         401 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1108             :     // Math.abs(a:plain-primitive) -> NumberAbs(ToNumber(a))
    1109         320 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1110         320 :     Node* value = graph()->NewNode(simplified()->NumberAbs(), input);
    1111             :     return Replace(value);
    1112             :   }
    1113             :   return NoChange();
    1114             : }
    1115             : 
    1116             : // ES6 section 20.2.2.2 Math.acos ( x )
    1117          14 : Reduction JSBuiltinReducer::ReduceMathAcos(Node* node) {
    1118             :   JSCallReduction r(node);
    1119          14 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1120             :     // Math.acos(a:plain-primitive) -> NumberAcos(ToNumber(a))
    1121          14 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1122          14 :     Node* value = graph()->NewNode(simplified()->NumberAcos(), input);
    1123             :     return Replace(value);
    1124             :   }
    1125             :   return NoChange();
    1126             : }
    1127             : 
    1128             : // ES6 section 20.2.2.3 Math.acosh ( x )
    1129          13 : Reduction JSBuiltinReducer::ReduceMathAcosh(Node* node) {
    1130             :   JSCallReduction r(node);
    1131          13 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1132             :     // Math.acosh(a:plain-primitive) -> NumberAcosh(ToNumber(a))
    1133          13 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1134          13 :     Node* value = graph()->NewNode(simplified()->NumberAcosh(), input);
    1135             :     return Replace(value);
    1136             :   }
    1137             :   return NoChange();
    1138             : }
    1139             : 
    1140             : // ES6 section 20.2.2.4 Math.asin ( x )
    1141          14 : Reduction JSBuiltinReducer::ReduceMathAsin(Node* node) {
    1142             :   JSCallReduction r(node);
    1143          14 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1144             :     // Math.asin(a:plain-primitive) -> NumberAsin(ToNumber(a))
    1145          14 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1146          14 :     Node* value = graph()->NewNode(simplified()->NumberAsin(), input);
    1147             :     return Replace(value);
    1148             :   }
    1149             :   return NoChange();
    1150             : }
    1151             : 
    1152             : // ES6 section 20.2.2.5 Math.asinh ( x )
    1153          13 : Reduction JSBuiltinReducer::ReduceMathAsinh(Node* node) {
    1154             :   JSCallReduction r(node);
    1155          13 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1156             :     // Math.asinh(a:plain-primitive) -> NumberAsinh(ToNumber(a))
    1157          13 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1158          13 :     Node* value = graph()->NewNode(simplified()->NumberAsinh(), input);
    1159             :     return Replace(value);
    1160             :   }
    1161             :   return NoChange();
    1162             : }
    1163             : 
    1164             : // ES6 section 20.2.2.6 Math.atan ( x )
    1165          14 : Reduction JSBuiltinReducer::ReduceMathAtan(Node* node) {
    1166             :   JSCallReduction r(node);
    1167          14 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1168             :     // Math.atan(a:plain-primitive) -> NumberAtan(ToNumber(a))
    1169          14 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1170          14 :     Node* value = graph()->NewNode(simplified()->NumberAtan(), input);
    1171             :     return Replace(value);
    1172             :   }
    1173             :   return NoChange();
    1174             : }
    1175             : 
    1176             : // ES6 section 20.2.2.7 Math.atanh ( x )
    1177          13 : Reduction JSBuiltinReducer::ReduceMathAtanh(Node* node) {
    1178             :   JSCallReduction r(node);
    1179          13 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1180             :     // Math.atanh(a:plain-primitive) -> NumberAtanh(ToNumber(a))
    1181          13 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1182          13 :     Node* value = graph()->NewNode(simplified()->NumberAtanh(), input);
    1183             :     return Replace(value);
    1184             :   }
    1185             :   return NoChange();
    1186             : }
    1187             : 
    1188             : // ES6 section 20.2.2.8 Math.atan2 ( y, x )
    1189         160 : Reduction JSBuiltinReducer::ReduceMathAtan2(Node* node) {
    1190             :   JSCallReduction r(node);
    1191         160 :   if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
    1192             :     // Math.atan2(a:plain-primitive,
    1193             :     //            b:plain-primitive) -> NumberAtan2(ToNumber(a),
    1194             :     //                                              ToNumber(b))
    1195         160 :     Node* left = ToNumber(r.left());
    1196         160 :     Node* right = ToNumber(r.right());
    1197         160 :     Node* value = graph()->NewNode(simplified()->NumberAtan2(), left, right);
    1198             :     return Replace(value);
    1199             :   }
    1200             :   return NoChange();
    1201             : }
    1202             : 
    1203             : // ES6 section 20.2.2.10 Math.ceil ( x )
    1204        7636 : Reduction JSBuiltinReducer::ReduceMathCeil(Node* node) {
    1205             :   JSCallReduction r(node);
    1206        7636 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1207             :     // Math.ceil(a:plain-primitive) -> NumberCeil(ToNumber(a))
    1208        5736 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1209        5736 :     Node* value = graph()->NewNode(simplified()->NumberCeil(), input);
    1210             :     return Replace(value);
    1211             :   }
    1212             :   return NoChange();
    1213             : }
    1214             : 
    1215             : // ES6 section 20.2.2.11 Math.clz32 ( x )
    1216          59 : Reduction JSBuiltinReducer::ReduceMathClz32(Node* node) {
    1217             :   JSCallReduction r(node);
    1218          59 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1219             :     // Math.clz32(a:plain-primitive) -> NumberClz32(ToUint32(a))
    1220          30 :     Node* input = ToUint32(r.GetJSCallInput(0));
    1221          30 :     Node* value = graph()->NewNode(simplified()->NumberClz32(), input);
    1222             :     return Replace(value);
    1223             :   }
    1224             :   return NoChange();
    1225             : }
    1226             : 
    1227             : // ES6 section 20.2.2.12 Math.cos ( x )
    1228          78 : Reduction JSBuiltinReducer::ReduceMathCos(Node* node) {
    1229             :   JSCallReduction r(node);
    1230          78 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1231             :     // Math.cos(a:plain-primitive) -> NumberCos(ToNumber(a))
    1232          57 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1233          57 :     Node* value = graph()->NewNode(simplified()->NumberCos(), input);
    1234             :     return Replace(value);
    1235             :   }
    1236             :   return NoChange();
    1237             : }
    1238             : 
    1239             : // ES6 section 20.2.2.13 Math.cosh ( x )
    1240          22 : Reduction JSBuiltinReducer::ReduceMathCosh(Node* node) {
    1241             :   JSCallReduction r(node);
    1242          22 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1243             :     // Math.cosh(a:plain-primitive) -> NumberCosh(ToNumber(a))
    1244          22 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1245          22 :     Node* value = graph()->NewNode(simplified()->NumberCosh(), input);
    1246             :     return Replace(value);
    1247             :   }
    1248             :   return NoChange();
    1249             : }
    1250             : 
    1251             : // ES6 section 20.2.2.14 Math.exp ( x )
    1252          57 : Reduction JSBuiltinReducer::ReduceMathExp(Node* node) {
    1253             :   JSCallReduction r(node);
    1254          57 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1255             :     // Math.exp(a:plain-primitive) -> NumberExp(ToNumber(a))
    1256          42 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1257          42 :     Node* value = graph()->NewNode(simplified()->NumberExp(), input);
    1258             :     return Replace(value);
    1259             :   }
    1260             :   return NoChange();
    1261             : }
    1262             : 
    1263             : // ES6 section 20.2.2.15 Math.expm1 ( x )
    1264           0 : Reduction JSBuiltinReducer::ReduceMathExpm1(Node* node) {
    1265             :   JSCallReduction r(node);
    1266           0 :   if (r.InputsMatchOne(Type::Number())) {
    1267             :     // Math.expm1(a:number) -> NumberExpm1(a)
    1268           0 :     Node* value = graph()->NewNode(simplified()->NumberExpm1(), r.left());
    1269             :     return Replace(value);
    1270             :   }
    1271             :   return NoChange();
    1272             : }
    1273             : 
    1274             : // ES6 section 20.2.2.16 Math.floor ( x )
    1275       28920 : Reduction JSBuiltinReducer::ReduceMathFloor(Node* node) {
    1276             :   JSCallReduction r(node);
    1277       28920 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1278             :     // Math.floor(a:plain-primitive) -> NumberFloor(ToNumber(a))
    1279        9355 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1280        9355 :     Node* value = graph()->NewNode(simplified()->NumberFloor(), input);
    1281             :     return Replace(value);
    1282             :   }
    1283             :   return NoChange();
    1284             : }
    1285             : 
    1286             : // ES6 section 20.2.2.17 Math.fround ( x )
    1287        1113 : Reduction JSBuiltinReducer::ReduceMathFround(Node* node) {
    1288             :   JSCallReduction r(node);
    1289        1113 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1290             :     // Math.fround(a:plain-primitive) -> NumberFround(ToNumber(a))
    1291         672 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1292         672 :     Node* value = graph()->NewNode(simplified()->NumberFround(), input);
    1293             :     return Replace(value);
    1294             :   }
    1295             :   return NoChange();
    1296             : }
    1297             : 
    1298             : // ES6 section 20.2.2.19 Math.imul ( x, y )
    1299         152 : Reduction JSBuiltinReducer::ReduceMathImul(Node* node) {
    1300             :   JSCallReduction r(node);
    1301         152 :   if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
    1302             :     // Math.imul(a:plain-primitive,
    1303             :     //           b:plain-primitive) -> NumberImul(ToUint32(a),
    1304             :     //                                            ToUint32(b))
    1305          57 :     Node* left = ToUint32(r.left());
    1306          57 :     Node* right = ToUint32(r.right());
    1307          57 :     Node* value = graph()->NewNode(simplified()->NumberImul(), left, right);
    1308             :     return Replace(value);
    1309             :   }
    1310             :   return NoChange();
    1311             : }
    1312             : 
    1313             : // ES6 section 20.2.2.20 Math.log ( x )
    1314         151 : Reduction JSBuiltinReducer::ReduceMathLog(Node* node) {
    1315             :   JSCallReduction r(node);
    1316         151 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1317             :     // Math.log(a:plain-primitive) -> NumberLog(ToNumber(a))
    1318         144 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1319         144 :     Node* value = graph()->NewNode(simplified()->NumberLog(), input);
    1320             :     return Replace(value);
    1321             :   }
    1322             :   return NoChange();
    1323             : }
    1324             : 
    1325             : // ES6 section 20.2.2.21 Math.log1p ( x )
    1326          13 : Reduction JSBuiltinReducer::ReduceMathLog1p(Node* node) {
    1327             :   JSCallReduction r(node);
    1328          13 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1329             :     // Math.log1p(a:plain-primitive) -> NumberLog1p(ToNumber(a))
    1330          13 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1331          13 :     Node* value = graph()->NewNode(simplified()->NumberLog1p(), input);
    1332             :     return Replace(value);
    1333             :   }
    1334             :   return NoChange();
    1335             : }
    1336             : 
    1337             : // ES6 section 20.2.2.22 Math.log10 ( x )
    1338           0 : Reduction JSBuiltinReducer::ReduceMathLog10(Node* node) {
    1339             :   JSCallReduction r(node);
    1340           0 :   if (r.InputsMatchOne(Type::Number())) {
    1341             :     // Math.log10(a:number) -> NumberLog10(a)
    1342           0 :     Node* value = graph()->NewNode(simplified()->NumberLog10(), r.left());
    1343             :     return Replace(value);
    1344             :   }
    1345             :   return NoChange();
    1346             : }
    1347             : 
    1348             : // ES6 section 20.2.2.23 Math.log2 ( x )
    1349           0 : Reduction JSBuiltinReducer::ReduceMathLog2(Node* node) {
    1350             :   JSCallReduction r(node);
    1351           0 :   if (r.InputsMatchOne(Type::Number())) {
    1352             :     // Math.log2(a:number) -> NumberLog(a)
    1353           0 :     Node* value = graph()->NewNode(simplified()->NumberLog2(), r.left());
    1354             :     return Replace(value);
    1355             :   }
    1356             :   return NoChange();
    1357             : }
    1358             : 
    1359             : // ES6 section 20.2.2.24 Math.max ( value1, value2, ...values )
    1360         338 : Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
    1361             :   JSCallReduction r(node);
    1362         337 :   if (r.InputsMatchZero()) {
    1363             :     // Math.max() -> -Infinity
    1364           1 :     return Replace(jsgraph()->Constant(-V8_INFINITY));
    1365             :   }
    1366         336 :   if (r.InputsMatchAll(Type::PlainPrimitive())) {
    1367             :     // Math.max(a:plain-primitive, b:plain-primitive, ...)
    1368         233 :     Node* value = ToNumber(r.GetJSCallInput(0));
    1369         908 :     for (int i = 1; i < r.GetJSCallArity(); i++) {
    1370         221 :       Node* input = ToNumber(r.GetJSCallInput(i));
    1371         221 :       value = graph()->NewNode(simplified()->NumberMax(), value, input);
    1372             :     }
    1373             :     return Replace(value);
    1374             :   }
    1375             :   return NoChange();
    1376             : }
    1377             : 
    1378             : // ES6 section 20.2.2.25 Math.min ( value1, value2, ...values )
    1379         307 : Reduction JSBuiltinReducer::ReduceMathMin(Node* node) {
    1380             :   JSCallReduction r(node);
    1381         306 :   if (r.InputsMatchZero()) {
    1382             :     // Math.min() -> Infinity
    1383           1 :     return Replace(jsgraph()->Constant(V8_INFINITY));
    1384             :   }
    1385         305 :   if (r.InputsMatchAll(Type::PlainPrimitive())) {
    1386             :     // Math.min(a:plain-primitive, b:plain-primitive, ...)
    1387         268 :     Node* value = ToNumber(r.GetJSCallInput(0));
    1388        1048 :     for (int i = 1; i < r.GetJSCallArity(); i++) {
    1389         256 :       Node* input = ToNumber(r.GetJSCallInput(i));
    1390         256 :       value = graph()->NewNode(simplified()->NumberMin(), value, input);
    1391             :     }
    1392             :     return Replace(value);
    1393             :   }
    1394             :   return NoChange();
    1395             : }
    1396             : 
    1397             : // ES6 section 20.2.2.26 Math.pow ( x, y )
    1398        1181 : Reduction JSBuiltinReducer::ReduceMathPow(Node* node) {
    1399             :   JSCallReduction r(node);
    1400        1181 :   if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
    1401             :     // Math.pow(a:plain-primitive,
    1402             :     //          b:plain-primitive) -> NumberPow(ToNumber(a), ToNumber(b))
    1403        1139 :     Node* left = ToNumber(r.left());
    1404        1139 :     Node* right = ToNumber(r.right());
    1405        1139 :     Node* value = graph()->NewNode(simplified()->NumberPow(), left, right);
    1406             :     return Replace(value);
    1407             :   }
    1408             :   return NoChange();
    1409             : }
    1410             : 
    1411             : // ES6 section 20.2.2.28 Math.round ( x )
    1412        1587 : Reduction JSBuiltinReducer::ReduceMathRound(Node* node) {
    1413             :   JSCallReduction r(node);
    1414        1587 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1415             :     // Math.round(a:plain-primitive) -> NumberRound(ToNumber(a))
    1416         106 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1417         106 :     Node* value = graph()->NewNode(simplified()->NumberRound(), input);
    1418             :     return Replace(value);
    1419             :   }
    1420             :   return NoChange();
    1421             : }
    1422             : 
    1423             : // ES6 section 20.2.2.9 Math.cbrt ( x )
    1424           0 : Reduction JSBuiltinReducer::ReduceMathCbrt(Node* node) {
    1425             :   JSCallReduction r(node);
    1426           0 :   if (r.InputsMatchOne(Type::Number())) {
    1427             :     // Math.cbrt(a:number) -> NumberCbrt(a)
    1428           0 :     Node* value = graph()->NewNode(simplified()->NumberCbrt(), r.left());
    1429             :     return Replace(value);
    1430             :   }
    1431             :   return NoChange();
    1432             : }
    1433             : 
    1434             : // ES6 section 20.2.2.29 Math.sign ( x )
    1435          34 : Reduction JSBuiltinReducer::ReduceMathSign(Node* node) {
    1436             :   JSCallReduction r(node);
    1437          34 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1438             :     // Math.sign(a:plain-primitive) -> NumberSign(ToNumber(a))
    1439          34 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1440          34 :     Node* value = graph()->NewNode(simplified()->NumberSign(), input);
    1441             :     return Replace(value);
    1442             :   }
    1443             :   return NoChange();
    1444             : }
    1445             : 
    1446             : // ES6 section 20.2.2.30 Math.sin ( x )
    1447         102 : Reduction JSBuiltinReducer::ReduceMathSin(Node* node) {
    1448             :   JSCallReduction r(node);
    1449         102 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1450             :     // Math.sin(a:plain-primitive) -> NumberSin(ToNumber(a))
    1451          92 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1452          92 :     Node* value = graph()->NewNode(simplified()->NumberSin(), input);
    1453             :     return Replace(value);
    1454             :   }
    1455             :   return NoChange();
    1456             : }
    1457             : 
    1458             : // ES6 section 20.2.2.31 Math.sinh ( x )
    1459          22 : Reduction JSBuiltinReducer::ReduceMathSinh(Node* node) {
    1460             :   JSCallReduction r(node);
    1461          22 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1462             :     // Math.sinh(a:plain-primitive) -> NumberSinh(ToNumber(a))
    1463          22 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1464          22 :     Node* value = graph()->NewNode(simplified()->NumberSinh(), input);
    1465             :     return Replace(value);
    1466             :   }
    1467             :   return NoChange();
    1468             : }
    1469             : 
    1470             : // ES6 section 20.2.2.32 Math.sqrt ( x )
    1471         103 : Reduction JSBuiltinReducer::ReduceMathSqrt(Node* node) {
    1472             :   JSCallReduction r(node);
    1473         103 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1474             :     // Math.sqrt(a:plain-primitive) -> NumberSqrt(ToNumber(a))
    1475          72 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1476          72 :     Node* value = graph()->NewNode(simplified()->NumberSqrt(), input);
    1477             :     return Replace(value);
    1478             :   }
    1479             :   return NoChange();
    1480             : }
    1481             : 
    1482             : // ES6 section 20.2.2.33 Math.tan ( x )
    1483          57 : Reduction JSBuiltinReducer::ReduceMathTan(Node* node) {
    1484             :   JSCallReduction r(node);
    1485          57 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1486             :     // Math.tan(a:plain-primitive) -> NumberTan(ToNumber(a))
    1487          21 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1488          21 :     Node* value = graph()->NewNode(simplified()->NumberTan(), input);
    1489             :     return Replace(value);
    1490             :   }
    1491             :   return NoChange();
    1492             : }
    1493             : 
    1494             : // ES6 section 20.2.2.34 Math.tanh ( x )
    1495          22 : Reduction JSBuiltinReducer::ReduceMathTanh(Node* node) {
    1496             :   JSCallReduction r(node);
    1497          22 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1498             :     // Math.tanh(a:plain-primitive) -> NumberTanh(ToNumber(a))
    1499          22 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1500          22 :     Node* value = graph()->NewNode(simplified()->NumberTanh(), input);
    1501             :     return Replace(value);
    1502             :   }
    1503             :   return NoChange();
    1504             : }
    1505             : 
    1506             : // ES6 section 20.2.2.35 Math.trunc ( x )
    1507        7260 : Reduction JSBuiltinReducer::ReduceMathTrunc(Node* node) {
    1508             :   JSCallReduction r(node);
    1509        7260 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1510             :     // Math.trunc(a:plain-primitive) -> NumberTrunc(ToNumber(a))
    1511        1395 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1512        1395 :     Node* value = graph()->NewNode(simplified()->NumberTrunc(), input);
    1513             :     return Replace(value);
    1514             :   }
    1515             :   return NoChange();
    1516             : }
    1517             : 
    1518             : // ES6 section 20.1.2.2 Number.isFinite ( number )
    1519          19 : Reduction JSBuiltinReducer::ReduceNumberIsFinite(Node* node) {
    1520             :   JSCallReduction r(node);
    1521          19 :   if (r.InputsMatchOne(Type::Number())) {
    1522             :     // Number.isFinite(a:number) -> NumberEqual(a', a')
    1523             :     // where a' = NumberSubtract(a, a)
    1524             :     Node* input = r.GetJSCallInput(0);
    1525          19 :     Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, input);
    1526          19 :     Node* value = graph()->NewNode(simplified()->NumberEqual(), diff, diff);
    1527             :     return Replace(value);
    1528             :   }
    1529             :   return NoChange();
    1530             : }
    1531             : 
    1532             : // ES6 section 20.1.2.3 Number.isInteger ( number )
    1533          38 : Reduction JSBuiltinReducer::ReduceNumberIsInteger(Node* node) {
    1534             :   JSCallReduction r(node);
    1535          19 :   if (r.InputsMatchOne(Type::Number())) {
    1536             :     // Number.isInteger(x:number) -> NumberEqual(NumberSubtract(x, x'), #0)
    1537             :     // where x' = NumberTrunc(x)
    1538             :     Node* input = r.GetJSCallInput(0);
    1539          19 :     Node* trunc = graph()->NewNode(simplified()->NumberTrunc(), input);
    1540          19 :     Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, trunc);
    1541             :     Node* value = graph()->NewNode(simplified()->NumberEqual(), diff,
    1542          38 :                                    jsgraph()->ZeroConstant());
    1543             :     return Replace(value);
    1544             :   }
    1545             :   return NoChange();
    1546             : }
    1547             : 
    1548             : // ES6 section 20.1.2.4 Number.isNaN ( number )
    1549          75 : Reduction JSBuiltinReducer::ReduceNumberIsNaN(Node* node) {
    1550             :   JSCallReduction r(node);
    1551          67 :   if (r.InputsMatchZero()) {
    1552             :     // Number.isNaN() -> #false
    1553           8 :     Node* value = jsgraph()->FalseConstant();
    1554             :     return Replace(value);
    1555             :   }
    1556             :   // Number.isNaN(a:number) -> ObjectIsNaN(a)
    1557             :   Node* input = r.GetJSCallInput(0);
    1558          59 :   Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
    1559             :   return Replace(value);
    1560             : }
    1561             : 
    1562             : // ES6 section 20.1.2.5 Number.isSafeInteger ( number )
    1563          21 : Reduction JSBuiltinReducer::ReduceNumberIsSafeInteger(Node* node) {
    1564             :   JSCallReduction r(node);
    1565          14 :   if (r.InputsMatchOne(type_cache_.kSafeInteger)) {
    1566             :     // Number.isInteger(x:safe-integer) -> #true
    1567           7 :     Node* value = jsgraph()->TrueConstant();
    1568             :     return Replace(value);
    1569             :   }
    1570             :   return NoChange();
    1571             : }
    1572             : 
    1573             : // ES6 section 20.1.2.13 Number.parseInt ( string, radix )
    1574         460 : Reduction JSBuiltinReducer::ReduceNumberParseInt(Node* node) {
    1575             :   JSCallReduction r(node);
    1576        1365 :   if (r.InputsMatchOne(type_cache_.kSafeInteger) ||
    1577             :       r.InputsMatchTwo(type_cache_.kSafeInteger,
    1578         884 :                        type_cache_.kZeroOrUndefined) ||
    1579         424 :       r.InputsMatchTwo(type_cache_.kSafeInteger, type_cache_.kTenOrUndefined)) {
    1580             :     // Number.parseInt(a:safe-integer) -> a
    1581             :     // Number.parseInt(a:safe-integer,b:#0\/undefined) -> a
    1582             :     // Number.parseInt(a:safe-integer,b:#10\/undefined) -> a
    1583             :     Node* value = r.GetJSCallInput(0);
    1584             :     return Replace(value);
    1585             :   }
    1586             :   return NoChange();
    1587             : }
    1588             : 
    1589             : // ES6 section #sec-object.create Object.create(proto, properties)
    1590          21 : Reduction JSBuiltinReducer::ReduceObjectCreate(Node* node) {
    1591             :   // We need exactly target, receiver and value parameters.
    1592          21 :   int arg_count = node->op()->ValueInputCount();
    1593          21 :   if (arg_count != 3) return NoChange();
    1594          21 :   Node* effect = NodeProperties::GetEffectInput(node);
    1595          21 :   Node* control = NodeProperties::GetControlInput(node);
    1596          21 :   Node* prototype = NodeProperties::GetValueInput(node, 2);
    1597             :   Type* prototype_type = NodeProperties::GetType(prototype);
    1598             :   Handle<Map> instance_map;
    1599          21 :   if (!prototype_type->IsHeapConstant()) return NoChange();
    1600             :   Handle<HeapObject> prototype_const =
    1601             :       prototype_type->AsHeapConstant()->Value();
    1602           0 :   if (!prototype_const->IsNull(isolate()) && !prototype_const->IsJSReceiver()) {
    1603             :     return NoChange();
    1604             :   }
    1605           0 :   instance_map = Map::GetObjectCreateMap(prototype_const);
    1606           0 :   Node* properties = jsgraph()->EmptyFixedArrayConstant();
    1607           0 :   if (instance_map->is_dictionary_map()) {
    1608             :     // Allocated an empty NameDictionary as backing store for the properties.
    1609           0 :     Handle<Map> map(isolate()->heap()->hash_table_map(), isolate());
    1610             :     int capacity =
    1611             :         NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
    1612             :     DCHECK(base::bits::IsPowerOfTwo32(capacity));
    1613             :     int length = NameDictionary::EntryToIndex(capacity);
    1614             :     int size = NameDictionary::SizeFor(length);
    1615             : 
    1616             :     effect = graph()->NewNode(
    1617           0 :         common()->BeginRegion(RegionObservability::kNotObservable), effect);
    1618             : 
    1619             :     Node* value = effect =
    1620             :         graph()->NewNode(simplified()->Allocate(Type::Any(), NOT_TENURED),
    1621           0 :                          jsgraph()->Constant(size), effect, control);
    1622             :     effect =
    1623             :         graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
    1624           0 :                          value, jsgraph()->HeapConstant(map), effect, control);
    1625             : 
    1626             :     // Initialize FixedArray fields.
    1627             :     effect = graph()->NewNode(
    1628             :         simplified()->StoreField(AccessBuilder::ForFixedArrayLength()), value,
    1629           0 :         jsgraph()->SmiConstant(length), effect, control);
    1630             :     // Initialize HashTable fields.
    1631             :     effect =
    1632             :         graph()->NewNode(simplified()->StoreField(
    1633             :                              AccessBuilder::ForHashTableBaseNumberOfElements()),
    1634           0 :                          value, jsgraph()->SmiConstant(0), effect, control);
    1635             :     effect = graph()->NewNode(
    1636             :         simplified()->StoreField(
    1637             :             AccessBuilder::ForHashTableBaseNumberOfDeletedElement()),
    1638           0 :         value, jsgraph()->SmiConstant(0), effect, control);
    1639             :     effect = graph()->NewNode(
    1640             :         simplified()->StoreField(AccessBuilder::ForHashTableBaseCapacity()),
    1641           0 :         value, jsgraph()->SmiConstant(capacity), effect, control);
    1642             :     // Initialize Dictionary fields.
    1643           0 :     Node* undefined = jsgraph()->UndefinedConstant();
    1644             :     effect = graph()->NewNode(
    1645             :         simplified()->StoreField(AccessBuilder::ForDictionaryMaxNumberKey()),
    1646           0 :         value, undefined, effect, control);
    1647             :     effect = graph()->NewNode(
    1648             :         simplified()->StoreField(
    1649             :             AccessBuilder::ForDictionaryNextEnumerationIndex()),
    1650             :         value, jsgraph()->SmiConstant(PropertyDetails::kInitialIndex), effect,
    1651           0 :         control);
    1652             :     // Initialize hte Properties fields.
    1653           0 :     for (int index = NameDictionary::kNextEnumerationIndexIndex + 1;
    1654             :          index < length; index++) {
    1655             :       effect = graph()->NewNode(
    1656             :           simplified()->StoreField(
    1657             :               AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier)),
    1658           0 :           value, undefined, effect, control);
    1659             :     }
    1660             :     properties = effect =
    1661           0 :         graph()->NewNode(common()->FinishRegion(), value, effect);
    1662             :   }
    1663             : 
    1664             :   int const instance_size = instance_map->instance_size();
    1665           0 :   if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
    1666             :   dependencies()->AssumeInitialMapCantChange(instance_map);
    1667             : 
    1668             :   // Emit code to allocate the JSObject instance for the given
    1669             :   // {instance_map}.
    1670             :   effect = graph()->NewNode(
    1671           0 :       common()->BeginRegion(RegionObservability::kNotObservable), effect);
    1672             :   Node* value = effect =
    1673             :       graph()->NewNode(simplified()->Allocate(Type::Any(), NOT_TENURED),
    1674           0 :                        jsgraph()->Constant(instance_size), effect, control);
    1675             :   effect =
    1676             :       graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), value,
    1677           0 :                        jsgraph()->HeapConstant(instance_map), effect, control);
    1678             :   effect = graph()->NewNode(
    1679             :       simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
    1680           0 :       properties, effect, control);
    1681             :   effect = graph()->NewNode(
    1682             :       simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
    1683           0 :       jsgraph()->EmptyFixedArrayConstant(), effect, control);
    1684             :   // Initialize Object fields.
    1685           0 :   Node* undefined = jsgraph()->UndefinedConstant();
    1686           0 :   for (int offset = JSObject::kHeaderSize; offset < instance_size;
    1687             :        offset += kPointerSize) {
    1688             :     effect = graph()->NewNode(
    1689             :         simplified()->StoreField(
    1690             :             AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier)),
    1691           0 :         value, undefined, effect, control);
    1692             :   }
    1693           0 :   value = effect = graph()->NewNode(common()->FinishRegion(), value, effect);
    1694             : 
    1695             :   // replace it
    1696           0 :   ReplaceWithValue(node, value, effect, control);
    1697             :   return Replace(value);
    1698             : }
    1699             : 
    1700             : // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
    1701         732 : Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) {
    1702             :   JSCallReduction r(node);
    1703         732 :   if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1704             :     // String.fromCharCode(a:plain-primitive) -> StringFromCharCode(a)
    1705         706 :     Node* input = ToNumber(r.GetJSCallInput(0));
    1706         706 :     Node* value = graph()->NewNode(simplified()->StringFromCharCode(), input);
    1707             :     return Replace(value);
    1708             :   }
    1709             :   return NoChange();
    1710             : }
    1711             : 
    1712             : namespace {
    1713             : 
    1714         554 : Node* GetStringWitness(Node* node) {
    1715         554 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1716             :   Type* receiver_type = NodeProperties::GetType(receiver);
    1717         554 :   Node* effect = NodeProperties::GetEffectInput(node);
    1718         554 :   if (receiver_type->Is(Type::String())) return receiver;
    1719             :   // Check if the {node} is dominated by a CheckString renaming for
    1720             :   // it's {receiver}, and if so use that renaming as {receiver} for
    1721             :   // the lowering below.
    1722         341 :   for (Node* dominator = effect;;) {
    1723         424 :     if (dominator->opcode() == IrOpcode::kCheckString &&
    1724         169 :         NodeProperties::IsSame(dominator->InputAt(0), receiver)) {
    1725             :       return dominator;
    1726             :     }
    1727          86 :     if (dominator->op()->EffectInputCount() != 1) {
    1728             :       // Didn't find any appropriate CheckString node.
    1729             :       return nullptr;
    1730             :     }
    1731          78 :     dominator = NodeProperties::GetEffectInput(dominator);
    1732          78 :   }
    1733             : }
    1734             : 
    1735             : }  // namespace
    1736             : 
    1737             : // ES6 section 21.1.3.1 String.prototype.charAt ( pos )
    1738         188 : Reduction JSBuiltinReducer::ReduceStringCharAt(Node* node) {
    1739             :   // We need at least target, receiver and index parameters.
    1740         214 :   if (node->op()->ValueInputCount() >= 3) {
    1741         107 :     Node* index = NodeProperties::GetValueInput(node, 2);
    1742             :     Type* index_type = NodeProperties::GetType(index);
    1743         107 :     Node* effect = NodeProperties::GetEffectInput(node);
    1744         107 :     Node* control = NodeProperties::GetControlInput(node);
    1745             : 
    1746         107 :     if (index_type->Is(Type::Integral32OrMinusZeroOrNaN())) {
    1747          81 :       if (Node* receiver = GetStringWitness(node)) {
    1748          81 :         if (!index_type->Is(Type::Unsigned32())) {
    1749             :           // Map -0 and NaN to 0 (as per ToInteger), and the values in
    1750             :           // the [-2^31,-1] range to the [2^31,2^32-1] range, which will
    1751             :           // be considered out-of-bounds as well, because of the maximal
    1752             :           // String length limit in V8.
    1753             :           STATIC_ASSERT(String::kMaxLength <= kMaxInt);
    1754           4 :           index = graph()->NewNode(simplified()->NumberToUint32(), index);
    1755             :         }
    1756             : 
    1757             :         // Determine the {receiver} length.
    1758             :         Node* receiver_length = effect = graph()->NewNode(
    1759             :             simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
    1760         243 :             effect, control);
    1761             : 
    1762             :         // Check if {index} is less than {receiver} length.
    1763             :         Node* check = graph()->NewNode(simplified()->NumberLessThan(), index,
    1764          81 :                                        receiver_length);
    1765             :         Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1766          81 :                                         check, control);
    1767             : 
    1768             :         // Return the character from the {receiver} as single character string.
    1769          81 :         Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1770             :         Node* vtrue = graph()->NewNode(simplified()->StringCharAt(), receiver,
    1771          81 :                                        index, if_true);
    1772             : 
    1773             :         // Return the empty string otherwise.
    1774          81 :         Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1775          81 :         Node* vfalse = jsgraph()->EmptyStringConstant();
    1776             : 
    1777          81 :         control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1778             :         Node* value =
    1779             :             graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    1780          81 :                              vtrue, vfalse, control);
    1781             : 
    1782          81 :         ReplaceWithValue(node, value, effect, control);
    1783             :         return Replace(value);
    1784             :       }
    1785             :     }
    1786             :   }
    1787             : 
    1788             :   return NoChange();
    1789             : }
    1790             : 
    1791             : // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
    1792         558 : Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) {
    1793             :   // We need at least target, receiver and index parameters.
    1794         618 :   if (node->op()->ValueInputCount() >= 3) {
    1795         309 :     Node* index = NodeProperties::GetValueInput(node, 2);
    1796             :     Type* index_type = NodeProperties::GetType(index);
    1797         309 :     Node* effect = NodeProperties::GetEffectInput(node);
    1798         309 :     Node* control = NodeProperties::GetControlInput(node);
    1799             : 
    1800         309 :     if (index_type->Is(Type::Integral32OrMinusZeroOrNaN())) {
    1801         252 :       if (Node* receiver = GetStringWitness(node)) {
    1802         249 :         if (!index_type->Is(Type::Unsigned32())) {
    1803             :           // Map -0 and NaN to 0 (as per ToInteger), and the values in
    1804             :           // the [-2^31,-1] range to the [2^31,2^32-1] range, which will
    1805             :           // be considered out-of-bounds as well, because of the maximal
    1806             :           // String length limit in V8.
    1807             :           STATIC_ASSERT(String::kMaxLength <= kMaxInt);
    1808           4 :           index = graph()->NewNode(simplified()->NumberToUint32(), index);
    1809             :         }
    1810             : 
    1811             :         // Determine the {receiver} length.
    1812             :         Node* receiver_length = effect = graph()->NewNode(
    1813             :             simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
    1814         747 :             effect, control);
    1815             : 
    1816             :         // Check if {index} is less than {receiver} length.
    1817             :         Node* check = graph()->NewNode(simplified()->NumberLessThan(), index,
    1818         249 :                                        receiver_length);
    1819             :         Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1820         249 :                                         check, control);
    1821             : 
    1822             :         // Load the character from the {receiver}.
    1823         249 :         Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1824             :         Node* vtrue = graph()->NewNode(simplified()->StringCharCodeAt(),
    1825         249 :                                        receiver, index, if_true);
    1826             : 
    1827             :         // Return NaN otherwise.
    1828         249 :         Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1829         249 :         Node* vfalse = jsgraph()->NaNConstant();
    1830             : 
    1831         249 :         control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1832             :         Node* value =
    1833             :             graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    1834         249 :                              vtrue, vfalse, control);
    1835             : 
    1836         249 :         ReplaceWithValue(node, value, effect, control);
    1837             :         return Replace(value);
    1838             :       }
    1839             :     }
    1840             :   }
    1841             : 
    1842             :   return NoChange();
    1843             : }
    1844             : 
    1845             : // ES6 String.prototype.concat(...args)
    1846             : // #sec-string.prototype.concat
    1847           1 : Reduction JSBuiltinReducer::ReduceStringConcat(Node* node) {
    1848           1 :   if (Node* receiver = GetStringWitness(node)) {
    1849             :     JSCallReduction r(node);
    1850           1 :     if (r.InputsMatchOne(Type::PlainPrimitive())) {
    1851             :       // String.prototype.concat(lhs:string, rhs:plain-primitive)
    1852             :       //   -> Call[StringAddStub](lhs, rhs)
    1853           0 :       StringAddFlags flags = r.InputsMatchOne(Type::String())
    1854             :                                  ? STRING_ADD_CHECK_NONE
    1855           0 :                                  : STRING_ADD_CONVERT_RIGHT;
    1856             :       // TODO(turbofan): Massage the FrameState of the {node} here once we
    1857             :       // have an artificial builtin frame type, so that it looks like the
    1858             :       // exception from StringAdd overflow came from String.prototype.concat
    1859             :       // builtin instead of the calling function.
    1860             :       Callable const callable =
    1861           0 :           CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
    1862             :       CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    1863             :           isolate(), graph()->zone(), callable.descriptor(), 0,
    1864             :           CallDescriptor::kNeedsFrameState,
    1865           0 :           Operator::kNoDeopt | Operator::kNoWrite);
    1866           0 :       node->ReplaceInput(0, jsgraph()->HeapConstant(callable.code()));
    1867           0 :       node->ReplaceInput(1, receiver);
    1868           0 :       NodeProperties::ChangeOp(node, common()->Call(desc));
    1869             :       return Changed(node);
    1870             :     }
    1871             :   }
    1872             : 
    1873             :   return NoChange();
    1874             : }
    1875             : 
    1876             : // ES6 String.prototype.indexOf(searchString [, position])
    1877             : // #sec-string.prototype.indexof
    1878         458 : Reduction JSBuiltinReducer::ReduceStringIndexOf(Node* node) {
    1879             :   // We need at least target, receiver and search_string parameters.
    1880         346 :   if (node->op()->ValueInputCount() >= 3) {
    1881         173 :     Node* search_string = NodeProperties::GetValueInput(node, 2);
    1882             :     Type* search_string_type = NodeProperties::GetType(search_string);
    1883         173 :     Node* position = (node->op()->ValueInputCount() >= 4)
    1884             :                          ? NodeProperties::GetValueInput(node, 3)
    1885         285 :                          : jsgraph()->ZeroConstant();
    1886             :     Type* position_type = NodeProperties::GetType(position);
    1887             : 
    1888         339 :     if (search_string_type->Is(Type::String()) &&
    1889             :         position_type->Is(Type::SignedSmall())) {
    1890         166 :       if (Node* receiver = GetStringWitness(node)) {
    1891             :         RelaxEffectsAndControls(node);
    1892         161 :         node->ReplaceInput(0, receiver);
    1893         161 :         node->ReplaceInput(1, search_string);
    1894         161 :         node->ReplaceInput(2, position);
    1895         161 :         node->TrimInputCount(3);
    1896         161 :         NodeProperties::ChangeOp(node, simplified()->StringIndexOf());
    1897             :         return Changed(node);
    1898             :       }
    1899             :     }
    1900             :   }
    1901             :   return NoChange();
    1902             : }
    1903             : 
    1904         324 : Reduction JSBuiltinReducer::ReduceStringIterator(Node* node) {
    1905          54 :   if (Node* receiver = GetStringWitness(node)) {
    1906          54 :     Node* effect = NodeProperties::GetEffectInput(node);
    1907          54 :     Node* control = NodeProperties::GetControlInput(node);
    1908             : 
    1909             :     Node* map = jsgraph()->HeapConstant(
    1910          54 :         handle(native_context()->string_iterator_map(), isolate()));
    1911             : 
    1912             :     // allocate new iterator
    1913             :     effect = graph()->NewNode(
    1914          54 :         common()->BeginRegion(RegionObservability::kNotObservable), effect);
    1915             :     Node* value = effect = graph()->NewNode(
    1916             :         simplified()->Allocate(Type::OtherObject(), NOT_TENURED),
    1917         108 :         jsgraph()->Constant(JSStringIterator::kSize), effect, control);
    1918             :     effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
    1919         162 :                               value, map, effect, control);
    1920             :     effect = graph()->NewNode(
    1921             :         simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
    1922         162 :         jsgraph()->EmptyFixedArrayConstant(), effect, control);
    1923             :     effect = graph()->NewNode(
    1924             :         simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
    1925         162 :         jsgraph()->EmptyFixedArrayConstant(), effect, control);
    1926             : 
    1927             :     // attach the iterator to this string
    1928             :     effect = graph()->NewNode(
    1929             :         simplified()->StoreField(AccessBuilder::ForJSStringIteratorString()),
    1930         162 :         value, receiver, effect, control);
    1931             :     effect = graph()->NewNode(
    1932             :         simplified()->StoreField(AccessBuilder::ForJSStringIteratorIndex()),
    1933         162 :         value, jsgraph()->SmiConstant(0), effect, control);
    1934             : 
    1935          54 :     value = effect = graph()->NewNode(common()->FinishRegion(), value, effect);
    1936             : 
    1937             :     // replace it
    1938          54 :     ReplaceWithValue(node, value, effect, control);
    1939             :     return Replace(value);
    1940             :   }
    1941             :   return NoChange();
    1942             : }
    1943             : 
    1944         450 : Reduction JSBuiltinReducer::ReduceStringIteratorNext(Node* node) {
    1945          45 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1946          45 :   Node* effect = NodeProperties::GetEffectInput(node);
    1947          45 :   Node* control = NodeProperties::GetControlInput(node);
    1948          45 :   Node* context = NodeProperties::GetContextInput(node);
    1949          45 :   if (HasInstanceTypeWitness(receiver, effect, JS_STRING_ITERATOR_TYPE)) {
    1950             :     Node* string = effect = graph()->NewNode(
    1951             :         simplified()->LoadField(AccessBuilder::ForJSStringIteratorString()),
    1952         135 :         receiver, effect, control);
    1953             :     Node* index = effect = graph()->NewNode(
    1954             :         simplified()->LoadField(AccessBuilder::ForJSStringIteratorIndex()),
    1955         135 :         receiver, effect, control);
    1956             :     Node* length = effect = graph()->NewNode(
    1957             :         simplified()->LoadField(AccessBuilder::ForStringLength()), string,
    1958         135 :         effect, control);
    1959             : 
    1960             :     // branch0: if (index < length)
    1961             :     Node* check0 =
    1962          45 :         graph()->NewNode(simplified()->NumberLessThan(), index, length);
    1963             :     Node* branch0 =
    1964          45 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
    1965             : 
    1966             :     Node* etrue0 = effect;
    1967          45 :     Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    1968             :     Node* done_true;
    1969             :     Node* vtrue0;
    1970             :     {
    1971          45 :       done_true = jsgraph()->FalseConstant();
    1972             :       Node* lead = graph()->NewNode(simplified()->StringCharCodeAt(), string,
    1973          45 :                                     index, if_true0);
    1974             : 
    1975             :       // branch1: if ((lead & 0xFC00) === 0xD800)
    1976             :       Node* check1 =
    1977             :           graph()->NewNode(simplified()->NumberEqual(),
    1978             :                            graph()->NewNode(simplified()->NumberBitwiseAnd(),
    1979             :                                             lead, jsgraph()->Constant(0xFC00)),
    1980         180 :                            jsgraph()->Constant(0xD800));
    1981             :       Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
    1982          45 :                                        check1, if_true0);
    1983          45 :       Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    1984             :       Node* vtrue1;
    1985             :       {
    1986             :         Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
    1987          90 :                                             jsgraph()->OneConstant());
    1988             :         // branch2: if ((index + 1) < length)
    1989             :         Node* check2 = graph()->NewNode(simplified()->NumberLessThan(),
    1990          45 :                                         next_index, length);
    1991             :         Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1992          45 :                                          check2, if_true1);
    1993          45 :         Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
    1994             :         Node* vtrue2;
    1995             :         {
    1996             :           Node* trail = graph()->NewNode(simplified()->StringCharCodeAt(),
    1997          45 :                                          string, next_index, if_true2);
    1998             :           // branch3: if ((trail & 0xFC00) === 0xDC00)
    1999             :           Node* check3 = graph()->NewNode(
    2000             :               simplified()->NumberEqual(),
    2001             :               graph()->NewNode(simplified()->NumberBitwiseAnd(), trail,
    2002             :                                jsgraph()->Constant(0xFC00)),
    2003         180 :               jsgraph()->Constant(0xDC00));
    2004             :           Node* branch3 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2005          45 :                                            check3, if_true2);
    2006          45 :           Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
    2007             :           Node* vtrue3;
    2008             :           {
    2009             :             vtrue3 = graph()->NewNode(
    2010             :                 simplified()->NumberBitwiseOr(),
    2011             : // Need to swap the order for big-endian platforms
    2012             : #if V8_TARGET_BIG_ENDIAN
    2013             :                 graph()->NewNode(simplified()->NumberShiftLeft(), lead,
    2014             :                                  jsgraph()->Constant(16)),
    2015             :                 trail);
    2016             : #else
    2017             :                 graph()->NewNode(simplified()->NumberShiftLeft(), trail,
    2018             :                                  jsgraph()->Constant(16)),
    2019         135 :                 lead);
    2020             : #endif
    2021             :           }
    2022             : 
    2023          45 :           Node* if_false3 = graph()->NewNode(common()->IfFalse(), branch3);
    2024             :           Node* vfalse3 = lead;
    2025          45 :           if_true2 = graph()->NewNode(common()->Merge(2), if_true3, if_false3);
    2026             :           vtrue2 =
    2027             :               graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
    2028          45 :                                vtrue3, vfalse3, if_true2);
    2029             :         }
    2030             : 
    2031          45 :         Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
    2032             :         Node* vfalse2 = lead;
    2033          45 :         if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
    2034             :         vtrue1 =
    2035             :             graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
    2036          45 :                              vtrue2, vfalse2, if_true1);
    2037             :       }
    2038             : 
    2039          45 :       Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    2040             :       Node* vfalse1 = lead;
    2041          45 :       if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
    2042             :       vtrue0 =
    2043             :           graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
    2044          45 :                            vtrue1, vfalse1, if_true0);
    2045             :       vtrue0 = graph()->NewNode(
    2046          45 :           simplified()->StringFromCodePoint(UnicodeEncoding::UTF16), vtrue0);
    2047             : 
    2048             :       // Update iterator.[[NextIndex]]
    2049             :       Node* char_length = etrue0 = graph()->NewNode(
    2050             :           simplified()->LoadField(AccessBuilder::ForStringLength()), vtrue0,
    2051         135 :           etrue0, if_true0);
    2052          45 :       index = graph()->NewNode(simplified()->NumberAdd(), index, char_length);
    2053             :       etrue0 = graph()->NewNode(
    2054             :           simplified()->StoreField(AccessBuilder::ForJSStringIteratorIndex()),
    2055         135 :           receiver, index, etrue0, if_true0);
    2056             :     }
    2057             : 
    2058          45 :     Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    2059             :     Node* done_false;
    2060             :     Node* vfalse0;
    2061             :     {
    2062          45 :       vfalse0 = jsgraph()->UndefinedConstant();
    2063          45 :       done_false = jsgraph()->TrueConstant();
    2064             :     }
    2065             : 
    2066          45 :     control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
    2067          45 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue0, effect, control);
    2068             :     Node* value =
    2069             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2070          45 :                          vtrue0, vfalse0, control);
    2071             :     Node* done =
    2072             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2073          45 :                          done_true, done_false, control);
    2074             : 
    2075             :     value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
    2076          45 :                                       value, done, context, effect);
    2077             : 
    2078          45 :     ReplaceWithValue(node, value, effect, control);
    2079             :     return Replace(value);
    2080             :   }
    2081             :   return NoChange();
    2082             : }
    2083             : 
    2084          86 : Reduction JSBuiltinReducer::ReduceArrayBufferViewAccessor(
    2085          86 :     Node* node, InstanceType instance_type, FieldAccess const& access) {
    2086          86 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    2087          86 :   Node* effect = NodeProperties::GetEffectInput(node);
    2088          86 :   Node* control = NodeProperties::GetControlInput(node);
    2089          86 :   if (HasInstanceTypeWitness(receiver, effect, instance_type)) {
    2090             :     // Load the {receiver}s field.
    2091             :     Node* value = effect = graph()->NewNode(simplified()->LoadField(access),
    2092          86 :                                             receiver, effect, control);
    2093             : 
    2094             :     // See if we can skip the neutering check.
    2095          86 :     if (isolate()->IsArrayBufferNeuteringIntact()) {
    2096             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
    2097             :       // gets neutered.
    2098             :       dependencies()->AssumePropertyCell(
    2099             :           factory()->array_buffer_neutering_protector());
    2100             :     } else {
    2101             :       // Check if the {receiver}s buffer was neutered.
    2102             :       Node* receiver_buffer = effect = graph()->NewNode(
    2103             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
    2104          15 :           receiver, effect, control);
    2105             :       Node* check = effect =
    2106             :           graph()->NewNode(simplified()->ArrayBufferWasNeutered(),
    2107           5 :                            receiver_buffer, effect, control);
    2108             : 
    2109             :       // Default to zero if the {receiver}s buffer was neutered.
    2110             :       value = graph()->NewNode(
    2111             :           common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
    2112          10 :           check, jsgraph()->ZeroConstant(), value);
    2113             :     }
    2114             : 
    2115          86 :     ReplaceWithValue(node, value, effect, control);
    2116             :     return Replace(value);
    2117             :   }
    2118             :   return NoChange();
    2119             : }
    2120             : 
    2121    31952288 : Reduction JSBuiltinReducer::Reduce(Node* node) {
    2122             :   Reduction reduction = NoChange();
    2123             :   JSCallReduction r(node);
    2124             : 
    2125             :   // Dispatch according to the BuiltinFunctionId if present.
    2126    31952288 :   if (!r.HasBuiltinFunctionId()) return NoChange();
    2127       81877 :   switch (r.GetBuiltinFunctionId()) {
    2128             :     case kArrayEntries:
    2129           7 :       return ReduceArrayIterator(node, IterationKind::kEntries);
    2130             :     case kArrayKeys:
    2131          13 :       return ReduceArrayIterator(node, IterationKind::kKeys);
    2132             :     case kArrayValues:
    2133        1492 :       return ReduceArrayIterator(node, IterationKind::kValues);
    2134             :     case kArrayIteratorNext:
    2135        1562 :       return ReduceArrayIteratorNext(node);
    2136             :     case kArrayIsArray:
    2137          21 :       return ReduceArrayIsArray(node);
    2138             :     case kArrayPop:
    2139         153 :       return ReduceArrayPop(node);
    2140             :     case kArrayPush:
    2141        1642 :       return ReduceArrayPush(node);
    2142             :     case kDateNow:
    2143           8 :       return ReduceDateNow(node);
    2144             :     case kDateGetTime:
    2145           4 :       return ReduceDateGetTime(node);
    2146             :     case kGlobalIsFinite:
    2147          51 :       reduction = ReduceGlobalIsFinite(node);
    2148          51 :       break;
    2149             :     case kGlobalIsNaN:
    2150       21097 :       reduction = ReduceGlobalIsNaN(node);
    2151       21097 :       break;
    2152             :     case kMathAbs:
    2153         401 :       reduction = ReduceMathAbs(node);
    2154         401 :       break;
    2155             :     case kMathAcos:
    2156          14 :       reduction = ReduceMathAcos(node);
    2157          14 :       break;
    2158             :     case kMathAcosh:
    2159          13 :       reduction = ReduceMathAcosh(node);
    2160          13 :       break;
    2161             :     case kMathAsin:
    2162          14 :       reduction = ReduceMathAsin(node);
    2163          14 :       break;
    2164             :     case kMathAsinh:
    2165          13 :       reduction = ReduceMathAsinh(node);
    2166          13 :       break;
    2167             :     case kMathAtan:
    2168          14 :       reduction = ReduceMathAtan(node);
    2169          14 :       break;
    2170             :     case kMathAtanh:
    2171          13 :       reduction = ReduceMathAtanh(node);
    2172          13 :       break;
    2173             :     case kMathAtan2:
    2174         160 :       reduction = ReduceMathAtan2(node);
    2175         160 :       break;
    2176             :     case kMathCbrt:
    2177           0 :       reduction = ReduceMathCbrt(node);
    2178           0 :       break;
    2179             :     case kMathCeil:
    2180        7636 :       reduction = ReduceMathCeil(node);
    2181        7636 :       break;
    2182             :     case kMathClz32:
    2183          59 :       reduction = ReduceMathClz32(node);
    2184          59 :       break;
    2185             :     case kMathCos:
    2186          78 :       reduction = ReduceMathCos(node);
    2187          78 :       break;
    2188             :     case kMathCosh:
    2189          22 :       reduction = ReduceMathCosh(node);
    2190          22 :       break;
    2191             :     case kMathExp:
    2192          57 :       reduction = ReduceMathExp(node);
    2193          57 :       break;
    2194             :     case kMathExpm1:
    2195           0 :       reduction = ReduceMathExpm1(node);
    2196           0 :       break;
    2197             :     case kMathFloor:
    2198       28920 :       reduction = ReduceMathFloor(node);
    2199       28920 :       break;
    2200             :     case kMathFround:
    2201        1113 :       reduction = ReduceMathFround(node);
    2202        1113 :       break;
    2203             :     case kMathImul:
    2204         152 :       reduction = ReduceMathImul(node);
    2205         152 :       break;
    2206             :     case kMathLog:
    2207         151 :       reduction = ReduceMathLog(node);
    2208         151 :       break;
    2209             :     case kMathLog1p:
    2210          13 :       reduction = ReduceMathLog1p(node);
    2211          13 :       break;
    2212             :     case kMathLog10:
    2213           0 :       reduction = ReduceMathLog10(node);
    2214           0 :       break;
    2215             :     case kMathLog2:
    2216           0 :       reduction = ReduceMathLog2(node);
    2217           0 :       break;
    2218             :     case kMathMax:
    2219         337 :       reduction = ReduceMathMax(node);
    2220         337 :       break;
    2221             :     case kMathMin:
    2222         306 :       reduction = ReduceMathMin(node);
    2223         306 :       break;
    2224             :     case kMathPow:
    2225        1181 :       reduction = ReduceMathPow(node);
    2226        1181 :       break;
    2227             :     case kMathRound:
    2228        1587 :       reduction = ReduceMathRound(node);
    2229        1587 :       break;
    2230             :     case kMathSign:
    2231          34 :       reduction = ReduceMathSign(node);
    2232          34 :       break;
    2233             :     case kMathSin:
    2234         102 :       reduction = ReduceMathSin(node);
    2235         102 :       break;
    2236             :     case kMathSinh:
    2237          22 :       reduction = ReduceMathSinh(node);
    2238          22 :       break;
    2239             :     case kMathSqrt:
    2240         103 :       reduction = ReduceMathSqrt(node);
    2241         103 :       break;
    2242             :     case kMathTan:
    2243          57 :       reduction = ReduceMathTan(node);
    2244          57 :       break;
    2245             :     case kMathTanh:
    2246          22 :       reduction = ReduceMathTanh(node);
    2247          22 :       break;
    2248             :     case kMathTrunc:
    2249        7260 :       reduction = ReduceMathTrunc(node);
    2250        7260 :       break;
    2251             :     case kNumberIsFinite:
    2252          19 :       reduction = ReduceNumberIsFinite(node);
    2253          19 :       break;
    2254             :     case kNumberIsInteger:
    2255          19 :       reduction = ReduceNumberIsInteger(node);
    2256          19 :       break;
    2257             :     case kNumberIsNaN:
    2258          67 :       reduction = ReduceNumberIsNaN(node);
    2259          67 :       break;
    2260             :     case kNumberIsSafeInteger:
    2261          14 :       reduction = ReduceNumberIsSafeInteger(node);
    2262          14 :       break;
    2263             :     case kNumberParseInt:
    2264         460 :       reduction = ReduceNumberParseInt(node);
    2265         460 :       break;
    2266             :     case kObjectCreate:
    2267          21 :       reduction = ReduceObjectCreate(node);
    2268          21 :       break;
    2269             :     case kStringFromCharCode:
    2270         732 :       reduction = ReduceStringFromCharCode(node);
    2271         732 :       break;
    2272             :     case kStringCharAt:
    2273         107 :       return ReduceStringCharAt(node);
    2274             :     case kStringCharCodeAt:
    2275         309 :       return ReduceStringCharCodeAt(node);
    2276             :     case kStringConcat:
    2277           1 :       return ReduceStringConcat(node);
    2278             :     case kStringIndexOf:
    2279         173 :       return ReduceStringIndexOf(node);
    2280             :     case kStringIterator:
    2281          54 :       return ReduceStringIterator(node);
    2282             :     case kStringIteratorNext:
    2283          45 :       return ReduceStringIteratorNext(node);
    2284             :     case kDataViewByteLength:
    2285             :       return ReduceArrayBufferViewAccessor(
    2286             :           node, JS_DATA_VIEW_TYPE,
    2287           0 :           AccessBuilder::ForJSArrayBufferViewByteLength());
    2288             :     case kDataViewByteOffset:
    2289             :       return ReduceArrayBufferViewAccessor(
    2290             :           node, JS_DATA_VIEW_TYPE,
    2291           0 :           AccessBuilder::ForJSArrayBufferViewByteOffset());
    2292             :     case kTypedArrayByteLength:
    2293             :       return ReduceArrayBufferViewAccessor(
    2294             :           node, JS_TYPED_ARRAY_TYPE,
    2295           0 :           AccessBuilder::ForJSArrayBufferViewByteLength());
    2296             :     case kTypedArrayByteOffset:
    2297             :       return ReduceArrayBufferViewAccessor(
    2298             :           node, JS_TYPED_ARRAY_TYPE,
    2299           0 :           AccessBuilder::ForJSArrayBufferViewByteOffset());
    2300             :     case kTypedArrayLength:
    2301             :       return ReduceArrayBufferViewAccessor(
    2302          86 :           node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength());
    2303             :     case kTypedArrayEntries:
    2304           7 :       return ReduceTypedArrayIterator(node, IterationKind::kEntries);
    2305             :     case kTypedArrayKeys:
    2306           0 :       return ReduceTypedArrayIterator(node, IterationKind::kKeys);
    2307             :     case kTypedArrayValues:
    2308           7 :       return ReduceTypedArrayIterator(node, IterationKind::kValues);
    2309             :     default:
    2310             :       break;
    2311             :   }
    2312             : 
    2313             :   // Replace builtin call assuming replacement nodes are pure values that don't
    2314             :   // produce an effect. Replaces {node} with {reduction} and relaxes effects.
    2315       76186 :   if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement());
    2316             : 
    2317       76186 :   return reduction;
    2318             : }
    2319             : 
    2320       31285 : Node* JSBuiltinReducer::ToNumber(Node* input) {
    2321             :   Type* input_type = NodeProperties::GetType(input);
    2322       31285 :   if (input_type->Is(Type::Number())) return input;
    2323        2950 :   return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), input);
    2324             : }
    2325             : 
    2326         144 : Node* JSBuiltinReducer::ToUint32(Node* input) {
    2327         144 :   input = ToNumber(input);
    2328             :   Type* input_type = NodeProperties::GetType(input);
    2329         144 :   if (input_type->Is(Type::Unsigned32())) return input;
    2330         212 :   return graph()->NewNode(simplified()->NumberToUint32(), input);
    2331             : }
    2332             : 
    2333      101003 : Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); }
    2334             : 
    2335           0 : Factory* JSBuiltinReducer::factory() const { return isolate()->factory(); }
    2336             : 
    2337        3435 : Isolate* JSBuiltinReducer::isolate() const { return jsgraph()->isolate(); }
    2338             : 
    2339             : 
    2340       24511 : CommonOperatorBuilder* JSBuiltinReducer::common() const {
    2341       24511 :   return jsgraph()->common();
    2342             : }
    2343             : 
    2344             : 
    2345       75182 : SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const {
    2346       75189 :   return jsgraph()->simplified();
    2347             : }
    2348             : 
    2349        1472 : JSOperatorBuilder* JSBuiltinReducer::javascript() const {
    2350        1472 :   return jsgraph()->javascript();
    2351             : }
    2352             : 
    2353             : }  // namespace compiler
    2354             : }  // namespace internal
    2355             : }  // namespace v8

Generated by: LCOV version 1.10