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