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