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/code-factory.h"
      6 #include "src/compilation-dependencies.h"
      7 #include "src/compiler/access-builder.h"
      8 #include "src/compiler/js-graph.h"
      9 #include "src/compiler/js-typed-lowering.h"
     10 #include "src/compiler/linkage.h"
     11 #include "src/compiler/node-matchers.h"
     12 #include "src/compiler/node-properties.h"
     13 #include "src/compiler/operator-properties.h"
     14 #include "src/compiler/state-values-utils.h"
     15 #include "src/type-cache.h"
     16 #include "src/types.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 namespace compiler {
     21 
     22 namespace {
     23 
     24 // A helper class to construct inline allocations on the simplified operator
     25 // level. This keeps track of the effect chain for initial stores on a newly
     26 // allocated object and also provides helpers for commonly allocated objects.
     27 class AllocationBuilder final {
     28  public:
     29   AllocationBuilder(JSGraph* jsgraph, Node* effect, Node* control)
     30       : jsgraph_(jsgraph),
     31         allocation_(nullptr),
     32         effect_(effect),
     33         control_(control) {}
     34 
     35   // Primitive allocation of static size.
     36   void Allocate(int size, PretenureFlag pretenure = NOT_TENURED) {
     37     effect_ = graph()->NewNode(common()->BeginRegion(), effect_);
     38     allocation_ =
     39         graph()->NewNode(simplified()->Allocate(pretenure),
     40                          jsgraph()->Constant(size), effect_, control_);
     41     effect_ = allocation_;
     42   }
     43 
     44   // Primitive store into a field.
     45   void Store(const FieldAccess& access, Node* value) {
     46     effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_,
     47                                value, effect_, control_);
     48   }
     49 
     50   // Primitive store into an element.
     51   void Store(ElementAccess const& access, Node* index, Node* value) {
     52     effect_ = graph()->NewNode(simplified()->StoreElement(access), allocation_,
     53                                index, value, effect_, control_);
     54   }
     55 
     56   // Compound allocation of a FixedArray.
     57   void AllocateArray(int length, Handle<Map> map,
     58                      PretenureFlag pretenure = NOT_TENURED) {
     59     DCHECK(map->instance_type() == FIXED_ARRAY_TYPE ||
     60            map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE);
     61     int size = (map->instance_type() == FIXED_ARRAY_TYPE)
     62                    ? FixedArray::SizeFor(length)
     63                    : FixedDoubleArray::SizeFor(length);
     64     Allocate(size, pretenure);
     65     Store(AccessBuilder::ForMap(), map);
     66     Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length));
     67   }
     68 
     69   // Compound store of a constant into a field.
     70   void Store(const FieldAccess& access, Handle<Object> value) {
     71     Store(access, jsgraph()->Constant(value));
     72   }
     73 
     74   void FinishAndChange(Node* node) {
     75     NodeProperties::SetType(allocation_, NodeProperties::GetType(node));
     76     node->ReplaceInput(0, allocation_);
     77     node->ReplaceInput(1, effect_);
     78     node->TrimInputCount(2);
     79     NodeProperties::ChangeOp(node, common()->FinishRegion());
     80   }
     81 
     82   Node* Finish() {
     83     return graph()->NewNode(common()->FinishRegion(), allocation_, effect_);
     84   }
     85 
     86  protected:
     87   JSGraph* jsgraph() { return jsgraph_; }
     88   Graph* graph() { return jsgraph_->graph(); }
     89   CommonOperatorBuilder* common() { return jsgraph_->common(); }
     90   SimplifiedOperatorBuilder* simplified() { return jsgraph_->simplified(); }
     91 
     92  private:
     93   JSGraph* const jsgraph_;
     94   Node* allocation_;
     95   Node* effect_;
     96   Node* control_;
     97 };
     98 
     99 }  // namespace
    100 
    101 
    102 // A helper class to simplify the process of reducing a single binop node with a
    103 // JSOperator. This class manages the rewriting of context, control, and effect
    104 // dependencies during lowering of a binop and contains numerous helper
    105 // functions for matching the types of inputs to an operation.
    106 class JSBinopReduction final {
    107  public:
    108   JSBinopReduction(JSTypedLowering* lowering, Node* node)
    109       : lowering_(lowering), node_(node) {}
    110 
    111   void ConvertInputsToNumber(Node* frame_state) {
    112     // To convert the inputs to numbers, we have to provide frame states
    113     // for lazy bailouts in the ToNumber conversions.
    114     // We use a little hack here: we take the frame state before the binary
    115     // operation and use it to construct the frame states for the conversion
    116     // so that after the deoptimization, the binary operation IC gets
    117     // already converted values from full code. This way we are sure that we
    118     // will not re-do any of the side effects.
    119 
    120     Node* left_input = nullptr;
    121     Node* right_input = nullptr;
    122     bool left_is_primitive = left_type()->Is(Type::PlainPrimitive());
    123     bool right_is_primitive = right_type()->Is(Type::PlainPrimitive());
    124     bool handles_exception = NodeProperties::IsExceptionalCall(node_);
    125 
    126     if (!left_is_primitive && !right_is_primitive && handles_exception) {
    127       ConvertBothInputsToNumber(&left_input, &right_input, frame_state);
    128     } else {
    129       left_input = left_is_primitive
    130                        ? ConvertPlainPrimitiveToNumber(left())
    131                        : ConvertSingleInputToNumber(
    132                              left(), CreateFrameStateForLeftInput(frame_state));
    133       right_input = right_is_primitive
    134                         ? ConvertPlainPrimitiveToNumber(right())
    135                         : ConvertSingleInputToNumber(
    136                               right(), CreateFrameStateForRightInput(
    137                                            frame_state, left_input));
    138     }
    139 
    140     node_->ReplaceInput(0, left_input);
    141     node_->ReplaceInput(1, right_input);
    142   }
    143 
    144   void ConvertInputsToUI32(Signedness left_signedness,
    145                            Signedness right_signedness) {
    146     node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
    147     node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
    148   }
    149 
    150   void SwapInputs() {
    151     Node* l = left();
    152     Node* r = right();
    153     node_->ReplaceInput(0, r);
    154     node_->ReplaceInput(1, l);
    155   }
    156 
    157   // Remove all effect and control inputs and outputs to this node and change
    158   // to the pure operator {op}, possibly inserting a boolean inversion.
    159   Reduction ChangeToPureOperator(const Operator* op, bool invert = false,
    160                                  Type* type = Type::Any()) {
    161     DCHECK_EQ(0, op->EffectInputCount());
    162     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
    163     DCHECK_EQ(0, op->ControlInputCount());
    164     DCHECK_EQ(2, op->ValueInputCount());
    165 
    166     // Remove the effects from the node, and update its effect/control usages.
    167     if (node_->op()->EffectInputCount() > 0) {
    168       lowering_->RelaxEffectsAndControls(node_);
    169     }
    170     // Remove the inputs corresponding to context, effect, and control.
    171     NodeProperties::RemoveNonValueInputs(node_);
    172     // Finally, update the operator to the new one.
    173     NodeProperties::ChangeOp(node_, op);
    174 
    175     // TODO(jarin): Replace the explicit typing hack with a call to some method
    176     // that encapsulates changing the operator and re-typing.
    177     Type* node_type = NodeProperties::GetType(node_);
    178     NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
    179 
    180     if (invert) {
    181       // Insert an boolean not to invert the value.
    182       Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
    183       node_->ReplaceUses(value);
    184       // Note: ReplaceUses() smashes all uses, so smash it back here.
    185       value->ReplaceInput(0, node_);
    186       return lowering_->Replace(value);
    187     }
    188     return lowering_->Changed(node_);
    189   }
    190 
    191   Reduction ChangeToStringComparisonOperator(const Operator* op,
    192                                              bool invert = false) {
    193     if (node_->op()->ControlInputCount() > 0) {
    194       lowering_->RelaxControls(node_);
    195     }
    196     // String comparison operators need effect and control inputs, so copy them
    197     // over.
    198     Node* effect = NodeProperties::GetEffectInput(node_);
    199     Node* control = NodeProperties::GetControlInput(node_);
    200     node_->ReplaceInput(2, effect);
    201     node_->ReplaceInput(3, control);
    202 
    203     node_->TrimInputCount(4);
    204     NodeProperties::ChangeOp(node_, op);
    205 
    206     if (invert) {
    207       // Insert a boolean-not to invert the value.
    208       Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
    209       node_->ReplaceUses(value);
    210       // Note: ReplaceUses() smashes all uses, so smash it back here.
    211       value->ReplaceInput(0, node_);
    212       return lowering_->Replace(value);
    213     }
    214     return lowering_->Changed(node_);
    215   }
    216 
    217   Reduction ChangeToPureOperator(const Operator* op, Type* type) {
    218     return ChangeToPureOperator(op, false, type);
    219   }
    220 
    221   // TODO(turbofan): Strong mode should be killed soonish!
    222   bool IsStrong() const {
    223     if (node_->opcode() == IrOpcode::kJSLessThan ||
    224         node_->opcode() == IrOpcode::kJSLessThanOrEqual ||
    225         node_->opcode() == IrOpcode::kJSGreaterThan ||
    226         node_->opcode() == IrOpcode::kJSGreaterThanOrEqual) {
    227       return is_strong(OpParameter<LanguageMode>(node_));
    228     }
    229     return is_strong(BinaryOperationParametersOf(node_->op()).language_mode());
    230   }
    231 
    232   bool LeftInputIs(Type* t) { return left_type()->Is(t); }
    233 
    234   bool RightInputIs(Type* t) { return right_type()->Is(t); }
    235 
    236   bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
    237 
    238   bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); }
    239 
    240   bool OneInputCannotBe(Type* t) {
    241     return !left_type()->Maybe(t) || !right_type()->Maybe(t);
    242   }
    243 
    244   bool NeitherInputCanBe(Type* t) {
    245     return !left_type()->Maybe(t) && !right_type()->Maybe(t);
    246   }
    247 
    248   Node* effect() { return NodeProperties::GetEffectInput(node_); }
    249   Node* control() { return NodeProperties::GetControlInput(node_); }
    250   Node* context() { return NodeProperties::GetContextInput(node_); }
    251   Node* left() { return NodeProperties::GetValueInput(node_, 0); }
    252   Node* right() { return NodeProperties::GetValueInput(node_, 1); }
    253   Type* left_type() { return NodeProperties::GetType(node_->InputAt(0)); }
    254   Type* right_type() { return NodeProperties::GetType(node_->InputAt(1)); }
    255 
    256   SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
    257   Graph* graph() const { return lowering_->graph(); }
    258   JSGraph* jsgraph() { return lowering_->jsgraph(); }
    259   JSOperatorBuilder* javascript() { return lowering_->javascript(); }
    260   MachineOperatorBuilder* machine() { return lowering_->machine(); }
    261   CommonOperatorBuilder* common() { return jsgraph()->common(); }
    262   Zone* zone() const { return graph()->zone(); }
    263 
    264  private:
    265   JSTypedLowering* lowering_;  // The containing lowering instance.
    266   Node* node_;                 // The original node.
    267 
    268   Node* CreateFrameStateForLeftInput(Node* frame_state) {
    269     FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
    270 
    271     if (state_info.bailout_id() == BailoutId::None()) {
    272       // Dummy frame state => just leave it as is.
    273       return frame_state;
    274     }
    275 
    276     // If the frame state is already the right one, just return it.
    277     if (state_info.state_combine().kind() == OutputFrameStateCombine::kPokeAt &&
    278         state_info.state_combine().GetOffsetToPokeAt() == 1) {
    279       return frame_state;
    280     }
    281 
    282     // Here, we smash the result of the conversion into the slot just below
    283     // the stack top. This is the slot that full code uses to store the
    284     // left operand.
    285     const Operator* op = jsgraph()->common()->FrameState(
    286         state_info.bailout_id(), OutputFrameStateCombine::PokeAt(1),
    287         state_info.function_info());
    288 
    289     return graph()->NewNode(op,
    290                             frame_state->InputAt(kFrameStateParametersInput),
    291                             frame_state->InputAt(kFrameStateLocalsInput),
    292                             frame_state->InputAt(kFrameStateStackInput),
    293                             frame_state->InputAt(kFrameStateContextInput),
    294                             frame_state->InputAt(kFrameStateFunctionInput),
    295                             frame_state->InputAt(kFrameStateOuterStateInput));
    296   }
    297 
    298   Node* CreateFrameStateForRightInput(Node* frame_state, Node* converted_left) {
    299     FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
    300 
    301     if (state_info.bailout_id() == BailoutId::None()) {
    302       // Dummy frame state => just leave it as is.
    303       return frame_state;
    304     }
    305 
    306     // Create a frame state that stores the result of the operation to the
    307     // top of the stack (i.e., the slot used for the right operand).
    308     const Operator* op = jsgraph()->common()->FrameState(
    309         state_info.bailout_id(), OutputFrameStateCombine::PokeAt(0),
    310         state_info.function_info());
    311 
    312     // Change the left operand {converted_left} on the expression stack.
    313     Node* stack = frame_state->InputAt(2);
    314     DCHECK_EQ(stack->opcode(), IrOpcode::kStateValues);
    315     DCHECK_GE(stack->InputCount(), 2);
    316 
    317     // TODO(jarin) Allocate in a local zone or a reusable buffer.
    318     NodeVector new_values(stack->InputCount(), zone());
    319     for (int i = 0; i < stack->InputCount(); i++) {
    320       if (i == stack->InputCount() - 2) {
    321         new_values[i] = converted_left;
    322       } else {
    323         new_values[i] = stack->InputAt(i);
    324       }
    325     }
    326     Node* new_stack =
    327         graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front());
    328 
    329     return graph()->NewNode(
    330         op, frame_state->InputAt(kFrameStateParametersInput),
    331         frame_state->InputAt(kFrameStateLocalsInput), new_stack,
    332         frame_state->InputAt(kFrameStateContextInput),
    333         frame_state->InputAt(kFrameStateFunctionInput),
    334         frame_state->InputAt(kFrameStateOuterStateInput));
    335   }
    336 
    337   Node* ConvertPlainPrimitiveToNumber(Node* node) {
    338     DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
    339     // Avoid inserting too many eager ToNumber() operations.
    340     Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
    341     if (reduction.Changed()) return reduction.replacement();
    342     // TODO(jarin) Use PlainPrimitiveToNumber once we have it.
    343     return graph()->NewNode(
    344         javascript()->ToNumber(), node, jsgraph()->NoContextConstant(),
    345         jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
    346   }
    347 
    348   Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
    349     DCHECK(!NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
    350     Node* const n = graph()->NewNode(javascript()->ToNumber(), node, context(),
    351                                      frame_state, effect(), control());
    352     NodeProperties::ReplaceUses(node_, node_, node_, n, n);
    353     update_effect(n);
    354     return n;
    355   }
    356 
    357   void ConvertBothInputsToNumber(Node** left_result, Node** right_result,
    358                                  Node* frame_state) {
    359     Node* projections[2];
    360 
    361     // Find {IfSuccess} and {IfException} continuations of the operation.
    362     NodeProperties::CollectControlProjections(node_, projections, 2);
    363     IfExceptionHint hint = OpParameter<IfExceptionHint>(projections[1]);
    364     Node* if_exception = projections[1];
    365     Node* if_success = projections[0];
    366 
    367     // Insert two ToNumber() operations that both potentially throw.
    368     Node* left_state = CreateFrameStateForLeftInput(frame_state);
    369     Node* left_conv =
    370         graph()->NewNode(javascript()->ToNumber(), left(), context(),
    371                          left_state, effect(), control());
    372     Node* left_success = graph()->NewNode(common()->IfSuccess(), left_conv);
    373     Node* right_state = CreateFrameStateForRightInput(frame_state, left_conv);
    374     Node* right_conv =
    375         graph()->NewNode(javascript()->ToNumber(), right(), context(),
    376                          right_state, left_conv, left_success);
    377     Node* left_exception =
    378         graph()->NewNode(common()->IfException(hint), left_conv, left_conv);
    379     Node* right_exception =
    380         graph()->NewNode(common()->IfException(hint), right_conv, right_conv);
    381     NodeProperties::ReplaceControlInput(if_success, right_conv);
    382     update_effect(right_conv);
    383 
    384     // Wire conversions to existing {IfException} continuation.
    385     Node* exception_merge = if_exception;
    386     Node* exception_value =
    387         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    388                          left_exception, right_exception, exception_merge);
    389     Node* exception_effect =
    390         graph()->NewNode(common()->EffectPhi(2), left_exception,
    391                          right_exception, exception_merge);
    392     for (Edge edge : exception_merge->use_edges()) {
    393       if (NodeProperties::IsEffectEdge(edge)) edge.UpdateTo(exception_effect);
    394       if (NodeProperties::IsValueEdge(edge)) edge.UpdateTo(exception_value);
    395     }
    396     NodeProperties::RemoveType(exception_merge);
    397     exception_merge->ReplaceInput(0, left_exception);
    398     exception_merge->ReplaceInput(1, right_exception);
    399     NodeProperties::ChangeOp(exception_merge, common()->Merge(2));
    400 
    401     *left_result = left_conv;
    402     *right_result = right_conv;
    403   }
    404 
    405   Node* ConvertToUI32(Node* node, Signedness signedness) {
    406     // Avoid introducing too many eager NumberToXXnt32() operations.
    407     Type* type = NodeProperties::GetType(node);
    408     if (signedness == kSigned) {
    409       if (!type->Is(Type::Signed32())) {
    410         node = graph()->NewNode(simplified()->NumberToInt32(), node);
    411       }
    412     } else {
    413       DCHECK_EQ(kUnsigned, signedness);
    414       if (!type->Is(Type::Unsigned32())) {
    415         node = graph()->NewNode(simplified()->NumberToUint32(), node);
    416       }
    417     }
    418     return node;
    419   }
    420 
    421   void update_effect(Node* effect) {
    422     NodeProperties::ReplaceEffectInput(node_, effect);
    423   }
    424 };
    425 
    426 
    427 // TODO(turbofan): js-typed-lowering improvements possible
    428 // - immediately put in type bounds for all new nodes
    429 // - relax effects from generic but not-side-effecting operations
    430 
    431 
    432 JSTypedLowering::JSTypedLowering(Editor* editor,
    433                                  CompilationDependencies* dependencies,
    434                                  Flags flags, JSGraph* jsgraph, Zone* zone)
    435     : AdvancedReducer(editor),
    436       dependencies_(dependencies),
    437       flags_(flags),
    438       jsgraph_(jsgraph),
    439       true_type_(Type::Constant(factory()->true_value(), graph()->zone())),
    440       false_type_(Type::Constant(factory()->false_value(), graph()->zone())),
    441       the_hole_type_(
    442           Type::Constant(factory()->the_hole_value(), graph()->zone())),
    443       type_cache_(TypeCache::Get()) {
    444   for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
    445     double min = kMinInt / (1 << k);
    446     double max = kMaxInt / (1 << k);
    447     shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
    448   }
    449 }
    450 
    451 
    452 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
    453   if (flags() & kDisableBinaryOpReduction) return NoChange();
    454 
    455   JSBinopReduction r(this, node);
    456   if (r.BothInputsAre(Type::Number())) {
    457     // JSAdd(x:number, y:number) => NumberAdd(x, y)
    458     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
    459   }
    460   if (r.NeitherInputCanBe(Type::StringOrReceiver()) && !r.IsStrong()) {
    461     // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
    462     Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
    463     r.ConvertInputsToNumber(frame_state);
    464     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
    465   }
    466   if (r.BothInputsAre(Type::String())) {
    467     // JSAdd(x:string, y:string) => CallStub[StringAdd](x, y)
    468     Callable const callable =
    469         CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
    470     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    471         isolate(), graph()->zone(), callable.descriptor(), 0,
    472         CallDescriptor::kNeedsFrameState, node->op()->properties());
    473     DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op()));
    474     node->RemoveInput(NodeProperties::FirstFrameStateIndex(node) + 1);
    475     node->InsertInput(graph()->zone(), 0,
    476                       jsgraph()->HeapConstant(callable.code()));
    477     NodeProperties::ChangeOp(node, common()->Call(desc));
    478     return Changed(node);
    479   }
    480   return NoChange();
    481 }
    482 
    483 
    484 Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
    485   if (flags() & kDisableBinaryOpReduction) return NoChange();
    486 
    487   JSBinopReduction r(this, node);
    488   if (r.BothInputsAre(Type::Number())) {
    489     // JSModulus(x:number, x:number) => NumberModulus(x, y)
    490     return r.ChangeToPureOperator(simplified()->NumberModulus(),
    491                                   Type::Number());
    492   }
    493   return NoChange();
    494 }
    495 
    496 
    497 Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
    498                                              const Operator* numberOp) {
    499   if (flags() & kDisableBinaryOpReduction) return NoChange();
    500 
    501   JSBinopReduction r(this, node);
    502   if (r.IsStrong() || numberOp == simplified()->NumberModulus()) {
    503     if (r.BothInputsAre(Type::Number())) {
    504       return r.ChangeToPureOperator(numberOp, Type::Number());
    505     }
    506     return NoChange();
    507   }
    508   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
    509   r.ConvertInputsToNumber(frame_state);
    510   return r.ChangeToPureOperator(numberOp, Type::Number());
    511 }
    512 
    513 
    514 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
    515   if (flags() & kDisableBinaryOpReduction) return NoChange();
    516 
    517   JSBinopReduction r(this, node);
    518   if (r.IsStrong()) {
    519     if (r.BothInputsAre(Type::Number())) {
    520       r.ConvertInputsToUI32(kSigned, kSigned);
    521       return r.ChangeToPureOperator(intOp, Type::Integral32());
    522     }
    523     return NoChange();
    524   }
    525   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
    526   r.ConvertInputsToNumber(frame_state);
    527   r.ConvertInputsToUI32(kSigned, kSigned);
    528   return r.ChangeToPureOperator(intOp, Type::Integral32());
    529 }
    530 
    531 
    532 Reduction JSTypedLowering::ReduceUI32Shift(Node* node,
    533                                            Signedness left_signedness,
    534                                            const Operator* shift_op) {
    535   if (flags() & kDisableBinaryOpReduction) return NoChange();
    536 
    537   JSBinopReduction r(this, node);
    538   if (r.IsStrong()) {
    539     if (r.BothInputsAre(Type::Number())) {
    540       r.ConvertInputsToUI32(left_signedness, kUnsigned);
    541       return r.ChangeToPureOperator(shift_op);
    542     }
    543     return NoChange();
    544   }
    545   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
    546   r.ConvertInputsToNumber(frame_state);
    547   r.ConvertInputsToUI32(left_signedness, kUnsigned);
    548   return r.ChangeToPureOperator(shift_op);
    549 }
    550 
    551 
    552 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
    553   if (flags() & kDisableBinaryOpReduction) return NoChange();
    554 
    555   JSBinopReduction r(this, node);
    556   if (r.BothInputsAre(Type::String())) {
    557     // If both inputs are definitely strings, perform a string comparison.
    558     const Operator* stringOp;
    559     switch (node->opcode()) {
    560       case IrOpcode::kJSLessThan:
    561         stringOp = simplified()->StringLessThan();
    562         break;
    563       case IrOpcode::kJSGreaterThan:
    564         stringOp = simplified()->StringLessThan();
    565         r.SwapInputs();  // a > b => b < a
    566         break;
    567       case IrOpcode::kJSLessThanOrEqual:
    568         stringOp = simplified()->StringLessThanOrEqual();
    569         break;
    570       case IrOpcode::kJSGreaterThanOrEqual:
    571         stringOp = simplified()->StringLessThanOrEqual();
    572         r.SwapInputs();  // a >= b => b <= a
    573         break;
    574       default:
    575         return NoChange();
    576     }
    577     r.ChangeToStringComparisonOperator(stringOp);
    578     return Changed(node);
    579   }
    580   if (r.OneInputCannotBe(Type::StringOrReceiver())) {
    581     const Operator* less_than;
    582     const Operator* less_than_or_equal;
    583     if (r.BothInputsAre(Type::Unsigned32())) {
    584       less_than = machine()->Uint32LessThan();
    585       less_than_or_equal = machine()->Uint32LessThanOrEqual();
    586     } else if (r.BothInputsAre(Type::Signed32())) {
    587       less_than = machine()->Int32LessThan();
    588       less_than_or_equal = machine()->Int32LessThanOrEqual();
    589     } else {
    590       // TODO(turbofan): mixed signed/unsigned int32 comparisons.
    591       if (r.IsStrong() && !r.BothInputsAre(Type::Number())) {
    592         return NoChange();
    593       }
    594       Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
    595       r.ConvertInputsToNumber(frame_state);
    596       less_than = simplified()->NumberLessThan();
    597       less_than_or_equal = simplified()->NumberLessThanOrEqual();
    598     }
    599     const Operator* comparison;
    600     switch (node->opcode()) {
    601       case IrOpcode::kJSLessThan:
    602         comparison = less_than;
    603         break;
    604       case IrOpcode::kJSGreaterThan:
    605         comparison = less_than;
    606         r.SwapInputs();  // a > b => b < a
    607         break;
    608       case IrOpcode::kJSLessThanOrEqual:
    609         comparison = less_than_or_equal;
    610         break;
    611       case IrOpcode::kJSGreaterThanOrEqual:
    612         comparison = less_than_or_equal;
    613         r.SwapInputs();  // a >= b => b <= a
    614         break;
    615       default:
    616         return NoChange();
    617     }
    618     return r.ChangeToPureOperator(comparison);
    619   }
    620   // TODO(turbofan): relax/remove effects of this operator in other cases.
    621   return NoChange();  // Keep a generic comparison.
    622 }
    623 
    624 
    625 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
    626   if (flags() & kDisableBinaryOpReduction) return NoChange();
    627 
    628   JSBinopReduction r(this, node);
    629 
    630   if (r.BothInputsAre(Type::Number())) {
    631     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
    632   }
    633   if (r.BothInputsAre(Type::String())) {
    634     return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
    635                                               invert);
    636   }
    637   if (r.BothInputsAre(Type::Boolean())) {
    638     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
    639                                   invert);
    640   }
    641   if (r.BothInputsAre(Type::Receiver())) {
    642     return r.ChangeToPureOperator(
    643         simplified()->ReferenceEqual(Type::Receiver()), invert);
    644   }
    645   if (r.OneInputIs(Type::NullOrUndefined())) {
    646     Callable const callable = CodeFactory::CompareNilIC(isolate(), kNullValue);
    647     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    648         isolate(), graph()->zone(), callable.descriptor(), 0,
    649         CallDescriptor::kNeedsFrameState, node->op()->properties());
    650     node->RemoveInput(r.LeftInputIs(Type::NullOrUndefined()) ? 0 : 1);
    651     node->InsertInput(graph()->zone(), 0,
    652                       jsgraph()->HeapConstant(callable.code()));
    653     NodeProperties::ChangeOp(node, common()->Call(desc));
    654     if (invert) {
    655       // Insert an boolean not to invert the value.
    656       Node* value = graph()->NewNode(simplified()->BooleanNot(), node);
    657       node->ReplaceUses(value);
    658       // Note: ReplaceUses() smashes all uses, so smash it back here.
    659       value->ReplaceInput(0, node);
    660       return Replace(value);
    661     }
    662     return Changed(node);
    663   }
    664   return NoChange();
    665 }
    666 
    667 
    668 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
    669   if (flags() & kDisableBinaryOpReduction) return NoChange();
    670 
    671   JSBinopReduction r(this, node);
    672   if (r.left() == r.right()) {
    673     // x === x is always true if x != NaN
    674     if (!r.left_type()->Maybe(Type::NaN())) {
    675       Node* replacement = jsgraph()->BooleanConstant(!invert);
    676       ReplaceWithValue(node, replacement);
    677       return Replace(replacement);
    678     }
    679   }
    680   if (r.OneInputCannotBe(Type::NumberOrString())) {
    681     // For values with canonical representation (i.e. not string nor number) an
    682     // empty type intersection means the values cannot be strictly equal.
    683     if (!r.left_type()->Maybe(r.right_type())) {
    684       Node* replacement = jsgraph()->BooleanConstant(invert);
    685       ReplaceWithValue(node, replacement);
    686       return Replace(replacement);
    687     }
    688   }
    689   if (r.OneInputIs(the_hole_type_)) {
    690     return r.ChangeToPureOperator(simplified()->ReferenceEqual(the_hole_type_),
    691                                   invert);
    692   }
    693   if (r.OneInputIs(Type::Undefined())) {
    694     return r.ChangeToPureOperator(
    695         simplified()->ReferenceEqual(Type::Undefined()), invert);
    696   }
    697   if (r.OneInputIs(Type::Null())) {
    698     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()),
    699                                   invert);
    700   }
    701   if (r.OneInputIs(Type::Boolean())) {
    702     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
    703                                   invert);
    704   }
    705   if (r.OneInputIs(Type::Object())) {
    706     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Object()),
    707                                   invert);
    708   }
    709   if (r.OneInputIs(Type::Receiver())) {
    710     return r.ChangeToPureOperator(
    711         simplified()->ReferenceEqual(Type::Receiver()), invert);
    712   }
    713   if (r.BothInputsAre(Type::Unique())) {
    714     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()),
    715                                   invert);
    716   }
    717   if (r.BothInputsAre(Type::String())) {
    718     return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
    719                                               invert);
    720   }
    721   if (r.BothInputsAre(Type::Number())) {
    722     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
    723   }
    724   // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
    725   return NoChange();
    726 }
    727 
    728 
    729 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
    730   Node* const input = node->InputAt(0);
    731   Type* const input_type = NodeProperties::GetType(input);
    732   Node* const effect = NodeProperties::GetEffectInput(node);
    733   if (input_type->Is(Type::Boolean())) {
    734     // JSToBoolean(x:boolean) => x
    735     ReplaceWithValue(node, input, effect);
    736     return Replace(input);
    737   } else if (input_type->Is(Type::OrderedNumber())) {
    738     // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0))
    739     RelaxEffectsAndControls(node);
    740     node->ReplaceInput(0, graph()->NewNode(simplified()->NumberEqual(), input,
    741                                            jsgraph()->ZeroConstant()));
    742     node->TrimInputCount(1);
    743     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
    744     return Changed(node);
    745   } else if (input_type->Is(Type::String())) {
    746     // JSToBoolean(x:string) => NumberLessThan(#0,x.length)
    747     FieldAccess const access = AccessBuilder::ForStringLength();
    748     Node* length = graph()->NewNode(simplified()->LoadField(access), input,
    749                                     effect, graph()->start());
    750     ReplaceWithValue(node, node, length);
    751     node->ReplaceInput(0, jsgraph()->ZeroConstant());
    752     node->ReplaceInput(1, length);
    753     node->TrimInputCount(2);
    754     NodeProperties::ChangeOp(node, simplified()->NumberLessThan());
    755     return Changed(node);
    756   }
    757   return NoChange();
    758 }
    759 
    760 
    761 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
    762   if (input->opcode() == IrOpcode::kJSToNumber) {
    763     // Recursively try to reduce the input first.
    764     Reduction result = ReduceJSToNumber(input);
    765     if (result.Changed()) return result;
    766     return Changed(input);  // JSToNumber(JSToNumber(x)) => JSToNumber(x)
    767   }
    768   // Check for ToNumber truncation of signaling NaN to undefined mapping.
    769   if (input->opcode() == IrOpcode::kSelect) {
    770     Node* check = NodeProperties::GetValueInput(input, 0);
    771     Node* vtrue = NodeProperties::GetValueInput(input, 1);
    772     Type* vtrue_type = NodeProperties::GetType(vtrue);
    773     Node* vfalse = NodeProperties::GetValueInput(input, 2);
    774     Type* vfalse_type = NodeProperties::GetType(vfalse);
    775     if (vtrue_type->Is(Type::Undefined()) && vfalse_type->Is(Type::Number())) {
    776       if (check->opcode() == IrOpcode::kNumberIsHoleNaN &&
    777           check->InputAt(0) == vfalse) {
    778         // JSToNumber(Select(NumberIsHoleNaN(x), y:undefined, x:number)) => x
    779         return Replace(vfalse);
    780       }
    781     }
    782   }
    783   // Check if we have a cached conversion.
    784   Type* input_type = NodeProperties::GetType(input);
    785   if (input_type->Is(Type::Number())) {
    786     // JSToNumber(x:number) => x
    787     return Changed(input);
    788   }
    789   if (input_type->Is(Type::Undefined())) {
    790     // JSToNumber(undefined) => #NaN
    791     return Replace(jsgraph()->NaNConstant());
    792   }
    793   if (input_type->Is(Type::Null())) {
    794     // JSToNumber(null) => #0
    795     return Replace(jsgraph()->ZeroConstant());
    796   }
    797   if (input_type->Is(Type::Boolean())) {
    798     // JSToNumber(x:boolean) => BooleanToNumber(x)
    799     return Replace(graph()->NewNode(simplified()->BooleanToNumber(), input));
    800   }
    801   // TODO(turbofan): js-typed-lowering of ToNumber(x:string)
    802   return NoChange();
    803 }
    804 
    805 
    806 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
    807   // Try to reduce the input first.
    808   Node* const input = node->InputAt(0);
    809   Reduction reduction = ReduceJSToNumberInput(input);
    810   if (reduction.Changed()) {
    811     ReplaceWithValue(node, reduction.replacement());
    812     return reduction;
    813   }
    814   Type* const input_type = NodeProperties::GetType(input);
    815   if (input_type->Is(Type::PlainPrimitive())) {
    816     if (NodeProperties::GetContextInput(node) !=
    817             jsgraph()->NoContextConstant() ||
    818         NodeProperties::GetEffectInput(node) != graph()->start() ||
    819         NodeProperties::GetControlInput(node) != graph()->start()) {
    820       // JSToNumber(x:plain-primitive,context,effect,control)
    821       //   => JSToNumber(x,no-context,start,start)
    822       RelaxEffectsAndControls(node);
    823       NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
    824       NodeProperties::ReplaceControlInput(node, graph()->start());
    825       NodeProperties::ReplaceEffectInput(node, graph()->start());
    826       DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
    827       NodeProperties::ReplaceFrameStateInput(node, 0,
    828                                              jsgraph()->EmptyFrameState());
    829       return Changed(node);
    830     }
    831   }
    832   return NoChange();
    833 }
    834 
    835 
    836 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
    837   if (input->opcode() == IrOpcode::kJSToString) {
    838     // Recursively try to reduce the input first.
    839     Reduction result = ReduceJSToString(input);
    840     if (result.Changed()) return result;
    841     return Changed(input);  // JSToString(JSToString(x)) => JSToString(x)
    842   }
    843   Type* input_type = NodeProperties::GetType(input);
    844   if (input_type->Is(Type::String())) {
    845     return Changed(input);  // JSToString(x:string) => x
    846   }
    847   if (input_type->Is(Type::Boolean())) {
    848     return Replace(graph()->NewNode(
    849         common()->Select(MachineRepresentation::kTagged), input,
    850         jsgraph()->HeapConstant(factory()->true_string()),
    851         jsgraph()->HeapConstant(factory()->false_string())));
    852   }
    853   if (input_type->Is(Type::Undefined())) {
    854     return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
    855   }
    856   if (input_type->Is(Type::Null())) {
    857     return Replace(jsgraph()->HeapConstant(factory()->null_string()));
    858   }
    859   // TODO(turbofan): js-typed-lowering of ToString(x:number)
    860   return NoChange();
    861 }
    862 
    863 
    864 Reduction JSTypedLowering::ReduceJSToString(Node* node) {
    865   // Try to reduce the input first.
    866   Node* const input = node->InputAt(0);
    867   Reduction reduction = ReduceJSToStringInput(input);
    868   if (reduction.Changed()) {
    869     ReplaceWithValue(node, reduction.replacement());
    870     return reduction;
    871   }
    872   return NoChange();
    873 }
    874 
    875 
    876 Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
    877   DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
    878   Node* receiver = NodeProperties::GetValueInput(node, 0);
    879   Type* receiver_type = NodeProperties::GetType(receiver);
    880   Node* context = NodeProperties::GetContextInput(node);
    881   Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
    882   Node* effect = NodeProperties::GetEffectInput(node);
    883   Node* control = NodeProperties::GetControlInput(node);
    884   if (!receiver_type->Is(Type::Receiver())) {
    885     // TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks.
    886     if (receiver_type->Maybe(Type::NullOrUndefined()) &&
    887         NodeProperties::IsExceptionalCall(node)) {
    888       // ToObject throws for null or undefined inputs.
    889       return NoChange();
    890     }
    891 
    892     // Check whether {receiver} is a Smi.
    893     Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
    894     Node* branch0 =
    895         graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
    896     Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    897     Node* etrue0 = effect;
    898 
    899     Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    900     Node* efalse0 = effect;
    901 
    902     // Determine the instance type of {receiver}.
    903     Node* receiver_map = efalse0 =
    904         graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
    905                          receiver, efalse0, if_false0);
    906     Node* receiver_instance_type = efalse0 = graph()->NewNode(
    907         simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
    908         receiver_map, efalse0, if_false0);
    909 
    910     // Check whether {receiver} is a spec object.
    911     STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
    912     Node* check1 =
    913         graph()->NewNode(machine()->Uint32LessThanOrEqual(),
    914                          jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
    915                          receiver_instance_type);
    916     Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    917                                      check1, if_false0);
    918     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    919     Node* etrue1 = efalse0;
    920 
    921     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    922     Node* efalse1 = efalse0;
    923 
    924     // Convert {receiver} using the ToObjectStub.
    925     Node* if_convert =
    926         graph()->NewNode(common()->Merge(2), if_true0, if_false1);
    927     Node* econvert =
    928         graph()->NewNode(common()->EffectPhi(2), etrue0, efalse1, if_convert);
    929     Node* rconvert;
    930     {
    931       Callable callable = CodeFactory::ToObject(isolate());
    932       CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    933           isolate(), graph()->zone(), callable.descriptor(), 0,
    934           CallDescriptor::kNeedsFrameState, node->op()->properties());
    935       rconvert = econvert = graph()->NewNode(
    936           common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
    937           receiver, context, frame_state, econvert, if_convert);
    938     }
    939 
    940     // The {receiver} is already a spec object.
    941     Node* if_done = if_true1;
    942     Node* edone = etrue1;
    943     Node* rdone = receiver;
    944 
    945     control = graph()->NewNode(common()->Merge(2), if_convert, if_done);
    946     effect = graph()->NewNode(common()->EffectPhi(2), econvert, edone, control);
    947     receiver =
    948         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    949                          rconvert, rdone, control);
    950   }
    951   ReplaceWithValue(node, receiver, effect, control);
    952   return Changed(receiver);
    953 }
    954 
    955 
    956 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
    957   DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
    958   Node* receiver = NodeProperties::GetValueInput(node, 0);
    959   Type* receiver_type = NodeProperties::GetType(receiver);
    960   Node* effect = NodeProperties::GetEffectInput(node);
    961   Node* control = NodeProperties::GetControlInput(node);
    962   Handle<Name> name = NamedAccessOf(node->op()).name();
    963   // Optimize "length" property of strings.
    964   if (name.is_identical_to(factory()->length_string()) &&
    965       receiver_type->Is(Type::String())) {
    966     Node* value = effect = graph()->NewNode(
    967         simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
    968         effect, control);
    969     ReplaceWithValue(node, value, effect);
    970     return Replace(value);
    971   }
    972   // Optimize "prototype" property of functions.
    973   if (name.is_identical_to(factory()->prototype_string()) &&
    974       receiver_type->IsConstant() &&
    975       receiver_type->AsConstant()->Value()->IsJSFunction()) {
    976     // TODO(turbofan): This lowering might not kick in if we ever lower
    977     // the C++ accessor for "prototype" in an earlier optimization pass.
    978     Handle<JSFunction> function =
    979         Handle<JSFunction>::cast(receiver_type->AsConstant()->Value());
    980     if (function->has_initial_map()) {
    981       // We need to add a code dependency on the initial map of the {function}
    982       // in order to be notified about changes to the "prototype" of {function},
    983       // so it doesn't make sense to continue unless deoptimization is enabled.
    984       if (!(flags() & kDeoptimizationEnabled)) return NoChange();
    985       Handle<Map> initial_map(function->initial_map(), isolate());
    986       dependencies()->AssumeInitialMapCantChange(initial_map);
    987       Node* value =
    988           jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
    989       ReplaceWithValue(node, value);
    990       return Replace(value);
    991     }
    992   }
    993   return NoChange();
    994 }
    995 
    996 
    997 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
    998   Node* key = NodeProperties::GetValueInput(node, 1);
    999   Node* base = NodeProperties::GetValueInput(node, 0);
   1000   Type* key_type = NodeProperties::GetType(key);
   1001   HeapObjectMatcher mbase(base);
   1002   if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
   1003     Handle<JSTypedArray> const array =
   1004         Handle<JSTypedArray>::cast(mbase.Value());
   1005     if (!array->GetBuffer()->was_neutered()) {
   1006       array->GetBuffer()->set_is_neuterable(false);
   1007       BufferAccess const access(array->type());
   1008       size_t const k =
   1009           ElementSizeLog2Of(access.machine_type().representation());
   1010       double const byte_length = array->byte_length()->Number();
   1011       CHECK_LT(k, arraysize(shifted_int32_ranges_));
   1012       if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
   1013         // JSLoadProperty(typed-array, int32)
   1014         Handle<FixedTypedArrayBase> elements =
   1015             Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
   1016         Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
   1017         Node* length = jsgraph()->Constant(byte_length);
   1018         Node* effect = NodeProperties::GetEffectInput(node);
   1019         Node* control = NodeProperties::GetControlInput(node);
   1020         // Check if we can avoid the bounds check.
   1021         if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
   1022           Node* load = graph()->NewNode(
   1023               simplified()->LoadElement(
   1024                   AccessBuilder::ForTypedArrayElement(array->type(), true)),
   1025               buffer, key, effect, control);
   1026           ReplaceWithValue(node, load, load);
   1027           return Replace(load);
   1028         }
   1029         // Compute byte offset.
   1030         Node* offset = Word32Shl(key, static_cast<int>(k));
   1031         Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer,
   1032                                       offset, length, effect, control);
   1033         ReplaceWithValue(node, load, load);
   1034         return Replace(load);
   1035       }
   1036     }
   1037   }
   1038   return NoChange();
   1039 }
   1040 
   1041 
   1042 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
   1043   Node* key = NodeProperties::GetValueInput(node, 1);
   1044   Node* base = NodeProperties::GetValueInput(node, 0);
   1045   Node* value = NodeProperties::GetValueInput(node, 2);
   1046   Type* key_type = NodeProperties::GetType(key);
   1047   Type* value_type = NodeProperties::GetType(value);
   1048   HeapObjectMatcher mbase(base);
   1049   if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
   1050     Handle<JSTypedArray> const array =
   1051         Handle<JSTypedArray>::cast(mbase.Value());
   1052     if (!array->GetBuffer()->was_neutered()) {
   1053       array->GetBuffer()->set_is_neuterable(false);
   1054       BufferAccess const access(array->type());
   1055       size_t const k =
   1056           ElementSizeLog2Of(access.machine_type().representation());
   1057       double const byte_length = array->byte_length()->Number();
   1058       CHECK_LT(k, arraysize(shifted_int32_ranges_));
   1059       if (access.external_array_type() != kExternalUint8ClampedArray &&
   1060           key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
   1061         // JSLoadProperty(typed-array, int32)
   1062         Handle<FixedTypedArrayBase> elements =
   1063             Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
   1064         Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
   1065         Node* length = jsgraph()->Constant(byte_length);
   1066         Node* context = NodeProperties::GetContextInput(node);
   1067         Node* effect = NodeProperties::GetEffectInput(node);
   1068         Node* control = NodeProperties::GetControlInput(node);
   1069         // Convert to a number first.
   1070         if (!value_type->Is(Type::Number())) {
   1071           Reduction number_reduction = ReduceJSToNumberInput(value);
   1072           if (number_reduction.Changed()) {
   1073             value = number_reduction.replacement();
   1074           } else {
   1075             Node* frame_state_for_to_number =
   1076                 NodeProperties::GetFrameStateInput(node, 1);
   1077             value = effect =
   1078                 graph()->NewNode(javascript()->ToNumber(), value, context,
   1079                                  frame_state_for_to_number, effect, control);
   1080           }
   1081         }
   1082         // Check if we can avoid the bounds check.
   1083         if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
   1084           RelaxControls(node);
   1085           node->ReplaceInput(0, buffer);
   1086           DCHECK_EQ(key, node->InputAt(1));
   1087           node->ReplaceInput(2, value);
   1088           node->ReplaceInput(3, effect);
   1089           node->ReplaceInput(4, control);
   1090           node->TrimInputCount(5);
   1091           NodeProperties::ChangeOp(
   1092               node,
   1093               simplified()->StoreElement(
   1094                   AccessBuilder::ForTypedArrayElement(array->type(), true)));
   1095           return Changed(node);
   1096         }
   1097         // Compute byte offset.
   1098         Node* offset = Word32Shl(key, static_cast<int>(k));
   1099         // Turn into a StoreBuffer operation.
   1100         RelaxControls(node);
   1101         node->ReplaceInput(0, buffer);
   1102         node->ReplaceInput(1, offset);
   1103         node->ReplaceInput(2, length);
   1104         node->ReplaceInput(3, value);
   1105         node->ReplaceInput(4, effect);
   1106         node->ReplaceInput(5, control);
   1107         node->TrimInputCount(6);
   1108         NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access));
   1109         return Changed(node);
   1110       }
   1111     }
   1112   }
   1113   return NoChange();
   1114 }
   1115 
   1116 
   1117 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
   1118   DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
   1119   Node* const context = NodeProperties::GetContextInput(node);
   1120   Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
   1121 
   1122   // If deoptimization is disabled, we cannot optimize.
   1123   if (!(flags() & kDeoptimizationEnabled) ||
   1124       (flags() & kDisableBinaryOpReduction)) {
   1125     return NoChange();
   1126   }
   1127 
   1128   // If we are in a try block, don't optimize since the runtime call
   1129   // in the proxy case can throw.
   1130   if (NodeProperties::IsExceptionalCall(node)) return NoChange();
   1131 
   1132   JSBinopReduction r(this, node);
   1133   Node* effect = r.effect();
   1134   Node* control = r.control();
   1135 
   1136   if (!r.right_type()->IsConstant() ||
   1137       !r.right_type()->AsConstant()->Value()->IsJSFunction()) {
   1138     return NoChange();
   1139   }
   1140 
   1141   Handle<JSFunction> function =
   1142       Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value());
   1143   Handle<SharedFunctionInfo> shared(function->shared(), isolate());
   1144 
   1145   if (!function->IsConstructor() ||
   1146       function->map()->has_non_instance_prototype()) {
   1147     return NoChange();
   1148   }
   1149 
   1150   JSFunction::EnsureHasInitialMap(function);
   1151   DCHECK(function->has_initial_map());
   1152   Handle<Map> initial_map(function->initial_map(), isolate());
   1153   this->dependencies()->AssumeInitialMapCantChange(initial_map);
   1154   Node* prototype =
   1155       jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
   1156 
   1157   Node* if_is_smi = nullptr;
   1158   Node* e_is_smi = nullptr;
   1159   // If the left hand side is an object, no smi check is needed.
   1160   if (r.left_type()->Maybe(Type::TaggedSigned())) {
   1161     Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
   1162     Node* branch_is_smi =
   1163         graph()->NewNode(common()->Branch(BranchHint::kFalse), is_smi, control);
   1164     if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
   1165     e_is_smi = effect;
   1166     control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
   1167   }
   1168 
   1169   Node* object_map = effect =
   1170       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
   1171                        r.left(), effect, control);
   1172 
   1173   // Loop through the {object}s prototype chain looking for the {prototype}.
   1174   Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
   1175 
   1176   Node* loop_effect = effect =
   1177       graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
   1178 
   1179   Node* loop_object_map =
   1180       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
   1181                        object_map, r.left(), loop);
   1182 
   1183   // Check if the lhs needs access checks.
   1184   Node* map_bit_field = effect =
   1185       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMapBitField()),
   1186                        loop_object_map, loop_effect, control);
   1187   int is_access_check_needed_bit = 1 << Map::kIsAccessCheckNeeded;
   1188   Node* is_access_check_needed_num =
   1189       graph()->NewNode(simplified()->NumberBitwiseAnd(), map_bit_field,
   1190                        jsgraph()->Uint32Constant(is_access_check_needed_bit));
   1191   Node* is_access_check_needed =
   1192       graph()->NewNode(machine()->Word32Equal(), is_access_check_needed_num,
   1193                        jsgraph()->Uint32Constant(is_access_check_needed_bit));
   1194 
   1195   Node* branch_is_access_check_needed = graph()->NewNode(
   1196       common()->Branch(BranchHint::kFalse), is_access_check_needed, control);
   1197   Node* if_is_access_check_needed =
   1198       graph()->NewNode(common()->IfTrue(), branch_is_access_check_needed);
   1199   Node* e_is_access_check_needed = effect;
   1200 
   1201   control =
   1202       graph()->NewNode(common()->IfFalse(), branch_is_access_check_needed);
   1203 
   1204   // Check if the lhs is a proxy.
   1205   Node* map_instance_type = effect = graph()->NewNode(
   1206       simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
   1207       loop_object_map, loop_effect, control);
   1208   Node* is_proxy = graph()->NewNode(machine()->Word32Equal(), map_instance_type,
   1209                                     jsgraph()->Uint32Constant(JS_PROXY_TYPE));
   1210   Node* branch_is_proxy =
   1211       graph()->NewNode(common()->Branch(BranchHint::kFalse), is_proxy, control);
   1212   Node* if_is_proxy = graph()->NewNode(common()->IfTrue(), branch_is_proxy);
   1213   Node* e_is_proxy = effect;
   1214 
   1215 
   1216   Node* runtime_has_in_proto_chain = control = graph()->NewNode(
   1217       common()->Merge(2), if_is_access_check_needed, if_is_proxy);
   1218   effect = graph()->NewNode(common()->EffectPhi(2), e_is_access_check_needed,
   1219                             e_is_proxy, control);
   1220 
   1221   // If we need an access check or the object is a Proxy, make a runtime call
   1222   // to finish the lowering.
   1223   Node* bool_result_runtime_has_in_proto_chain_case = graph()->NewNode(
   1224       javascript()->CallRuntime(Runtime::kHasInPrototypeChain, 2), r.left(),
   1225       prototype, context, frame_state, effect, control);
   1226 
   1227   control = graph()->NewNode(common()->IfFalse(), branch_is_proxy);
   1228 
   1229   Node* object_prototype = effect = graph()->NewNode(
   1230       simplified()->LoadField(AccessBuilder::ForMapPrototype()),
   1231       loop_object_map, loop_effect, control);
   1232 
   1233   // Check if object prototype is equal to function prototype.
   1234   Node* eq_proto =
   1235       graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
   1236                        object_prototype, prototype);
   1237   Node* branch_eq_proto =
   1238       graph()->NewNode(common()->Branch(BranchHint::kFalse), eq_proto, control);
   1239   Node* if_eq_proto = graph()->NewNode(common()->IfTrue(), branch_eq_proto);
   1240   Node* e_eq_proto = effect;
   1241 
   1242   control = graph()->NewNode(common()->IfFalse(), branch_eq_proto);
   1243 
   1244   // If not, check if object prototype is the null prototype.
   1245   Node* null_proto =
   1246       graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
   1247                        object_prototype, jsgraph()->NullConstant());
   1248   Node* branch_null_proto = graph()->NewNode(
   1249       common()->Branch(BranchHint::kFalse), null_proto, control);
   1250   Node* if_null_proto = graph()->NewNode(common()->IfTrue(), branch_null_proto);
   1251   Node* e_null_proto = effect;
   1252 
   1253   control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
   1254   Node* load_object_map = effect =
   1255       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
   1256                        object_prototype, effect, control);
   1257   // Close the loop.
   1258   loop_effect->ReplaceInput(1, effect);
   1259   loop_object_map->ReplaceInput(1, load_object_map);
   1260   loop->ReplaceInput(1, control);
   1261 
   1262   control = graph()->NewNode(common()->Merge(3), runtime_has_in_proto_chain,
   1263                              if_eq_proto, if_null_proto);
   1264   effect = graph()->NewNode(common()->EffectPhi(3),
   1265                             bool_result_runtime_has_in_proto_chain_case,
   1266                             e_eq_proto, e_null_proto, control);
   1267 
   1268   Node* result = graph()->NewNode(
   1269       common()->Phi(MachineRepresentation::kTagged, 3),
   1270       bool_result_runtime_has_in_proto_chain_case, jsgraph()->TrueConstant(),
   1271       jsgraph()->FalseConstant(), control);
   1272 
   1273   if (if_is_smi != nullptr) {
   1274     DCHECK_NOT_NULL(e_is_smi);
   1275     control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
   1276     effect =
   1277         graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
   1278     result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
   1279                               jsgraph()->FalseConstant(), result, control);
   1280   }
   1281 
   1282   ReplaceWithValue(node, result, effect, control);
   1283   return Changed(result);
   1284 }
   1285 
   1286 
   1287 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
   1288   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
   1289   ContextAccess const& access = ContextAccessOf(node->op());
   1290   Node* effect = NodeProperties::GetEffectInput(node);
   1291   Node* control = graph()->start();
   1292   for (size_t i = 0; i < access.depth(); ++i) {
   1293     Node* previous = effect = graph()->NewNode(
   1294         simplified()->LoadField(
   1295             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
   1296         NodeProperties::GetValueInput(node, 0), effect, control);
   1297     node->ReplaceInput(0, previous);
   1298   }
   1299   node->ReplaceInput(1, effect);
   1300   node->ReplaceInput(2, control);
   1301   NodeProperties::ChangeOp(
   1302       node,
   1303       simplified()->LoadField(AccessBuilder::ForContextSlot(access.index())));
   1304   return Changed(node);
   1305 }
   1306 
   1307 
   1308 Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
   1309   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
   1310   ContextAccess const& access = ContextAccessOf(node->op());
   1311   Node* effect = NodeProperties::GetEffectInput(node);
   1312   Node* control = graph()->start();
   1313   for (size_t i = 0; i < access.depth(); ++i) {
   1314     Node* previous = effect = graph()->NewNode(
   1315         simplified()->LoadField(
   1316             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
   1317         NodeProperties::GetValueInput(node, 0), effect, control);
   1318     node->ReplaceInput(0, previous);
   1319   }
   1320   node->RemoveInput(2);
   1321   node->ReplaceInput(2, effect);
   1322   NodeProperties::ChangeOp(
   1323       node,
   1324       simplified()->StoreField(AccessBuilder::ForContextSlot(access.index())));
   1325   return Changed(node);
   1326 }
   1327 
   1328 
   1329 Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
   1330   DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
   1331   ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
   1332   Node* receiver = NodeProperties::GetValueInput(node, 0);
   1333   Type* receiver_type = NodeProperties::GetType(receiver);
   1334   Node* context = NodeProperties::GetContextInput(node);
   1335   Type* context_type = NodeProperties::GetType(context);
   1336   Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
   1337   Node* effect = NodeProperties::GetEffectInput(node);
   1338   Node* control = NodeProperties::GetControlInput(node);
   1339   if (!receiver_type->Is(Type::Receiver())) {
   1340     if (receiver_type->Is(Type::NullOrUndefined()) ||
   1341         mode == ConvertReceiverMode::kNullOrUndefined) {
   1342       if (context_type->IsConstant()) {
   1343         Handle<JSObject> global_proxy(
   1344             Handle<Context>::cast(context_type->AsConstant()->Value())
   1345                 ->global_proxy(),
   1346             isolate());
   1347         receiver = jsgraph()->Constant(global_proxy);
   1348       } else {
   1349         Node* native_context = effect = graph()->NewNode(
   1350             javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1351             context, context, effect);
   1352         receiver = effect = graph()->NewNode(
   1353             javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
   1354             native_context, native_context, effect);
   1355       }
   1356     } else if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
   1357                mode == ConvertReceiverMode::kNotNullOrUndefined) {
   1358       receiver = effect =
   1359           graph()->NewNode(javascript()->ToObject(), receiver, context,
   1360                            frame_state, effect, control);
   1361     } else {
   1362       // Check {receiver} for undefined.
   1363       Node* check0 =
   1364           graph()->NewNode(simplified()->ReferenceEqual(receiver_type),
   1365                            receiver, jsgraph()->UndefinedConstant());
   1366       Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
   1367                                        check0, control);
   1368       Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   1369       Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   1370 
   1371       // Check {receiver} for null.
   1372       Node* check1 =
   1373           graph()->NewNode(simplified()->ReferenceEqual(receiver_type),
   1374                            receiver, jsgraph()->NullConstant());
   1375       Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
   1376                                        check1, if_false0);
   1377       Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   1378       Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   1379 
   1380       // Convert {receiver} using ToObject.
   1381       Node* if_convert = if_false1;
   1382       Node* econvert = effect;
   1383       Node* rconvert;
   1384       {
   1385         rconvert = econvert =
   1386             graph()->NewNode(javascript()->ToObject(), receiver, context,
   1387                              frame_state, econvert, if_convert);
   1388       }
   1389 
   1390       // Replace {receiver} with global proxy of {context}.
   1391       Node* if_global =
   1392           graph()->NewNode(common()->Merge(2), if_true0, if_true1);
   1393       Node* eglobal = effect;
   1394       Node* rglobal;
   1395       {
   1396         if (context_type->IsConstant()) {
   1397           Handle<JSObject> global_proxy(
   1398               Handle<Context>::cast(context_type->AsConstant()->Value())
   1399                   ->global_proxy(),
   1400               isolate());
   1401           rglobal = jsgraph()->Constant(global_proxy);
   1402         } else {
   1403           Node* native_context = eglobal = graph()->NewNode(
   1404               javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1405               context, context, eglobal);
   1406           rglobal = eglobal = graph()->NewNode(
   1407               javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
   1408               native_context, native_context, eglobal);
   1409         }
   1410       }
   1411 
   1412       control = graph()->NewNode(common()->Merge(2), if_convert, if_global);
   1413       effect =
   1414           graph()->NewNode(common()->EffectPhi(2), econvert, eglobal, control);
   1415       receiver =
   1416           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
   1417                            rconvert, rglobal, control);
   1418     }
   1419   }
   1420   ReplaceWithValue(node, receiver, effect, control);
   1421   return Changed(receiver);
   1422 }
   1423 
   1424 
   1425 namespace {
   1426 
   1427 // Maximum instance size for which allocations will be inlined.
   1428 const int kMaxInlineInstanceSize = 64 * kPointerSize;
   1429 
   1430 
   1431 // Checks whether allocation using the given constructor can be inlined.
   1432 bool IsAllocationInlineable(Handle<JSFunction> constructor) {
   1433   // TODO(bmeurer): Further relax restrictions on inlining, i.e.
   1434   // instance type and maybe instance size (inobject properties
   1435   // are limited anyways by the runtime).
   1436   return constructor->has_initial_map() &&
   1437          constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
   1438          constructor->initial_map()->instance_size() < kMaxInlineInstanceSize;
   1439 }
   1440 
   1441 }  // namespace
   1442 
   1443 
   1444 Reduction JSTypedLowering::ReduceJSCreate(Node* node) {
   1445   DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
   1446   Node* const target = NodeProperties::GetValueInput(node, 0);
   1447   Type* const target_type = NodeProperties::GetType(target);
   1448   Node* const new_target = NodeProperties::GetValueInput(node, 1);
   1449   Node* const effect = NodeProperties::GetEffectInput(node);
   1450   // TODO(turbofan): Add support for NewTarget passed to JSCreate.
   1451   if (target != new_target) return NoChange();
   1452   // Extract constructor function.
   1453   if (target_type->IsConstant() &&
   1454       target_type->AsConstant()->Value()->IsJSFunction()) {
   1455     Handle<JSFunction> constructor =
   1456         Handle<JSFunction>::cast(target_type->AsConstant()->Value());
   1457     DCHECK(constructor->IsConstructor());
   1458     // Force completion of inobject slack tracking before
   1459     // generating code to finalize the instance size.
   1460     constructor->CompleteInobjectSlackTrackingIfActive();
   1461 
   1462     // TODO(bmeurer): We fall back to the runtime in case we cannot inline
   1463     // the allocation here, which is sort of expensive. We should think about
   1464     // a soft fallback to some NewObjectCodeStub.
   1465     if (IsAllocationInlineable(constructor)) {
   1466       // Compute instance size from initial map of {constructor}.
   1467       Handle<Map> initial_map(constructor->initial_map(), isolate());
   1468       int const instance_size = initial_map->instance_size();
   1469 
   1470       // Add a dependency on the {initial_map} to make sure that this code is
   1471       // deoptimized whenever the {initial_map} of the {constructor} changes.
   1472       dependencies()->AssumeInitialMapCantChange(initial_map);
   1473 
   1474       // Emit code to allocate the JSObject instance for the {constructor}.
   1475       AllocationBuilder a(jsgraph(), effect, graph()->start());
   1476       a.Allocate(instance_size);
   1477       a.Store(AccessBuilder::ForMap(), initial_map);
   1478       a.Store(AccessBuilder::ForJSObjectProperties(),
   1479               jsgraph()->EmptyFixedArrayConstant());
   1480       a.Store(AccessBuilder::ForJSObjectElements(),
   1481               jsgraph()->EmptyFixedArrayConstant());
   1482       for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) {
   1483         a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
   1484                 jsgraph()->UndefinedConstant());
   1485       }
   1486       a.FinishAndChange(node);
   1487       return Changed(node);
   1488     }
   1489   }
   1490   return NoChange();
   1491 }
   1492 
   1493 
   1494 namespace {
   1495 
   1496 // Retrieves the frame state holding actual argument values.
   1497 Node* GetArgumentsFrameState(Node* frame_state) {
   1498   Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
   1499   FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state);
   1500   return outer_state_info.type() == FrameStateType::kArgumentsAdaptor
   1501              ? outer_state
   1502              : frame_state;
   1503 }
   1504 
   1505 }  // namespace
   1506 
   1507 
   1508 Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) {
   1509   DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
   1510   CreateArgumentsParameters const& p = CreateArgumentsParametersOf(node->op());
   1511   Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
   1512   Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
   1513   FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
   1514 
   1515   // Use the ArgumentsAccessStub for materializing both mapped and unmapped
   1516   // arguments object, but only for non-inlined (i.e. outermost) frames.
   1517   if (outer_state->opcode() != IrOpcode::kFrameState) {
   1518     Isolate* isolate = jsgraph()->isolate();
   1519     int parameter_count = state_info.parameter_count() - 1;
   1520     int parameter_offset = parameter_count * kPointerSize;
   1521     int offset = StandardFrameConstants::kCallerSPOffset + parameter_offset;
   1522     Node* parameter_pointer = graph()->NewNode(
   1523         machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()),
   1524         jsgraph()->IntPtrConstant(offset));
   1525 
   1526     if (p.type() != CreateArgumentsParameters::kRestArray) {
   1527       Handle<SharedFunctionInfo> shared;
   1528       if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
   1529       bool unmapped = p.type() == CreateArgumentsParameters::kUnmappedArguments;
   1530       Callable callable = CodeFactory::ArgumentsAccess(
   1531           isolate, unmapped, shared->has_duplicate_parameters());
   1532       CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1533           isolate, graph()->zone(), callable.descriptor(), 0,
   1534           CallDescriptor::kNeedsFrameState);
   1535       const Operator* new_op = common()->Call(desc);
   1536       Node* stub_code = jsgraph()->HeapConstant(callable.code());
   1537       node->InsertInput(graph()->zone(), 0, stub_code);
   1538       node->InsertInput(graph()->zone(), 2,
   1539                         jsgraph()->Constant(parameter_count));
   1540       node->InsertInput(graph()->zone(), 3, parameter_pointer);
   1541       NodeProperties::ChangeOp(node, new_op);
   1542       return Changed(node);
   1543     } else {
   1544       Callable callable = CodeFactory::RestArgumentsAccess(isolate);
   1545       CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1546           isolate, graph()->zone(), callable.descriptor(), 0,
   1547           CallDescriptor::kNeedsFrameState);
   1548       const Operator* new_op = common()->Call(desc);
   1549       Node* stub_code = jsgraph()->HeapConstant(callable.code());
   1550       node->InsertInput(graph()->zone(), 0, stub_code);
   1551       node->ReplaceInput(1, jsgraph()->Constant(parameter_count));
   1552       node->InsertInput(graph()->zone(), 2, parameter_pointer);
   1553       node->InsertInput(graph()->zone(), 3,
   1554                         jsgraph()->Constant(p.start_index()));
   1555       NodeProperties::ChangeOp(node, new_op);
   1556       return Changed(node);
   1557     }
   1558   } else if (outer_state->opcode() == IrOpcode::kFrameState) {
   1559     // Use inline allocation for all mapped arguments objects within inlined
   1560     // (i.e. non-outermost) frames, independent of the object size.
   1561     if (p.type() == CreateArgumentsParameters::kMappedArguments) {
   1562       Handle<SharedFunctionInfo> shared;
   1563       if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
   1564       Node* const callee = NodeProperties::GetValueInput(node, 0);
   1565       Node* const control = NodeProperties::GetControlInput(node);
   1566       Node* const context = NodeProperties::GetContextInput(node);
   1567       Node* effect = NodeProperties::GetEffectInput(node);
   1568       // TODO(mstarzinger): Duplicate parameters are not handled yet.
   1569       if (shared->has_duplicate_parameters()) return NoChange();
   1570       // Choose the correct frame state and frame state info depending on
   1571       // whether there conceptually is an arguments adaptor frame in the call
   1572       // chain.
   1573       Node* const args_state = GetArgumentsFrameState(frame_state);
   1574       FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
   1575       // Prepare element backing store to be used by arguments object.
   1576       bool has_aliased_arguments = false;
   1577       Node* const elements = AllocateAliasedArguments(
   1578           effect, control, args_state, context, shared, &has_aliased_arguments);
   1579       effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
   1580       // Load the arguments object map from the current native context.
   1581       Node* const load_native_context = effect = graph()->NewNode(
   1582           javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1583           context, context, effect);
   1584       Node* const load_arguments_map = effect = graph()->NewNode(
   1585           simplified()->LoadField(AccessBuilder::ForContextSlot(
   1586               has_aliased_arguments ? Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX
   1587                                     : Context::SLOPPY_ARGUMENTS_MAP_INDEX)),
   1588           load_native_context, effect, control);
   1589       // Actually allocate and initialize the arguments object.
   1590       AllocationBuilder a(jsgraph(), effect, control);
   1591       Node* properties = jsgraph()->EmptyFixedArrayConstant();
   1592       int length = args_state_info.parameter_count() - 1;  // Minus receiver.
   1593       STATIC_ASSERT(Heap::kSloppyArgumentsObjectSize == 5 * kPointerSize);
   1594       a.Allocate(Heap::kSloppyArgumentsObjectSize);
   1595       a.Store(AccessBuilder::ForMap(), load_arguments_map);
   1596       a.Store(AccessBuilder::ForJSObjectProperties(), properties);
   1597       a.Store(AccessBuilder::ForJSObjectElements(), elements);
   1598       a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
   1599       a.Store(AccessBuilder::ForArgumentsCallee(), callee);
   1600       RelaxControls(node);
   1601       a.FinishAndChange(node);
   1602       return Changed(node);
   1603     } else if (p.type() == CreateArgumentsParameters::kUnmappedArguments) {
   1604       // Use inline allocation for all unmapped arguments objects within inlined
   1605       // (i.e. non-outermost) frames, independent of the object size.
   1606       Node* const control = NodeProperties::GetControlInput(node);
   1607       Node* const context = NodeProperties::GetContextInput(node);
   1608       Node* effect = NodeProperties::GetEffectInput(node);
   1609       // Choose the correct frame state and frame state info depending on
   1610       // whether there conceptually is an arguments adaptor frame in the call
   1611       // chain.
   1612       Node* const args_state = GetArgumentsFrameState(frame_state);
   1613       FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
   1614       // Prepare element backing store to be used by arguments object.
   1615       Node* const elements = AllocateArguments(effect, control, args_state);
   1616       effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
   1617       // Load the arguments object map from the current native context.
   1618       Node* const load_native_context = effect = graph()->NewNode(
   1619           javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1620           context, context, effect);
   1621       Node* const load_arguments_map = effect = graph()->NewNode(
   1622           simplified()->LoadField(AccessBuilder::ForContextSlot(
   1623               Context::STRICT_ARGUMENTS_MAP_INDEX)),
   1624           load_native_context, effect, control);
   1625       // Actually allocate and initialize the arguments object.
   1626       AllocationBuilder a(jsgraph(), effect, control);
   1627       Node* properties = jsgraph()->EmptyFixedArrayConstant();
   1628       int length = args_state_info.parameter_count() - 1;  // Minus receiver.
   1629       STATIC_ASSERT(Heap::kStrictArgumentsObjectSize == 4 * kPointerSize);
   1630       a.Allocate(Heap::kStrictArgumentsObjectSize);
   1631       a.Store(AccessBuilder::ForMap(), load_arguments_map);
   1632       a.Store(AccessBuilder::ForJSObjectProperties(), properties);
   1633       a.Store(AccessBuilder::ForJSObjectElements(), elements);
   1634       a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
   1635       RelaxControls(node);
   1636       a.FinishAndChange(node);
   1637       return Changed(node);
   1638     } else if (p.type() == CreateArgumentsParameters::kRestArray) {
   1639       // Use inline allocation for all unmapped arguments objects within inlined
   1640       // (i.e. non-outermost) frames, independent of the object size.
   1641       Node* const control = NodeProperties::GetControlInput(node);
   1642       Node* const context = NodeProperties::GetContextInput(node);
   1643       Node* effect = NodeProperties::GetEffectInput(node);
   1644       // Choose the correct frame state and frame state info depending on
   1645       // whether there conceptually is an arguments adaptor frame in the call
   1646       // chain.
   1647       Node* const args_state = GetArgumentsFrameState(frame_state);
   1648       FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
   1649       // Prepare element backing store to be used by the rest array.
   1650       Node* const elements =
   1651           AllocateRestArguments(effect, control, args_state, p.start_index());
   1652       effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
   1653       // Load the JSArray object map from the current native context.
   1654       Node* const load_native_context = effect = graph()->NewNode(
   1655           javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1656           context, context, effect);
   1657       Node* const load_jsarray_map = effect = graph()->NewNode(
   1658           simplified()->LoadField(AccessBuilder::ForContextSlot(
   1659               Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX)),
   1660           load_native_context, effect, control);
   1661       // Actually allocate and initialize the jsarray.
   1662       AllocationBuilder a(jsgraph(), effect, control);
   1663       Node* properties = jsgraph()->EmptyFixedArrayConstant();
   1664 
   1665       // -1 to minus receiver
   1666       int argument_count = args_state_info.parameter_count() - 1;
   1667       int length = std::max(0, argument_count - p.start_index());
   1668       STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
   1669       a.Allocate(JSArray::kSize);
   1670       a.Store(AccessBuilder::ForMap(), load_jsarray_map);
   1671       a.Store(AccessBuilder::ForJSObjectProperties(), properties);
   1672       a.Store(AccessBuilder::ForJSObjectElements(), elements);
   1673       a.Store(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS),
   1674               jsgraph()->Constant(length));
   1675       RelaxControls(node);
   1676       a.FinishAndChange(node);
   1677       return Changed(node);
   1678     }
   1679   }
   1680 
   1681   return NoChange();
   1682 }
   1683 
   1684 
   1685 Reduction JSTypedLowering::ReduceNewArray(Node* node, Node* length,
   1686                                           int capacity,
   1687                                           Handle<AllocationSite> site) {
   1688   DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
   1689   Node* context = NodeProperties::GetContextInput(node);
   1690   Node* effect = NodeProperties::GetEffectInput(node);
   1691   Node* control = NodeProperties::GetControlInput(node);
   1692 
   1693   // Extract transition and tenuring feedback from the {site} and add
   1694   // appropriate code dependencies on the {site} if deoptimization is
   1695   // enabled.
   1696   PretenureFlag pretenure = site->GetPretenureMode();
   1697   ElementsKind elements_kind = site->GetElementsKind();
   1698   DCHECK(IsFastElementsKind(elements_kind));
   1699   if (flags() & kDeoptimizationEnabled) {
   1700     dependencies()->AssumeTenuringDecision(site);
   1701     dependencies()->AssumeTransitionStable(site);
   1702   }
   1703 
   1704   // Retrieve the initial map for the array from the appropriate native context.
   1705   Node* native_context = effect = graph()->NewNode(
   1706       javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1707       context, context, effect);
   1708   Node* js_array_map = effect = graph()->NewNode(
   1709       javascript()->LoadContext(0, Context::ArrayMapIndex(elements_kind), true),
   1710       native_context, native_context, effect);
   1711 
   1712   // Setup elements and properties.
   1713   Node* elements;
   1714   if (capacity == 0) {
   1715     elements = jsgraph()->EmptyFixedArrayConstant();
   1716   } else {
   1717     elements = effect =
   1718         AllocateElements(effect, control, elements_kind, capacity, pretenure);
   1719   }
   1720   Node* properties = jsgraph()->EmptyFixedArrayConstant();
   1721 
   1722   // Perform the allocation of the actual JSArray object.
   1723   AllocationBuilder a(jsgraph(), effect, control);
   1724   a.Allocate(JSArray::kSize, pretenure);
   1725   a.Store(AccessBuilder::ForMap(), js_array_map);
   1726   a.Store(AccessBuilder::ForJSObjectProperties(), properties);
   1727   a.Store(AccessBuilder::ForJSObjectElements(), elements);
   1728   a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
   1729   RelaxControls(node);
   1730   a.FinishAndChange(node);
   1731   return Changed(node);
   1732 }
   1733 
   1734 
   1735 Reduction JSTypedLowering::ReduceJSCreateArray(Node* node) {
   1736   DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
   1737   CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
   1738   Node* target = NodeProperties::GetValueInput(node, 0);
   1739   Node* new_target = NodeProperties::GetValueInput(node, 1);
   1740 
   1741   // TODO(bmeurer): Optimize the subclassing case.
   1742   if (target != new_target) return NoChange();
   1743 
   1744   // Check if we have a feedback {site} on the {node}.
   1745   Handle<AllocationSite> site = p.site();
   1746   if (p.site().is_null()) return NoChange();
   1747 
   1748   // Attempt to inline calls to the Array constructor for the relevant cases
   1749   // where either no arguments are provided, or exactly one unsigned number
   1750   // argument is given.
   1751   if (site->CanInlineCall()) {
   1752     if (p.arity() == 0) {
   1753       Node* length = jsgraph()->ZeroConstant();
   1754       int capacity = JSArray::kPreallocatedArrayElements;
   1755       return ReduceNewArray(node, length, capacity, site);
   1756     } else if (p.arity() == 1) {
   1757       Node* length = NodeProperties::GetValueInput(node, 2);
   1758       Type* length_type = NodeProperties::GetType(length);
   1759       if (length_type->Is(type_cache_.kElementLoopUnrollType)) {
   1760         int capacity = static_cast<int>(length_type->Max());
   1761         return ReduceNewArray(node, length, capacity, site);
   1762       }
   1763     }
   1764   }
   1765 
   1766   // Reduce {node} to the appropriate ArrayConstructorStub backend.
   1767   // Note that these stubs "behave" like JSFunctions, which means they
   1768   // expect a receiver on the stack, which they remove. We just push
   1769   // undefined for the receiver.
   1770   ElementsKind elements_kind = site->GetElementsKind();
   1771   AllocationSiteOverrideMode override_mode =
   1772       (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE)
   1773           ? DISABLE_ALLOCATION_SITES
   1774           : DONT_OVERRIDE;
   1775   if (p.arity() == 0) {
   1776     ArrayNoArgumentConstructorStub stub(isolate(), elements_kind,
   1777                                         override_mode);
   1778     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1779         isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 1,
   1780         CallDescriptor::kNeedsFrameState);
   1781     node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
   1782     node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
   1783     node->InsertInput(graph()->zone(), 3, jsgraph()->UndefinedConstant());
   1784     NodeProperties::ChangeOp(node, common()->Call(desc));
   1785     return Changed(node);
   1786   } else if (p.arity() == 1) {
   1787     // TODO(bmeurer): Optimize for the 0 length non-holey case?
   1788     ArraySingleArgumentConstructorStub stub(
   1789         isolate(), GetHoleyElementsKind(elements_kind), override_mode);
   1790     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1791         isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2,
   1792         CallDescriptor::kNeedsFrameState);
   1793     node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
   1794     node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
   1795     node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(1));
   1796     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
   1797     NodeProperties::ChangeOp(node, common()->Call(desc));
   1798     return Changed(node);
   1799   } else {
   1800     int const arity = static_cast<int>(p.arity());
   1801     ArrayNArgumentsConstructorStub stub(isolate(), elements_kind,
   1802                                         override_mode);
   1803     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1804         isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
   1805         arity + 1, CallDescriptor::kNeedsFrameState);
   1806     node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
   1807     node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
   1808     node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
   1809     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
   1810     NodeProperties::ChangeOp(node, common()->Call(desc));
   1811     return Changed(node);
   1812   }
   1813 }
   1814 
   1815 
   1816 Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) {
   1817   DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
   1818   CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
   1819   Handle<SharedFunctionInfo> shared = p.shared_info();
   1820 
   1821   // Use the FastNewClosureStub that allocates in new space only for nested
   1822   // functions that don't need literals cloning.
   1823   if (p.pretenure() == NOT_TENURED && shared->num_literals() == 0) {
   1824     Isolate* isolate = jsgraph()->isolate();
   1825     Callable callable = CodeFactory::FastNewClosure(
   1826         isolate, shared->language_mode(), shared->kind());
   1827     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1828         isolate, graph()->zone(), callable.descriptor(), 0,
   1829         CallDescriptor::kNoFlags);
   1830     const Operator* new_op = common()->Call(desc);
   1831     Node* stub_code = jsgraph()->HeapConstant(callable.code());
   1832     node->InsertInput(graph()->zone(), 0, stub_code);
   1833     node->InsertInput(graph()->zone(), 1, jsgraph()->HeapConstant(shared));
   1834     NodeProperties::ChangeOp(node, new_op);
   1835     return Changed(node);
   1836   }
   1837 
   1838   return NoChange();
   1839 }
   1840 
   1841 
   1842 Reduction JSTypedLowering::ReduceJSCreateIterResultObject(Node* node) {
   1843   DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
   1844   Node* value = NodeProperties::GetValueInput(node, 0);
   1845   Node* done = NodeProperties::GetValueInput(node, 1);
   1846   Node* context = NodeProperties::GetContextInput(node);
   1847   Node* effect = NodeProperties::GetEffectInput(node);
   1848 
   1849   // Load the JSIteratorResult map for the {context}.
   1850   Node* native_context = effect = graph()->NewNode(
   1851       javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1852       context, context, effect);
   1853   Node* iterator_result_map = effect = graph()->NewNode(
   1854       javascript()->LoadContext(0, Context::ITERATOR_RESULT_MAP_INDEX, true),
   1855       native_context, native_context, effect);
   1856 
   1857   // Emit code to allocate the JSIteratorResult instance.
   1858   AllocationBuilder a(jsgraph(), effect, graph()->start());
   1859   a.Allocate(JSIteratorResult::kSize);
   1860   a.Store(AccessBuilder::ForMap(), iterator_result_map);
   1861   a.Store(AccessBuilder::ForJSObjectProperties(),
   1862           jsgraph()->EmptyFixedArrayConstant());
   1863   a.Store(AccessBuilder::ForJSObjectElements(),
   1864           jsgraph()->EmptyFixedArrayConstant());
   1865   a.Store(AccessBuilder::ForJSIteratorResultValue(), value);
   1866   a.Store(AccessBuilder::ForJSIteratorResultDone(), done);
   1867   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
   1868   a.FinishAndChange(node);
   1869   return Changed(node);
   1870 }
   1871 
   1872 
   1873 Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
   1874   DCHECK_EQ(IrOpcode::kJSCreateLiteralArray, node->opcode());
   1875   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
   1876   Handle<FixedArray> const constants = Handle<FixedArray>::cast(p.constant());
   1877   int const length = constants->length();
   1878   int const flags = p.flags();
   1879 
   1880   // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
   1881   // initial length limit for arrays with "fast" elements kind.
   1882   // TODO(rossberg): Teach strong mode to FastCloneShallowArrayStub.
   1883   if ((flags & ArrayLiteral::kShallowElements) != 0 &&
   1884       (flags & ArrayLiteral::kIsStrong) == 0 &&
   1885       length < JSArray::kInitialMaxFastElementArray) {
   1886     Isolate* isolate = jsgraph()->isolate();
   1887     Callable callable = CodeFactory::FastCloneShallowArray(isolate);
   1888     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1889         isolate, graph()->zone(), callable.descriptor(), 0,
   1890         (OperatorProperties::GetFrameStateInputCount(node->op()) != 0)
   1891             ? CallDescriptor::kNeedsFrameState
   1892             : CallDescriptor::kNoFlags);
   1893     const Operator* new_op = common()->Call(desc);
   1894     Node* stub_code = jsgraph()->HeapConstant(callable.code());
   1895     Node* literal_index = jsgraph()->SmiConstant(p.index());
   1896     Node* constant_elements = jsgraph()->HeapConstant(constants);
   1897     node->InsertInput(graph()->zone(), 0, stub_code);
   1898     node->InsertInput(graph()->zone(), 2, literal_index);
   1899     node->InsertInput(graph()->zone(), 3, constant_elements);
   1900     NodeProperties::ChangeOp(node, new_op);
   1901     return Changed(node);
   1902   }
   1903 
   1904   return NoChange();
   1905 }
   1906 
   1907 
   1908 Reduction JSTypedLowering::ReduceJSCreateLiteralObject(Node* node) {
   1909   DCHECK_EQ(IrOpcode::kJSCreateLiteralObject, node->opcode());
   1910   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
   1911   Handle<FixedArray> const constants = Handle<FixedArray>::cast(p.constant());
   1912   // Constants are pairs, see ObjectLiteral::properties_count().
   1913   int const length = constants->length() / 2;
   1914   int const flags = p.flags();
   1915 
   1916   // Use the FastCloneShallowObjectStub only for shallow boilerplates without
   1917   // elements up to the number of properties that the stubs can handle.
   1918   if ((flags & ObjectLiteral::kShallowProperties) != 0 &&
   1919       length <= FastCloneShallowObjectStub::kMaximumClonedProperties) {
   1920     Isolate* isolate = jsgraph()->isolate();
   1921     Callable callable = CodeFactory::FastCloneShallowObject(isolate, length);
   1922     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1923         isolate, graph()->zone(), callable.descriptor(), 0,
   1924         (OperatorProperties::GetFrameStateInputCount(node->op()) != 0)
   1925             ? CallDescriptor::kNeedsFrameState
   1926             : CallDescriptor::kNoFlags);
   1927     const Operator* new_op = common()->Call(desc);
   1928     Node* stub_code = jsgraph()->HeapConstant(callable.code());
   1929     Node* literal_index = jsgraph()->SmiConstant(p.index());
   1930     Node* literal_flags = jsgraph()->SmiConstant(flags);
   1931     Node* constant_elements = jsgraph()->HeapConstant(constants);
   1932     node->InsertInput(graph()->zone(), 0, stub_code);
   1933     node->InsertInput(graph()->zone(), 2, literal_index);
   1934     node->InsertInput(graph()->zone(), 3, constant_elements);
   1935     node->InsertInput(graph()->zone(), 4, literal_flags);
   1936     NodeProperties::ChangeOp(node, new_op);
   1937     return Changed(node);
   1938   }
   1939 
   1940   return NoChange();
   1941 }
   1942 
   1943 
   1944 Reduction JSTypedLowering::ReduceJSCreateFunctionContext(Node* node) {
   1945   DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
   1946   int slot_count = OpParameter<int>(node->op());
   1947   Node* const closure = NodeProperties::GetValueInput(node, 0);
   1948 
   1949   // Use inline allocation for function contexts up to a size limit.
   1950   if (slot_count < kFunctionContextAllocationLimit) {
   1951     // JSCreateFunctionContext[slot_count < limit]](fun)
   1952     Node* effect = NodeProperties::GetEffectInput(node);
   1953     Node* control = NodeProperties::GetControlInput(node);
   1954     Node* context = NodeProperties::GetContextInput(node);
   1955     Node* extension = jsgraph()->TheHoleConstant();
   1956     Node* native_context = effect = graph()->NewNode(
   1957         javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1958         context, context, effect);
   1959     AllocationBuilder a(jsgraph(), effect, control);
   1960     STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
   1961     int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
   1962     a.AllocateArray(context_length, factory()->function_context_map());
   1963     a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
   1964     a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
   1965     a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
   1966     a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
   1967             native_context);
   1968     for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
   1969       a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
   1970     }
   1971     RelaxControls(node);
   1972     a.FinishAndChange(node);
   1973     return Changed(node);
   1974   }
   1975 
   1976   // Use the FastNewContextStub only for function contexts up maximum size.
   1977   if (slot_count <= FastNewContextStub::kMaximumSlots) {
   1978     Isolate* isolate = jsgraph()->isolate();
   1979     Callable callable = CodeFactory::FastNewContext(isolate, slot_count);
   1980     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   1981         isolate, graph()->zone(), callable.descriptor(), 0,
   1982         CallDescriptor::kNoFlags);
   1983     const Operator* new_op = common()->Call(desc);
   1984     Node* stub_code = jsgraph()->HeapConstant(callable.code());
   1985     node->InsertInput(graph()->zone(), 0, stub_code);
   1986     NodeProperties::ChangeOp(node, new_op);
   1987     return Changed(node);
   1988   }
   1989 
   1990   return NoChange();
   1991 }
   1992 
   1993 
   1994 Reduction JSTypedLowering::ReduceJSCreateWithContext(Node* node) {
   1995   DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode());
   1996   Node* object = NodeProperties::GetValueInput(node, 0);
   1997   Node* closure = NodeProperties::GetValueInput(node, 1);
   1998   Node* effect = NodeProperties::GetEffectInput(node);
   1999   Node* control = NodeProperties::GetControlInput(node);
   2000   Node* context = NodeProperties::GetContextInput(node);
   2001   Node* native_context = effect = graph()->NewNode(
   2002       javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   2003       context, context, effect);
   2004   AllocationBuilder a(jsgraph(), effect, control);
   2005   STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
   2006   a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map());
   2007   a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
   2008   a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
   2009   a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), object);
   2010   a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
   2011           native_context);
   2012   RelaxControls(node);
   2013   a.FinishAndChange(node);
   2014   return Changed(node);
   2015 }
   2016 
   2017 
   2018 Reduction JSTypedLowering::ReduceJSCreateCatchContext(Node* node) {
   2019   DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode());
   2020   Handle<String> name = OpParameter<Handle<String>>(node);
   2021   Node* exception = NodeProperties::GetValueInput(node, 0);
   2022   Node* closure = NodeProperties::GetValueInput(node, 1);
   2023   Node* effect = NodeProperties::GetEffectInput(node);
   2024   Node* control = NodeProperties::GetControlInput(node);
   2025   Node* context = NodeProperties::GetContextInput(node);
   2026   Node* native_context = effect = graph()->NewNode(
   2027       javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   2028       context, context, effect);
   2029   AllocationBuilder a(jsgraph(), effect, control);
   2030   STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
   2031   a.AllocateArray(Context::MIN_CONTEXT_SLOTS + 1,
   2032                   factory()->catch_context_map());
   2033   a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
   2034   a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
   2035   a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), name);
   2036   a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
   2037           native_context);
   2038   a.Store(AccessBuilder::ForContextSlot(Context::THROWN_OBJECT_INDEX),
   2039           exception);
   2040   RelaxControls(node);
   2041   a.FinishAndChange(node);
   2042   return Changed(node);
   2043 }
   2044 
   2045 
   2046 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) {
   2047   DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode());
   2048   Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
   2049   int context_length = scope_info->ContextLength();
   2050   Node* const closure = NodeProperties::GetValueInput(node, 0);
   2051 
   2052   // Use inline allocation for block contexts up to a size limit.
   2053   if (context_length < kBlockContextAllocationLimit) {
   2054     // JSCreateBlockContext[scope[length < limit]](fun)
   2055     Node* effect = NodeProperties::GetEffectInput(node);
   2056     Node* control = NodeProperties::GetControlInput(node);
   2057     Node* context = NodeProperties::GetContextInput(node);
   2058     Node* extension = jsgraph()->Constant(scope_info);
   2059     Node* native_context = effect = graph()->NewNode(
   2060         javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   2061         context, context, effect);
   2062     AllocationBuilder a(jsgraph(), effect, control);
   2063     STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
   2064     a.AllocateArray(context_length, factory()->block_context_map());
   2065     a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
   2066     a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
   2067     a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
   2068     a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
   2069             native_context);
   2070     for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
   2071       a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
   2072     }
   2073     RelaxControls(node);
   2074     a.FinishAndChange(node);
   2075     return Changed(node);
   2076   }
   2077 
   2078   return NoChange();
   2079 }
   2080 
   2081 
   2082 Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
   2083   DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
   2084   CallConstructParameters const& p = CallConstructParametersOf(node->op());
   2085   DCHECK_LE(2u, p.arity());
   2086   int const arity = static_cast<int>(p.arity() - 2);
   2087   Node* target = NodeProperties::GetValueInput(node, 0);
   2088   Type* target_type = NodeProperties::GetType(target);
   2089   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
   2090 
   2091   // Check if {target} is a known JSFunction.
   2092   if (target_type->IsConstant() &&
   2093       target_type->AsConstant()->Value()->IsJSFunction()) {
   2094     Handle<JSFunction> function =
   2095         Handle<JSFunction>::cast(target_type->AsConstant()->Value());
   2096     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
   2097 
   2098     // Remove the eager bailout frame state.
   2099     NodeProperties::RemoveFrameStateInput(node, 1);
   2100 
   2101     // Patch {node} to an indirect call via the {function}s construct stub.
   2102     Callable callable(handle(shared->construct_stub(), isolate()),
   2103                       ConstructStubDescriptor(isolate()));
   2104     node->RemoveInput(arity + 1);
   2105     node->InsertInput(graph()->zone(), 0,
   2106                       jsgraph()->HeapConstant(callable.code()));
   2107     node->InsertInput(graph()->zone(), 2, new_target);
   2108     node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
   2109     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
   2110     node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
   2111     NodeProperties::ChangeOp(
   2112         node, common()->Call(Linkage::GetStubCallDescriptor(
   2113                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
   2114                   CallDescriptor::kNeedsFrameState)));
   2115     return Changed(node);
   2116   }
   2117 
   2118   // Check if {target} is a JSFunction.
   2119   if (target_type->Is(Type::Function())) {
   2120     // Remove the eager bailout frame state.
   2121     NodeProperties::RemoveFrameStateInput(node, 1);
   2122 
   2123     // Patch {node} to an indirect call via the ConstructFunction builtin.
   2124     Callable callable = CodeFactory::ConstructFunction(isolate());
   2125     node->RemoveInput(arity + 1);
   2126     node->InsertInput(graph()->zone(), 0,
   2127                       jsgraph()->HeapConstant(callable.code()));
   2128     node->InsertInput(graph()->zone(), 2, new_target);
   2129     node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
   2130     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
   2131     NodeProperties::ChangeOp(
   2132         node, common()->Call(Linkage::GetStubCallDescriptor(
   2133                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
   2134                   CallDescriptor::kNeedsFrameState)));
   2135     return Changed(node);
   2136   }
   2137 
   2138   return NoChange();
   2139 }
   2140 
   2141 
   2142 Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
   2143   DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
   2144   CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
   2145   int const arity = static_cast<int>(p.arity() - 2);
   2146   ConvertReceiverMode convert_mode = p.convert_mode();
   2147   Node* target = NodeProperties::GetValueInput(node, 0);
   2148   Type* target_type = NodeProperties::GetType(target);
   2149   Node* receiver = NodeProperties::GetValueInput(node, 1);
   2150   Type* receiver_type = NodeProperties::GetType(receiver);
   2151   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   2152   Node* effect = NodeProperties::GetEffectInput(node);
   2153   Node* control = NodeProperties::GetControlInput(node);
   2154 
   2155   // Try to infer receiver {convert_mode} from {receiver} type.
   2156   if (receiver_type->Is(Type::NullOrUndefined())) {
   2157     convert_mode = ConvertReceiverMode::kNullOrUndefined;
   2158   } else if (!receiver_type->Maybe(Type::NullOrUndefined())) {
   2159     convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
   2160   }
   2161 
   2162   // Check if {target} is a known JSFunction.
   2163   if (target_type->IsConstant() &&
   2164       target_type->AsConstant()->Value()->IsJSFunction()) {
   2165     Handle<JSFunction> function =
   2166         Handle<JSFunction>::cast(target_type->AsConstant()->Value());
   2167     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
   2168 
   2169     // Class constructors are callable, but [[Call]] will raise an exception.
   2170     // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
   2171     if (IsClassConstructor(shared->kind())) return NoChange();
   2172 
   2173     // Load the context from the {target}.
   2174     Node* context = effect = graph()->NewNode(
   2175         simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
   2176         effect, control);
   2177     NodeProperties::ReplaceContextInput(node, context);
   2178 
   2179     // Check if we need to convert the {receiver}.
   2180     if (is_sloppy(shared->language_mode()) && !shared->native() &&
   2181         !receiver_type->Is(Type::Receiver())) {
   2182       receiver = effect =
   2183           graph()->NewNode(javascript()->ConvertReceiver(convert_mode),
   2184                            receiver, context, frame_state, effect, control);
   2185       NodeProperties::ReplaceValueInput(node, receiver, 1);
   2186     }
   2187 
   2188     // Update the effect dependency for the {node}.
   2189     NodeProperties::ReplaceEffectInput(node, effect);
   2190 
   2191     // Remove the eager bailout frame state.
   2192     NodeProperties::RemoveFrameStateInput(node, 1);
   2193 
   2194     // Compute flags for the call.
   2195     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
   2196     if (p.tail_call_mode() == TailCallMode::kAllow) {
   2197       flags |= CallDescriptor::kSupportsTailCalls;
   2198     }
   2199 
   2200     Node* new_target = jsgraph()->UndefinedConstant();
   2201     Node* argument_count = jsgraph()->Int32Constant(arity);
   2202     if (shared->internal_formal_parameter_count() == arity ||
   2203         shared->internal_formal_parameter_count() ==
   2204             SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
   2205       // Patch {node} to a direct call.
   2206       node->InsertInput(graph()->zone(), arity + 2, new_target);
   2207       node->InsertInput(graph()->zone(), arity + 3, argument_count);
   2208       NodeProperties::ChangeOp(node,
   2209                                common()->Call(Linkage::GetJSCallDescriptor(
   2210                                    graph()->zone(), false, 1 + arity, flags)));
   2211     } else {
   2212       // Patch {node} to an indirect call via the ArgumentsAdaptorTrampoline.
   2213       Callable callable = CodeFactory::ArgumentAdaptor(isolate());
   2214       node->InsertInput(graph()->zone(), 0,
   2215                         jsgraph()->HeapConstant(callable.code()));
   2216       node->InsertInput(graph()->zone(), 2, new_target);
   2217       node->InsertInput(graph()->zone(), 3, argument_count);
   2218       node->InsertInput(
   2219           graph()->zone(), 4,
   2220           jsgraph()->Int32Constant(shared->internal_formal_parameter_count()));
   2221       NodeProperties::ChangeOp(
   2222           node, common()->Call(Linkage::GetStubCallDescriptor(
   2223                     isolate(), graph()->zone(), callable.descriptor(),
   2224                     1 + arity, flags)));
   2225     }
   2226     return Changed(node);
   2227   }
   2228 
   2229   // Check if {target} is a JSFunction.
   2230   if (target_type->Is(Type::Function())) {
   2231     // Remove the eager bailout frame state.
   2232     NodeProperties::RemoveFrameStateInput(node, 1);
   2233 
   2234     // Compute flags for the call.
   2235     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
   2236     if (p.tail_call_mode() == TailCallMode::kAllow) {
   2237       flags |= CallDescriptor::kSupportsTailCalls;
   2238     }
   2239 
   2240     // Patch {node} to an indirect call via the CallFunction builtin.
   2241     Callable callable = CodeFactory::CallFunction(isolate(), convert_mode);
   2242     node->InsertInput(graph()->zone(), 0,
   2243                       jsgraph()->HeapConstant(callable.code()));
   2244     node->InsertInput(graph()->zone(), 2, jsgraph()->Int32Constant(arity));
   2245     NodeProperties::ChangeOp(
   2246         node, common()->Call(Linkage::GetStubCallDescriptor(
   2247                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
   2248                   flags)));
   2249     return Changed(node);
   2250   }
   2251 
   2252   // Maybe we did at least learn something about the {receiver}.
   2253   if (p.convert_mode() != convert_mode) {
   2254     NodeProperties::ChangeOp(
   2255         node,
   2256         javascript()->CallFunction(p.arity(), p.language_mode(), p.feedback(),
   2257                                    convert_mode, p.tail_call_mode()));
   2258     return Changed(node);
   2259   }
   2260 
   2261   return NoChange();
   2262 }
   2263 
   2264 
   2265 Reduction JSTypedLowering::ReduceJSForInDone(Node* node) {
   2266   DCHECK_EQ(IrOpcode::kJSForInDone, node->opcode());
   2267   node->TrimInputCount(2);
   2268   NodeProperties::ChangeOp(node, machine()->Word32Equal());
   2269   return Changed(node);
   2270 }
   2271 
   2272 
   2273 Reduction JSTypedLowering::ReduceJSForInPrepare(Node* node) {
   2274   DCHECK_EQ(IrOpcode::kJSForInPrepare, node->opcode());
   2275   Node* receiver = NodeProperties::GetValueInput(node, 0);
   2276   Node* context = NodeProperties::GetContextInput(node);
   2277   Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
   2278   Node* effect = NodeProperties::GetEffectInput(node);
   2279   Node* control = NodeProperties::GetControlInput(node);
   2280 
   2281   // Get the set of properties to enumerate.
   2282   Node* cache_type = effect = graph()->NewNode(
   2283       javascript()->CallRuntime(Runtime::kGetPropertyNamesFast, 1), receiver,
   2284       context, frame_state, effect, control);
   2285   control = graph()->NewNode(common()->IfSuccess(), cache_type);
   2286 
   2287   Node* receiver_map = effect =
   2288       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
   2289                        receiver, effect, control);
   2290   Node* cache_type_map = effect =
   2291       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
   2292                        cache_type, effect, control);
   2293   Node* meta_map = jsgraph()->HeapConstant(factory()->meta_map());
   2294 
   2295   // If we got a map from the GetPropertyNamesFast runtime call, we can do a
   2296   // fast modification check. Otherwise, we got a fixed array, and we have to
   2297   // perform a slow check on every iteration.
   2298   Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()),
   2299                                   cache_type_map, meta_map);
   2300   Node* branch0 =
   2301       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
   2302 
   2303   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   2304   Node* cache_array_true0;
   2305   Node* cache_length_true0;
   2306   Node* cache_type_true0;
   2307   Node* etrue0;
   2308   {
   2309     // Enum cache case.
   2310     Node* cache_type_enum_length = etrue0 = graph()->NewNode(
   2311         simplified()->LoadField(AccessBuilder::ForMapBitField3()), cache_type,
   2312         effect, if_true0);
   2313     cache_length_true0 = graph()->NewNode(
   2314         simplified()->NumberBitwiseAnd(), cache_type_enum_length,
   2315         jsgraph()->Int32Constant(Map::EnumLengthBits::kMask));
   2316 
   2317     Node* check1 =
   2318         graph()->NewNode(machine()->Word32Equal(), cache_length_true0,
   2319                          jsgraph()->Int32Constant(0));
   2320     Node* branch1 =
   2321         graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0);
   2322 
   2323     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   2324     Node* cache_array_true1;
   2325     Node* etrue1;
   2326     {
   2327       // No properties to enumerate.
   2328       cache_array_true1 =
   2329           jsgraph()->HeapConstant(factory()->empty_fixed_array());
   2330       etrue1 = etrue0;
   2331     }
   2332 
   2333     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   2334     Node* cache_array_false1;
   2335     Node* efalse1;
   2336     {
   2337       // Load the enumeration cache from the instance descriptors of {receiver}.
   2338       Node* receiver_map_descriptors = efalse1 = graph()->NewNode(
   2339           simplified()->LoadField(AccessBuilder::ForMapDescriptors()),
   2340           receiver_map, etrue0, if_false1);
   2341       Node* object_map_enum_cache = efalse1 = graph()->NewNode(
   2342           simplified()->LoadField(AccessBuilder::ForDescriptorArrayEnumCache()),
   2343           receiver_map_descriptors, efalse1, if_false1);
   2344       cache_array_false1 = efalse1 = graph()->NewNode(
   2345           simplified()->LoadField(
   2346               AccessBuilder::ForDescriptorArrayEnumCacheBridgeCache()),
   2347           object_map_enum_cache, efalse1, if_false1);
   2348     }
   2349 
   2350     if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
   2351     etrue0 =
   2352         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0);
   2353     cache_array_true0 =
   2354         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
   2355                          cache_array_true1, cache_array_false1, if_true0);
   2356 
   2357     cache_type_true0 = cache_type;
   2358   }
   2359 
   2360   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   2361   Node* cache_array_false0;
   2362   Node* cache_length_false0;
   2363   Node* cache_type_false0;
   2364   Node* efalse0;
   2365   {
   2366     // FixedArray case.
   2367     cache_type_false0 = jsgraph()->OneConstant();  // Smi means slow check
   2368     cache_array_false0 = cache_type;
   2369     cache_length_false0 = efalse0 = graph()->NewNode(
   2370         simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
   2371         cache_array_false0, effect, if_false0);
   2372   }
   2373 
   2374   control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
   2375   effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
   2376   Node* cache_array =
   2377       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
   2378                        cache_array_true0, cache_array_false0, control);
   2379   Node* cache_length =
   2380       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
   2381                        cache_length_true0, cache_length_false0, control);
   2382   cache_type =
   2383       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
   2384                        cache_type_true0, cache_type_false0, control);
   2385 
   2386   for (auto edge : node->use_edges()) {
   2387     Node* const use = edge.from();
   2388     if (NodeProperties::IsEffectEdge(edge)) {
   2389       edge.UpdateTo(effect);
   2390       Revisit(use);
   2391     } else {
   2392       if (NodeProperties::IsControlEdge(edge)) {
   2393         if (use->opcode() == IrOpcode::kIfSuccess) {
   2394           Replace(use, control);
   2395         } else if (use->opcode() == IrOpcode::kIfException) {
   2396           edge.UpdateTo(cache_type_true0);
   2397           continue;
   2398         } else {
   2399           UNREACHABLE();
   2400         }
   2401       } else {
   2402         DCHECK(NodeProperties::IsValueEdge(edge));
   2403         DCHECK_EQ(IrOpcode::kProjection, use->opcode());
   2404         switch (ProjectionIndexOf(use->op())) {
   2405           case 0:
   2406             Replace(use, cache_type);
   2407             break;
   2408           case 1:
   2409             Replace(use, cache_array);
   2410             break;
   2411           case 2:
   2412             Replace(use, cache_length);
   2413             break;
   2414           default:
   2415             UNREACHABLE();
   2416             break;
   2417         }
   2418       }
   2419       use->Kill();
   2420     }
   2421   }
   2422   return NoChange();  // All uses were replaced already above.
   2423 }
   2424 
   2425 
   2426 Reduction JSTypedLowering::ReduceJSForInNext(Node* node) {
   2427   DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode());
   2428   Node* receiver = NodeProperties::GetValueInput(node, 0);
   2429   Node* cache_array = NodeProperties::GetValueInput(node, 1);
   2430   Node* cache_type = NodeProperties::GetValueInput(node, 2);
   2431   Node* index = NodeProperties::GetValueInput(node, 3);
   2432   Node* context = NodeProperties::GetContextInput(node);
   2433   Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
   2434   Node* effect = NodeProperties::GetEffectInput(node);
   2435   Node* control = NodeProperties::GetControlInput(node);
   2436 
   2437   // Load the next {key} from the {cache_array}.
   2438   Node* key = effect = graph()->NewNode(
   2439       simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
   2440       cache_array, index, effect, control);
   2441 
   2442   // Load the map of the {receiver}.
   2443   Node* receiver_map = effect =
   2444       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
   2445                        receiver, effect, control);
   2446 
   2447   // Check if the expected map still matches that of the {receiver}.
   2448   Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()),
   2449                                   receiver_map, cache_type);
   2450   Node* branch0 =
   2451       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
   2452 
   2453   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   2454   Node* etrue0;
   2455   Node* vtrue0;
   2456   {
   2457     // Don't need filtering since expected map still matches that of the
   2458     // {receiver}.
   2459     etrue0 = effect;
   2460     vtrue0 = key;
   2461   }
   2462 
   2463   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   2464   Node* efalse0;
   2465   Node* vfalse0;
   2466   {
   2467     // Check if the {cache_type} is zero, which indicates proxy.
   2468     Node* check1 = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()),
   2469                                     cache_type, jsgraph()->ZeroConstant());
   2470     Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
   2471                                      check1, if_false0);
   2472 
   2473     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   2474     Node* etrue1;
   2475     Node* vtrue1;
   2476     {
   2477       // Don't do filtering for proxies.
   2478       etrue1 = effect;
   2479       vtrue1 = key;
   2480     }
   2481 
   2482     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   2483     Node* efalse1;
   2484     Node* vfalse1;
   2485     {
   2486       // Filter the {key} to check if it's still a valid property of the
   2487       // {receiver} (does the ToName conversion implicitly).
   2488       vfalse1 = efalse1 = graph()->NewNode(
   2489           javascript()->CallRuntime(Runtime::kForInFilter, 2), receiver, key,
   2490           context, frame_state, effect, if_false1);
   2491       if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
   2492     }
   2493 
   2494     if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
   2495     efalse0 =
   2496         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
   2497     vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
   2498                                vtrue1, vfalse1, if_false0);
   2499   }
   2500 
   2501   control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
   2502   effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
   2503   ReplaceWithValue(node, node, effect, control);
   2504   node->ReplaceInput(0, vtrue0);
   2505   node->ReplaceInput(1, vfalse0);
   2506   node->ReplaceInput(2, control);
   2507   node->TrimInputCount(3);
   2508   NodeProperties::ChangeOp(node,
   2509                            common()->Phi(MachineRepresentation::kTagged, 2));
   2510   return Changed(node);
   2511 }
   2512 
   2513 
   2514 Reduction JSTypedLowering::ReduceJSForInStep(Node* node) {
   2515   DCHECK_EQ(IrOpcode::kJSForInStep, node->opcode());
   2516   node->ReplaceInput(1, jsgraph()->Int32Constant(1));
   2517   NodeProperties::ChangeOp(node, machine()->Int32Add());
   2518   return Changed(node);
   2519 }
   2520 
   2521 
   2522 Reduction JSTypedLowering::ReduceSelect(Node* node) {
   2523   DCHECK_EQ(IrOpcode::kSelect, node->opcode());
   2524   Node* const condition = NodeProperties::GetValueInput(node, 0);
   2525   Type* const condition_type = NodeProperties::GetType(condition);
   2526   Node* const vtrue = NodeProperties::GetValueInput(node, 1);
   2527   Type* const vtrue_type = NodeProperties::GetType(vtrue);
   2528   Node* const vfalse = NodeProperties::GetValueInput(node, 2);
   2529   Type* const vfalse_type = NodeProperties::GetType(vfalse);
   2530   if (condition_type->Is(true_type_)) {
   2531     // Select(condition:true, vtrue, vfalse) => vtrue
   2532     return Replace(vtrue);
   2533   }
   2534   if (condition_type->Is(false_type_)) {
   2535     // Select(condition:false, vtrue, vfalse) => vfalse
   2536     return Replace(vfalse);
   2537   }
   2538   if (vtrue_type->Is(true_type_) && vfalse_type->Is(false_type_)) {
   2539     // Select(condition, vtrue:true, vfalse:false) => condition
   2540     return Replace(condition);
   2541   }
   2542   if (vtrue_type->Is(false_type_) && vfalse_type->Is(true_type_)) {
   2543     // Select(condition, vtrue:false, vfalse:true) => BooleanNot(condition)
   2544     node->TrimInputCount(1);
   2545     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
   2546     return Changed(node);
   2547   }
   2548   return NoChange();
   2549 }
   2550 
   2551 
   2552 Reduction JSTypedLowering::Reduce(Node* node) {
   2553   // Check if the output type is a singleton.  In that case we already know the
   2554   // result value and can simply replace the node if it's eliminable.
   2555   if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
   2556       node->op()->HasProperty(Operator::kEliminatable)) {
   2557     Type* upper = NodeProperties::GetType(node);
   2558     if (upper->IsConstant()) {
   2559       Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
   2560       ReplaceWithValue(node, replacement);
   2561       return Changed(replacement);
   2562     } else if (upper->Is(Type::MinusZero())) {
   2563       Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
   2564       ReplaceWithValue(node, replacement);
   2565       return Changed(replacement);
   2566     } else if (upper->Is(Type::NaN())) {
   2567       Node* replacement = jsgraph()->NaNConstant();
   2568       ReplaceWithValue(node, replacement);
   2569       return Changed(replacement);
   2570     } else if (upper->Is(Type::Null())) {
   2571       Node* replacement = jsgraph()->NullConstant();
   2572       ReplaceWithValue(node, replacement);
   2573       return Changed(replacement);
   2574     } else if (upper->Is(Type::PlainNumber()) && upper->Min() == upper->Max()) {
   2575       Node* replacement = jsgraph()->Constant(upper->Min());
   2576       ReplaceWithValue(node, replacement);
   2577       return Changed(replacement);
   2578     } else if (upper->Is(Type::Undefined())) {
   2579       Node* replacement = jsgraph()->UndefinedConstant();
   2580       ReplaceWithValue(node, replacement);
   2581       return Changed(replacement);
   2582     }
   2583   }
   2584   switch (node->opcode()) {
   2585     case IrOpcode::kJSEqual:
   2586       return ReduceJSEqual(node, false);
   2587     case IrOpcode::kJSNotEqual:
   2588       return ReduceJSEqual(node, true);
   2589     case IrOpcode::kJSStrictEqual:
   2590       return ReduceJSStrictEqual(node, false);
   2591     case IrOpcode::kJSStrictNotEqual:
   2592       return ReduceJSStrictEqual(node, true);
   2593     case IrOpcode::kJSLessThan:         // fall through
   2594     case IrOpcode::kJSGreaterThan:      // fall through
   2595     case IrOpcode::kJSLessThanOrEqual:  // fall through
   2596     case IrOpcode::kJSGreaterThanOrEqual:
   2597       return ReduceJSComparison(node);
   2598     case IrOpcode::kJSBitwiseOr:
   2599       return ReduceInt32Binop(node, simplified()->NumberBitwiseOr());
   2600     case IrOpcode::kJSBitwiseXor:
   2601       return ReduceInt32Binop(node, simplified()->NumberBitwiseXor());
   2602     case IrOpcode::kJSBitwiseAnd:
   2603       return ReduceInt32Binop(node, simplified()->NumberBitwiseAnd());
   2604     case IrOpcode::kJSShiftLeft:
   2605       return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft());
   2606     case IrOpcode::kJSShiftRight:
   2607       return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftRight());
   2608     case IrOpcode::kJSShiftRightLogical:
   2609       return ReduceUI32Shift(node, kUnsigned,
   2610                              simplified()->NumberShiftRightLogical());
   2611     case IrOpcode::kJSAdd:
   2612       return ReduceJSAdd(node);
   2613     case IrOpcode::kJSSubtract:
   2614       return ReduceNumberBinop(node, simplified()->NumberSubtract());
   2615     case IrOpcode::kJSMultiply:
   2616       return ReduceNumberBinop(node, simplified()->NumberMultiply());
   2617     case IrOpcode::kJSDivide:
   2618       return ReduceNumberBinop(node, simplified()->NumberDivide());
   2619     case IrOpcode::kJSModulus:
   2620       return ReduceJSModulus(node);
   2621     case IrOpcode::kJSToBoolean:
   2622       return ReduceJSToBoolean(node);
   2623     case IrOpcode::kJSToNumber:
   2624       return ReduceJSToNumber(node);
   2625     case IrOpcode::kJSToString:
   2626       return ReduceJSToString(node);
   2627     case IrOpcode::kJSToObject:
   2628       return ReduceJSToObject(node);
   2629     case IrOpcode::kJSLoadNamed:
   2630       return ReduceJSLoadNamed(node);
   2631     case IrOpcode::kJSLoadProperty:
   2632       return ReduceJSLoadProperty(node);
   2633     case IrOpcode::kJSStoreProperty:
   2634       return ReduceJSStoreProperty(node);
   2635     case IrOpcode::kJSInstanceOf:
   2636       return ReduceJSInstanceOf(node);
   2637     case IrOpcode::kJSLoadContext:
   2638       return ReduceJSLoadContext(node);
   2639     case IrOpcode::kJSStoreContext:
   2640       return ReduceJSStoreContext(node);
   2641     case IrOpcode::kJSConvertReceiver:
   2642       return ReduceJSConvertReceiver(node);
   2643     case IrOpcode::kJSCreate:
   2644       return ReduceJSCreate(node);
   2645     case IrOpcode::kJSCreateArguments:
   2646       return ReduceJSCreateArguments(node);
   2647     case IrOpcode::kJSCreateArray:
   2648       return ReduceJSCreateArray(node);
   2649     case IrOpcode::kJSCreateClosure:
   2650       return ReduceJSCreateClosure(node);
   2651     case IrOpcode::kJSCreateIterResultObject:
   2652       return ReduceJSCreateIterResultObject(node);
   2653     case IrOpcode::kJSCreateLiteralArray:
   2654       return ReduceJSCreateLiteralArray(node);
   2655     case IrOpcode::kJSCreateLiteralObject:
   2656       return ReduceJSCreateLiteralObject(node);
   2657     case IrOpcode::kJSCreateFunctionContext:
   2658       return ReduceJSCreateFunctionContext(node);
   2659     case IrOpcode::kJSCreateWithContext:
   2660       return ReduceJSCreateWithContext(node);
   2661     case IrOpcode::kJSCreateCatchContext:
   2662       return ReduceJSCreateCatchContext(node);
   2663     case IrOpcode::kJSCreateBlockContext:
   2664       return ReduceJSCreateBlockContext(node);
   2665     case IrOpcode::kJSCallConstruct:
   2666       return ReduceJSCallConstruct(node);
   2667     case IrOpcode::kJSCallFunction:
   2668       return ReduceJSCallFunction(node);
   2669     case IrOpcode::kJSForInDone:
   2670       return ReduceJSForInDone(node);
   2671     case IrOpcode::kJSForInNext:
   2672       return ReduceJSForInNext(node);
   2673     case IrOpcode::kJSForInPrepare:
   2674       return ReduceJSForInPrepare(node);
   2675     case IrOpcode::kJSForInStep:
   2676       return ReduceJSForInStep(node);
   2677     case IrOpcode::kSelect:
   2678       return ReduceSelect(node);
   2679     default:
   2680       break;
   2681   }
   2682   return NoChange();
   2683 }
   2684 
   2685 
   2686 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
   2687   if (rhs == 0) return lhs;
   2688   return graph()->NewNode(machine()->Word32Shl(), lhs,
   2689                           jsgraph()->Int32Constant(rhs));
   2690 }
   2691 
   2692 
   2693 // Helper that allocates a FixedArray holding argument values recorded in the
   2694 // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
   2695 Node* JSTypedLowering::AllocateArguments(Node* effect, Node* control,
   2696                                          Node* frame_state) {
   2697   FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
   2698   int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
   2699   if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
   2700 
   2701   // Prepare an iterator over argument values recorded in the frame state.
   2702   Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
   2703   StateValuesAccess parameters_access(parameters);
   2704   auto parameters_it = ++parameters_access.begin();
   2705 
   2706   // Actually allocate the backing store.
   2707   AllocationBuilder a(jsgraph(), effect, control);
   2708   a.AllocateArray(argument_count, factory()->fixed_array_map());
   2709   for (int i = 0; i < argument_count; ++i, ++parameters_it) {
   2710     a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
   2711   }
   2712   return a.Finish();
   2713 }
   2714 
   2715 
   2716 // Helper that allocates a FixedArray holding argument values recorded in the
   2717 // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
   2718 Node* JSTypedLowering::AllocateRestArguments(Node* effect, Node* control,
   2719                                              Node* frame_state,
   2720                                              int start_index) {
   2721   FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
   2722   int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
   2723   int num_elements = std::max(0, argument_count - start_index);
   2724   if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant();
   2725 
   2726   // Prepare an iterator over argument values recorded in the frame state.
   2727   Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
   2728   StateValuesAccess parameters_access(parameters);
   2729   auto parameters_it = ++parameters_access.begin();
   2730 
   2731   // Skip unused arguments.
   2732   for (int i = 0; i < start_index; i++) {
   2733     ++parameters_it;
   2734   }
   2735 
   2736   // Actually allocate the backing store.
   2737   AllocationBuilder a(jsgraph(), effect, control);
   2738   a.AllocateArray(num_elements, factory()->fixed_array_map());
   2739   for (int i = 0; i < num_elements; ++i, ++parameters_it) {
   2740     a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
   2741   }
   2742   return a.Finish();
   2743 }
   2744 
   2745 
   2746 // Helper that allocates a FixedArray serving as a parameter map for values
   2747 // recorded in the given {frame_state}. Some elements map to slots within the
   2748 // given {context}. Serves as backing store for JSCreateArguments nodes.
   2749 Node* JSTypedLowering::AllocateAliasedArguments(
   2750     Node* effect, Node* control, Node* frame_state, Node* context,
   2751     Handle<SharedFunctionInfo> shared, bool* has_aliased_arguments) {
   2752   FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
   2753   int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
   2754   if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
   2755 
   2756   // If there is no aliasing, the arguments object elements are not special in
   2757   // any way, we can just return an unmapped backing store instead.
   2758   int parameter_count = shared->internal_formal_parameter_count();
   2759   if (parameter_count == 0) {
   2760     return AllocateArguments(effect, control, frame_state);
   2761   }
   2762 
   2763   // Calculate number of argument values being aliased/mapped.
   2764   int mapped_count = Min(argument_count, parameter_count);
   2765   *has_aliased_arguments = true;
   2766 
   2767   // Prepare an iterator over argument values recorded in the frame state.
   2768   Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
   2769   StateValuesAccess parameters_access(parameters);
   2770   auto paratemers_it = ++parameters_access.begin();
   2771 
   2772   // The unmapped argument values recorded in the frame state are stored yet
   2773   // another indirection away and then linked into the parameter map below,
   2774   // whereas mapped argument values are replaced with a hole instead.
   2775   AllocationBuilder aa(jsgraph(), effect, control);
   2776   aa.AllocateArray(argument_count, factory()->fixed_array_map());
   2777   for (int i = 0; i < mapped_count; ++i, ++paratemers_it) {
   2778     aa.Store(AccessBuilder::ForFixedArraySlot(i), jsgraph()->TheHoleConstant());
   2779   }
   2780   for (int i = mapped_count; i < argument_count; ++i, ++paratemers_it) {
   2781     aa.Store(AccessBuilder::ForFixedArraySlot(i), (*paratemers_it).node);
   2782   }
   2783   Node* arguments = aa.Finish();
   2784 
   2785   // Actually allocate the backing store.
   2786   AllocationBuilder a(jsgraph(), arguments, control);
   2787   a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
   2788   a.Store(AccessBuilder::ForFixedArraySlot(0), context);
   2789   a.Store(AccessBuilder::ForFixedArraySlot(1), arguments);
   2790   for (int i = 0; i < mapped_count; ++i) {
   2791     int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
   2792     a.Store(AccessBuilder::ForFixedArraySlot(i + 2), jsgraph()->Constant(idx));
   2793   }
   2794   return a.Finish();
   2795 }
   2796 
   2797 
   2798 Node* JSTypedLowering::AllocateElements(Node* effect, Node* control,
   2799                                         ElementsKind elements_kind,
   2800                                         int capacity, PretenureFlag pretenure) {
   2801   DCHECK_LE(1, capacity);
   2802   DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);
   2803 
   2804   Handle<Map> elements_map = IsFastDoubleElementsKind(elements_kind)
   2805                                  ? factory()->fixed_double_array_map()
   2806                                  : factory()->fixed_array_map();
   2807   ElementAccess access = IsFastDoubleElementsKind(elements_kind)
   2808                              ? AccessBuilder::ForFixedDoubleArrayElement()
   2809                              : AccessBuilder::ForFixedArrayElement();
   2810   Node* value =
   2811       IsFastDoubleElementsKind(elements_kind)
   2812           ? jsgraph()->Float64Constant(bit_cast<double>(kHoleNanInt64))
   2813           : jsgraph()->TheHoleConstant();
   2814 
   2815   // Actually allocate the backing store.
   2816   AllocationBuilder a(jsgraph(), effect, control);
   2817   a.AllocateArray(capacity, elements_map, pretenure);
   2818   for (int i = 0; i < capacity; ++i) {
   2819     Node* index = jsgraph()->Constant(i);
   2820     a.Store(access, index, value);
   2821   }
   2822   return a.Finish();
   2823 }
   2824 
   2825 
   2826 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
   2827 
   2828 
   2829 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
   2830 
   2831 
   2832 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); }
   2833 
   2834 
   2835 JSOperatorBuilder* JSTypedLowering::javascript() const {
   2836   return jsgraph()->javascript();
   2837 }
   2838 
   2839 
   2840 CommonOperatorBuilder* JSTypedLowering::common() const {
   2841   return jsgraph()->common();
   2842 }
   2843 
   2844 
   2845 SimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
   2846   return jsgraph()->simplified();
   2847 }
   2848 
   2849 
   2850 MachineOperatorBuilder* JSTypedLowering::machine() const {
   2851   return jsgraph()->machine();
   2852 }
   2853 
   2854 
   2855 CompilationDependencies* JSTypedLowering::dependencies() const {
   2856   return dependencies_;
   2857 }
   2858 
   2859 }  // namespace compiler
   2860 }  // namespace internal
   2861 }  // namespace v8
   2862