Home | History | Annotate | Download | only in compiler
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/compiler/js-typed-lowering.h"
      6 
      7 #include "src/ast/modules.h"
      8 #include "src/builtins/builtins-utils.h"
      9 #include "src/code-factory.h"
     10 #include "src/compilation-dependencies.h"
     11 #include "src/compiler/access-builder.h"
     12 #include "src/compiler/js-graph.h"
     13 #include "src/compiler/linkage.h"
     14 #include "src/compiler/node-matchers.h"
     15 #include "src/compiler/node-properties.h"
     16 #include "src/compiler/operator-properties.h"
     17 #include "src/compiler/type-cache.h"
     18 #include "src/compiler/types.h"
     19 #include "src/objects-inl.h"
     20 
     21 namespace v8 {
     22 namespace internal {
     23 namespace compiler {
     24 
     25 // A helper class to simplify the process of reducing a single binop node with a
     26 // JSOperator. This class manages the rewriting of context, control, and effect
     27 // dependencies during lowering of a binop and contains numerous helper
     28 // functions for matching the types of inputs to an operation.
     29 class JSBinopReduction final {
     30  public:
     31   JSBinopReduction(JSTypedLowering* lowering, Node* node)
     32       : lowering_(lowering), node_(node) {}
     33 
     34   bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
     35     if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
     36       DCHECK_EQ(1, node_->op()->EffectOutputCount());
     37       switch (CompareOperationHintOf(node_->op())) {
     38         case CompareOperationHint::kSignedSmall:
     39           *hint = NumberOperationHint::kSignedSmall;
     40           return true;
     41         case CompareOperationHint::kNumber:
     42           *hint = NumberOperationHint::kNumber;
     43           return true;
     44         case CompareOperationHint::kNumberOrOddball:
     45           *hint = NumberOperationHint::kNumberOrOddball;
     46           return true;
     47         case CompareOperationHint::kAny:
     48         case CompareOperationHint::kNone:
     49         case CompareOperationHint::kString:
     50         case CompareOperationHint::kReceiver:
     51         case CompareOperationHint::kInternalizedString:
     52           break;
     53       }
     54     }
     55     return false;
     56   }
     57 
     58   bool IsInternalizedStringCompareOperation() {
     59     if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
     60       DCHECK_EQ(1, node_->op()->EffectOutputCount());
     61       return (CompareOperationHintOf(node_->op()) ==
     62               CompareOperationHint::kInternalizedString) &&
     63              BothInputsMaybe(Type::InternalizedString());
     64     }
     65     return false;
     66   }
     67 
     68   bool IsReceiverCompareOperation() {
     69     if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
     70       DCHECK_EQ(1, node_->op()->EffectOutputCount());
     71       return (CompareOperationHintOf(node_->op()) ==
     72               CompareOperationHint::kReceiver) &&
     73              BothInputsMaybe(Type::Receiver());
     74     }
     75     return false;
     76   }
     77 
     78   bool IsStringCompareOperation() {
     79     if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
     80       DCHECK_EQ(1, node_->op()->EffectOutputCount());
     81       return (CompareOperationHintOf(node_->op()) ==
     82               CompareOperationHint::kString) &&
     83              BothInputsMaybe(Type::String());
     84     }
     85     return false;
     86   }
     87 
     88   // Check if a string addition will definitely result in creating a ConsString,
     89   // i.e. if the combined length of the resulting string exceeds the ConsString
     90   // minimum length.
     91   bool ShouldCreateConsString() {
     92     DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode());
     93     DCHECK(OneInputIs(Type::String()));
     94     if (BothInputsAre(Type::String()) ||
     95         ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) &&
     96          BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) {
     97       HeapObjectBinopMatcher m(node_);
     98       if (m.right().HasValue() && m.right().Value()->IsString()) {
     99         Handle<String> right_string = Handle<String>::cast(m.right().Value());
    100         if (right_string->length() >= ConsString::kMinLength) return true;
    101       }
    102       if (m.left().HasValue() && m.left().Value()->IsString()) {
    103         Handle<String> left_string = Handle<String>::cast(m.left().Value());
    104         if (left_string->length() >= ConsString::kMinLength) {
    105           // The invariant for ConsString requires the left hand side to be
    106           // a sequential or external string if the right hand side is the
    107           // empty string. Since we don't know anything about the right hand
    108           // side here, we must ensure that the left hand side satisfy the
    109           // constraints independent of the right hand side.
    110           return left_string->IsSeqString() || left_string->IsExternalString();
    111         }
    112       }
    113     }
    114     return false;
    115   }
    116 
    117   // Inserts a CheckReceiver for the left input.
    118   void CheckLeftInputToReceiver() {
    119     Node* left_input = graph()->NewNode(simplified()->CheckReceiver(), left(),
    120                                         effect(), control());
    121     node_->ReplaceInput(0, left_input);
    122     update_effect(left_input);
    123   }
    124 
    125   // Checks that both inputs are Receiver, and if we don't know
    126   // statically that one side is already a Receiver, insert a
    127   // CheckReceiver node.
    128   void CheckInputsToReceiver() {
    129     if (!left_type()->Is(Type::Receiver())) {
    130       CheckLeftInputToReceiver();
    131     }
    132     if (!right_type()->Is(Type::Receiver())) {
    133       Node* right_input = graph()->NewNode(simplified()->CheckReceiver(),
    134                                            right(), effect(), control());
    135       node_->ReplaceInput(1, right_input);
    136       update_effect(right_input);
    137     }
    138   }
    139 
    140   // Checks that both inputs are String, and if we don't know
    141   // statically that one side is already a String, insert a
    142   // CheckString node.
    143   void CheckInputsToString() {
    144     if (!left_type()->Is(Type::String())) {
    145       Node* left_input = graph()->NewNode(simplified()->CheckString(), left(),
    146                                           effect(), control());
    147       node_->ReplaceInput(0, left_input);
    148       update_effect(left_input);
    149     }
    150     if (!right_type()->Is(Type::String())) {
    151       Node* right_input = graph()->NewNode(simplified()->CheckString(), right(),
    152                                            effect(), control());
    153       node_->ReplaceInput(1, right_input);
    154       update_effect(right_input);
    155     }
    156   }
    157 
    158   // Checks that both inputs are InternalizedString, and if we don't know
    159   // statically that one side is already an InternalizedString, insert a
    160   // CheckInternalizedString node.
    161   void CheckInputsToInternalizedString() {
    162     if (!left_type()->Is(Type::UniqueName())) {
    163       Node* left_input = graph()->NewNode(
    164           simplified()->CheckInternalizedString(), left(), effect(), control());
    165       node_->ReplaceInput(0, left_input);
    166       update_effect(left_input);
    167     }
    168     if (!right_type()->Is(Type::UniqueName())) {
    169       Node* right_input =
    170           graph()->NewNode(simplified()->CheckInternalizedString(), right(),
    171                            effect(), control());
    172       node_->ReplaceInput(1, right_input);
    173       update_effect(right_input);
    174     }
    175   }
    176 
    177   void ConvertInputsToNumber() {
    178     // To convert the inputs to numbers, we have to provide frame states
    179     // for lazy bailouts in the ToNumber conversions.
    180     // We use a little hack here: we take the frame state before the binary
    181     // operation and use it to construct the frame states for the conversion
    182     // so that after the deoptimization, the binary operation IC gets
    183     // already converted values from full code. This way we are sure that we
    184     // will not re-do any of the side effects.
    185 
    186     Node* left_input = nullptr;
    187     Node* right_input = nullptr;
    188     bool left_is_primitive = left_type()->Is(Type::PlainPrimitive());
    189     bool right_is_primitive = right_type()->Is(Type::PlainPrimitive());
    190     bool handles_exception = NodeProperties::IsExceptionalCall(node_);
    191 
    192     if (!left_is_primitive && !right_is_primitive && handles_exception) {
    193       ConvertBothInputsToNumber(&left_input, &right_input);
    194     } else {
    195       left_input = left_is_primitive
    196                        ? ConvertPlainPrimitiveToNumber(left())
    197                        : ConvertSingleInputToNumber(
    198                              left(), CreateFrameStateForLeftInput());
    199       right_input =
    200           right_is_primitive
    201               ? ConvertPlainPrimitiveToNumber(right())
    202               : ConvertSingleInputToNumber(
    203                     right(), CreateFrameStateForRightInput(left_input));
    204     }
    205 
    206     node_->ReplaceInput(0, left_input);
    207     node_->ReplaceInput(1, right_input);
    208   }
    209 
    210   void ConvertInputsToUI32(Signedness left_signedness,
    211                            Signedness right_signedness) {
    212     node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
    213     node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
    214   }
    215 
    216   void SwapInputs() {
    217     Node* l = left();
    218     Node* r = right();
    219     node_->ReplaceInput(0, r);
    220     node_->ReplaceInput(1, l);
    221   }
    222 
    223   // Remove all effect and control inputs and outputs to this node and change
    224   // to the pure operator {op}, possibly inserting a boolean inversion.
    225   Reduction ChangeToPureOperator(const Operator* op, bool invert = false,
    226                                  Type* type = Type::Any()) {
    227     DCHECK_EQ(0, op->EffectInputCount());
    228     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
    229     DCHECK_EQ(0, op->ControlInputCount());
    230     DCHECK_EQ(2, op->ValueInputCount());
    231 
    232     // Remove the effects from the node, and update its effect/control usages.
    233     if (node_->op()->EffectInputCount() > 0) {
    234       lowering_->RelaxEffectsAndControls(node_);
    235     }
    236     // Remove the inputs corresponding to context, effect, and control.
    237     NodeProperties::RemoveNonValueInputs(node_);
    238     // Finally, update the operator to the new one.
    239     NodeProperties::ChangeOp(node_, op);
    240 
    241     // TODO(jarin): Replace the explicit typing hack with a call to some method
    242     // that encapsulates changing the operator and re-typing.
    243     Type* node_type = NodeProperties::GetType(node_);
    244     NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
    245 
    246     if (invert) {
    247       // Insert an boolean not to invert the value.
    248       Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
    249       node_->ReplaceUses(value);
    250       // Note: ReplaceUses() smashes all uses, so smash it back here.
    251       value->ReplaceInput(0, node_);
    252       return lowering_->Replace(value);
    253     }
    254     return lowering_->Changed(node_);
    255   }
    256 
    257   Reduction ChangeToSpeculativeOperator(const Operator* op, bool invert,
    258                                         Type* upper_bound) {
    259     DCHECK_EQ(1, op->EffectInputCount());
    260     DCHECK_EQ(1, op->EffectOutputCount());
    261     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
    262     DCHECK_EQ(1, op->ControlInputCount());
    263     DCHECK_EQ(0, op->ControlOutputCount());
    264     DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
    265     DCHECK_EQ(2, op->ValueInputCount());
    266 
    267     DCHECK_EQ(1, node_->op()->EffectInputCount());
    268     DCHECK_EQ(1, node_->op()->EffectOutputCount());
    269     DCHECK_EQ(1, node_->op()->ControlInputCount());
    270     DCHECK_EQ(2, node_->op()->ValueInputCount());
    271 
    272     // Reconnect the control output to bypass the IfSuccess node and
    273     // possibly disconnect from the IfException node.
    274     for (Edge edge : node_->use_edges()) {
    275       Node* const user = edge.from();
    276       DCHECK(!user->IsDead());
    277       if (NodeProperties::IsControlEdge(edge)) {
    278         if (user->opcode() == IrOpcode::kIfSuccess) {
    279           user->ReplaceUses(NodeProperties::GetControlInput(node_));
    280           user->Kill();
    281         } else {
    282           DCHECK_EQ(user->opcode(), IrOpcode::kIfException);
    283           edge.UpdateTo(jsgraph()->Dead());
    284         }
    285       }
    286     }
    287 
    288     // Remove the frame state and the context.
    289     if (OperatorProperties::HasFrameStateInput(node_->op())) {
    290       node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
    291     }
    292     node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
    293 
    294     NodeProperties::ChangeOp(node_, op);
    295 
    296     // Update the type to number.
    297     Type* node_type = NodeProperties::GetType(node_);
    298     NodeProperties::SetType(node_,
    299                             Type::Intersect(node_type, upper_bound, zone()));
    300 
    301     if (invert) {
    302       // Insert an boolean not to invert the value.
    303       Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
    304       node_->ReplaceUses(value);
    305       // Note: ReplaceUses() smashes all uses, so smash it back here.
    306       value->ReplaceInput(0, node_);
    307       return lowering_->Replace(value);
    308     }
    309     return lowering_->Changed(node_);
    310   }
    311 
    312   Reduction ChangeToPureOperator(const Operator* op, Type* type) {
    313     return ChangeToPureOperator(op, false, type);
    314   }
    315 
    316   Reduction ChangeToSpeculativeOperator(const Operator* op, Type* type) {
    317     return ChangeToSpeculativeOperator(op, false, type);
    318   }
    319 
    320   const Operator* NumberOp() {
    321     switch (node_->opcode()) {
    322       case IrOpcode::kJSAdd:
    323         return simplified()->NumberAdd();
    324       case IrOpcode::kJSSubtract:
    325         return simplified()->NumberSubtract();
    326       case IrOpcode::kJSMultiply:
    327         return simplified()->NumberMultiply();
    328       case IrOpcode::kJSDivide:
    329         return simplified()->NumberDivide();
    330       case IrOpcode::kJSModulus:
    331         return simplified()->NumberModulus();
    332       case IrOpcode::kJSBitwiseAnd:
    333         return simplified()->NumberBitwiseAnd();
    334       case IrOpcode::kJSBitwiseOr:
    335         return simplified()->NumberBitwiseOr();
    336       case IrOpcode::kJSBitwiseXor:
    337         return simplified()->NumberBitwiseXor();
    338       case IrOpcode::kJSShiftLeft:
    339         return simplified()->NumberShiftLeft();
    340       case IrOpcode::kJSShiftRight:
    341         return simplified()->NumberShiftRight();
    342       case IrOpcode::kJSShiftRightLogical:
    343         return simplified()->NumberShiftRightLogical();
    344       default:
    345         break;
    346     }
    347     UNREACHABLE();
    348     return nullptr;
    349   }
    350 
    351   const Operator* NumberOpFromSpeculativeNumberOp() {
    352     switch (node_->opcode()) {
    353       case IrOpcode::kSpeculativeNumberAdd:
    354         return simplified()->NumberAdd();
    355       case IrOpcode::kSpeculativeNumberSubtract:
    356         return simplified()->NumberSubtract();
    357       case IrOpcode::kSpeculativeNumberMultiply:
    358         return simplified()->NumberMultiply();
    359       case IrOpcode::kSpeculativeNumberDivide:
    360         return simplified()->NumberDivide();
    361       case IrOpcode::kSpeculativeNumberModulus:
    362         return simplified()->NumberModulus();
    363       default:
    364         break;
    365     }
    366     UNREACHABLE();
    367     return nullptr;
    368   }
    369 
    370   bool LeftInputIs(Type* t) { return left_type()->Is(t); }
    371 
    372   bool RightInputIs(Type* t) { return right_type()->Is(t); }
    373 
    374   bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
    375 
    376   bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); }
    377 
    378   bool BothInputsMaybe(Type* t) {
    379     return left_type()->Maybe(t) && right_type()->Maybe(t);
    380   }
    381 
    382   bool OneInputCannotBe(Type* t) {
    383     return !left_type()->Maybe(t) || !right_type()->Maybe(t);
    384   }
    385 
    386   bool NeitherInputCanBe(Type* t) {
    387     return !left_type()->Maybe(t) && !right_type()->Maybe(t);
    388   }
    389 
    390   Node* effect() { return NodeProperties::GetEffectInput(node_); }
    391   Node* control() { return NodeProperties::GetControlInput(node_); }
    392   Node* context() { return NodeProperties::GetContextInput(node_); }
    393   Node* left() { return NodeProperties::GetValueInput(node_, 0); }
    394   Node* right() { return NodeProperties::GetValueInput(node_, 1); }
    395   Type* left_type() { return NodeProperties::GetType(node_->InputAt(0)); }
    396   Type* right_type() { return NodeProperties::GetType(node_->InputAt(1)); }
    397   Type* type() { return NodeProperties::GetType(node_); }
    398 
    399   SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
    400   Graph* graph() const { return lowering_->graph(); }
    401   JSGraph* jsgraph() { return lowering_->jsgraph(); }
    402   JSOperatorBuilder* javascript() { return lowering_->javascript(); }
    403   CommonOperatorBuilder* common() { return jsgraph()->common(); }
    404   Zone* zone() const { return graph()->zone(); }
    405 
    406  private:
    407   JSTypedLowering* lowering_;  // The containing lowering instance.
    408   Node* node_;                 // The original node.
    409 
    410   Node* CreateFrameStateForLeftInput() {
    411     // Deoptimization is disabled => return dummy frame state instead.
    412     Node* dummy_state = NodeProperties::GetFrameStateInput(node_);
    413     DCHECK(OpParameter<FrameStateInfo>(dummy_state).bailout_id().IsNone());
    414     return dummy_state;
    415   }
    416 
    417   Node* CreateFrameStateForRightInput(Node* converted_left) {
    418     // Deoptimization is disabled => return dummy frame state instead.
    419     Node* dummy_state = NodeProperties::GetFrameStateInput(node_);
    420     DCHECK(OpParameter<FrameStateInfo>(dummy_state).bailout_id().IsNone());
    421     return dummy_state;
    422   }
    423 
    424   Node* ConvertPlainPrimitiveToNumber(Node* node) {
    425     DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
    426     // Avoid inserting too many eager ToNumber() operations.
    427     Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
    428     if (reduction.Changed()) return reduction.replacement();
    429     if (NodeProperties::GetType(node)->Is(Type::Number())) {
    430       return node;
    431     }
    432     return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
    433   }
    434 
    435   Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
    436     DCHECK(!NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
    437     Node* const n = graph()->NewNode(javascript()->ToNumber(), node, context(),
    438                                      frame_state, effect(), control());
    439     Node* const if_success = graph()->NewNode(common()->IfSuccess(), n);
    440     NodeProperties::ReplaceControlInput(node_, if_success);
    441     NodeProperties::ReplaceUses(node_, node_, node_, node_, n);
    442     update_effect(n);
    443     return n;
    444   }
    445 
    446   void ConvertBothInputsToNumber(Node** left_result, Node** right_result) {
    447     Node* projections[2];
    448 
    449     // Find {IfSuccess} and {IfException} continuations of the operation.
    450     NodeProperties::CollectControlProjections(node_, projections, 2);
    451     Node* if_exception = projections[1];
    452     Node* if_success = projections[0];
    453 
    454     // Insert two ToNumber() operations that both potentially throw.
    455     Node* left_state = CreateFrameStateForLeftInput();
    456     Node* left_conv =
    457         graph()->NewNode(javascript()->ToNumber(), left(), context(),
    458                          left_state, effect(), control());
    459     Node* left_success = graph()->NewNode(common()->IfSuccess(), left_conv);
    460     Node* right_state = CreateFrameStateForRightInput(left_conv);
    461     Node* right_conv =
    462         graph()->NewNode(javascript()->ToNumber(), right(), context(),
    463                          right_state, left_conv, left_success);
    464     Node* left_exception =
    465         graph()->NewNode(common()->IfException(), left_conv, left_conv);
    466     Node* right_exception =
    467         graph()->NewNode(common()->IfException(), right_conv, right_conv);
    468     NodeProperties::ReplaceControlInput(if_success, right_conv);
    469     update_effect(right_conv);
    470 
    471     // Wire conversions to existing {IfException} continuation.
    472     Node* exception_merge = if_exception;
    473     Node* exception_value =
    474         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    475                          left_exception, right_exception, exception_merge);
    476     Node* exception_effect =
    477         graph()->NewNode(common()->EffectPhi(2), left_exception,
    478                          right_exception, exception_merge);
    479     for (Edge edge : exception_merge->use_edges()) {
    480       if (NodeProperties::IsEffectEdge(edge)) edge.UpdateTo(exception_effect);
    481       if (NodeProperties::IsValueEdge(edge)) edge.UpdateTo(exception_value);
    482     }
    483     NodeProperties::RemoveType(exception_merge);
    484     exception_merge->ReplaceInput(0, left_exception);
    485     exception_merge->ReplaceInput(1, right_exception);
    486     NodeProperties::ChangeOp(exception_merge, common()->Merge(2));
    487 
    488     *left_result = left_conv;
    489     *right_result = right_conv;
    490   }
    491 
    492   Node* ConvertToUI32(Node* node, Signedness signedness) {
    493     // Avoid introducing too many eager NumberToXXnt32() operations.
    494     Type* type = NodeProperties::GetType(node);
    495     if (signedness == kSigned) {
    496       if (!type->Is(Type::Signed32())) {
    497         node = graph()->NewNode(simplified()->NumberToInt32(), node);
    498       }
    499     } else {
    500       DCHECK_EQ(kUnsigned, signedness);
    501       if (!type->Is(Type::Unsigned32())) {
    502         node = graph()->NewNode(simplified()->NumberToUint32(), node);
    503       }
    504     }
    505     return node;
    506   }
    507 
    508   void update_effect(Node* effect) {
    509     NodeProperties::ReplaceEffectInput(node_, effect);
    510   }
    511 };
    512 
    513 
    514 // TODO(turbofan): js-typed-lowering improvements possible
    515 // - immediately put in type bounds for all new nodes
    516 // - relax effects from generic but not-side-effecting operations
    517 
    518 JSTypedLowering::JSTypedLowering(Editor* editor,
    519                                  CompilationDependencies* dependencies,
    520                                  Flags flags, JSGraph* jsgraph, Zone* zone)
    521     : AdvancedReducer(editor),
    522       dependencies_(dependencies),
    523       flags_(flags),
    524       jsgraph_(jsgraph),
    525       pointer_comparable_type_(Type::Union(
    526           Type::Oddball(),
    527           Type::Union(
    528               Type::SymbolOrReceiver(),
    529               Type::HeapConstant(factory()->empty_string(), graph()->zone()),
    530               graph()->zone()),
    531           graph()->zone())),
    532       type_cache_(TypeCache::Get()) {
    533   for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
    534     double min = kMinInt / (1 << k);
    535     double max = kMaxInt / (1 << k);
    536     shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
    537   }
    538 }
    539 
    540 Reduction JSTypedLowering::ReduceSpeculativeNumberAdd(Node* node) {
    541   JSBinopReduction r(this, node);
    542   NumberOperationHint hint = NumberOperationHintOf(node->op());
    543   if (hint == NumberOperationHint::kNumberOrOddball &&
    544       r.BothInputsAre(Type::PlainPrimitive()) &&
    545       r.NeitherInputCanBe(Type::StringOrReceiver())) {
    546     // SpeculativeNumberAdd(x:-string, y:-string) =>
    547     //     NumberAdd(ToNumber(x), ToNumber(y))
    548     r.ConvertInputsToNumber();
    549     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
    550   }
    551   return NoChange();
    552 }
    553 
    554 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
    555   JSBinopReduction r(this, node);
    556   if (r.BothInputsAre(Type::Number())) {
    557     // JSAdd(x:number, y:number) => NumberAdd(x, y)
    558     r.ConvertInputsToNumber();
    559     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
    560   }
    561   if ((r.BothInputsAre(Type::PlainPrimitive()) ||
    562        !(flags() & kDeoptimizationEnabled)) &&
    563       r.NeitherInputCanBe(Type::StringOrReceiver())) {
    564     // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
    565     r.ConvertInputsToNumber();
    566     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
    567   }
    568   if (r.OneInputIs(Type::String())) {
    569     if (r.ShouldCreateConsString()) {
    570       return ReduceCreateConsString(node);
    571     }
    572     StringAddFlags flags = STRING_ADD_CHECK_NONE;
    573     if (!r.LeftInputIs(Type::String())) {
    574       flags = STRING_ADD_CONVERT_LEFT;
    575     } else if (!r.RightInputIs(Type::String())) {
    576       flags = STRING_ADD_CONVERT_RIGHT;
    577     }
    578     Operator::Properties properties = node->op()->properties();
    579     if (r.NeitherInputCanBe(Type::Receiver())) {
    580       // Both sides are already strings, so we know that the
    581       // string addition will not cause any observable side
    582       // effects; it can still throw obviously.
    583       properties = Operator::kNoWrite | Operator::kNoDeopt;
    584     }
    585     // JSAdd(x:string, y) => CallStub[StringAdd](x, y)
    586     // JSAdd(x, y:string) => CallStub[StringAdd](x, y)
    587     Callable const callable =
    588         CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
    589     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    590         isolate(), graph()->zone(), callable.descriptor(), 0,
    591         CallDescriptor::kNeedsFrameState, properties);
    592     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
    593     node->InsertInput(graph()->zone(), 0,
    594                       jsgraph()->HeapConstant(callable.code()));
    595     NodeProperties::ChangeOp(node, common()->Call(desc));
    596     return Changed(node);
    597   }
    598   return NoChange();
    599 }
    600 
    601 Reduction JSTypedLowering::ReduceNumberBinop(Node* node) {
    602   JSBinopReduction r(this, node);
    603   if (r.BothInputsAre(Type::PlainPrimitive()) ||
    604       !(flags() & kDeoptimizationEnabled)) {
    605     r.ConvertInputsToNumber();
    606     return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
    607   }
    608   return NoChange();
    609 }
    610 
    611 Reduction JSTypedLowering::ReduceSpeculativeNumberBinop(Node* node) {
    612   JSBinopReduction r(this, node);
    613   NumberOperationHint hint = NumberOperationHintOf(node->op());
    614   if (hint == NumberOperationHint::kNumberOrOddball &&
    615       r.BothInputsAre(Type::NumberOrOddball())) {
    616     r.ConvertInputsToNumber();
    617     return r.ChangeToPureOperator(r.NumberOpFromSpeculativeNumberOp(),
    618                                   Type::Number());
    619   }
    620   return NoChange();
    621 }
    622 
    623 Reduction JSTypedLowering::ReduceInt32Binop(Node* node) {
    624   JSBinopReduction r(this, node);
    625   if (r.BothInputsAre(Type::PlainPrimitive()) ||
    626       !(flags() & kDeoptimizationEnabled)) {
    627     r.ConvertInputsToNumber();
    628     r.ConvertInputsToUI32(kSigned, kSigned);
    629     return r.ChangeToPureOperator(r.NumberOp(), Type::Signed32());
    630   }
    631   return NoChange();
    632 }
    633 
    634 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, Signedness signedness) {
    635   JSBinopReduction r(this, node);
    636   if (r.BothInputsAre(Type::PlainPrimitive()) ||
    637       !(flags() & kDeoptimizationEnabled)) {
    638     r.ConvertInputsToNumber();
    639     r.ConvertInputsToUI32(signedness, kUnsigned);
    640     return r.ChangeToPureOperator(r.NumberOp(), signedness == kUnsigned
    641                                                     ? Type::Unsigned32()
    642                                                     : Type::Signed32());
    643   }
    644   return NoChange();
    645 }
    646 
    647 Reduction JSTypedLowering::ReduceCreateConsString(Node* node) {
    648   Node* first = NodeProperties::GetValueInput(node, 0);
    649   Node* second = NodeProperties::GetValueInput(node, 1);
    650   Node* context = NodeProperties::GetContextInput(node);
    651   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    652   Node* effect = NodeProperties::GetEffectInput(node);
    653   Node* control = NodeProperties::GetControlInput(node);
    654 
    655   // Make sure {first} is actually a String.
    656   Type* first_type = NodeProperties::GetType(first);
    657   if (!first_type->Is(Type::String())) {
    658     first = effect =
    659         graph()->NewNode(simplified()->CheckString(), first, effect, control);
    660     first_type = NodeProperties::GetType(first);
    661   }
    662 
    663   // Make sure {second} is actually a String.
    664   Type* second_type = NodeProperties::GetType(second);
    665   if (!second_type->Is(Type::String())) {
    666     second = effect =
    667         graph()->NewNode(simplified()->CheckString(), second, effect, control);
    668     second_type = NodeProperties::GetType(second);
    669   }
    670 
    671   // Determine the {first} length.
    672   HeapObjectBinopMatcher m(node);
    673   Node* first_length =
    674       (m.left().HasValue() && m.left().Value()->IsString())
    675           ? jsgraph()->Constant(
    676                 Handle<String>::cast(m.left().Value())->length())
    677           : effect = graph()->NewNode(
    678                 simplified()->LoadField(AccessBuilder::ForStringLength()),
    679                 first, effect, control);
    680 
    681   // Determine the {second} length.
    682   Node* second_length =
    683       (m.right().HasValue() && m.right().Value()->IsString())
    684           ? jsgraph()->Constant(
    685                 Handle<String>::cast(m.right().Value())->length())
    686           : effect = graph()->NewNode(
    687                 simplified()->LoadField(AccessBuilder::ForStringLength()),
    688                 second, effect, control);
    689 
    690   // Compute the resulting length.
    691   Node* length =
    692       graph()->NewNode(simplified()->NumberAdd(), first_length, second_length);
    693 
    694   // Check if we would overflow the allowed maximum string length.
    695   Node* check = graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
    696                                  jsgraph()->Constant(String::kMaxLength));
    697   if (isolate()->IsStringLengthOverflowIntact()) {
    698     // Add a code dependency on the string length overflow protector.
    699     dependencies()->AssumePropertyCell(factory()->string_length_protector());
    700 
    701     // We can just deoptimize if the {check} fails. Besides generating a
    702     // shorter code sequence than the version below, this has the additional
    703     // benefit of not holding on to the lazy {frame_state} and thus potentially
    704     // reduces the number of live ranges and allows for more truncations.
    705     effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
    706   } else {
    707     Node* branch =
    708         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    709     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    710     Node* efalse = effect;
    711     {
    712       // Throw a RangeError in case of overflow.
    713       Node* vfalse = efalse = graph()->NewNode(
    714           javascript()->CallRuntime(Runtime::kThrowInvalidStringLength),
    715           context, frame_state, efalse, if_false);
    716       if_false = graph()->NewNode(common()->IfSuccess(), vfalse);
    717       if_false = graph()->NewNode(common()->Throw(), vfalse, efalse, if_false);
    718       // TODO(bmeurer): This should be on the AdvancedReducer somehow.
    719       NodeProperties::MergeControlToEnd(graph(), common(), if_false);
    720       Revisit(graph()->end());
    721 
    722       // Update potential {IfException} uses of {node} to point to the
    723       // %ThrowInvalidStringLength runtime call node instead.
    724       for (Edge edge : node->use_edges()) {
    725         if (edge.from()->opcode() == IrOpcode::kIfException) {
    726           DCHECK(NodeProperties::IsControlEdge(edge) ||
    727                  NodeProperties::IsEffectEdge(edge));
    728           edge.UpdateTo(vfalse);
    729           Revisit(edge.from());
    730         }
    731       }
    732     }
    733     control = graph()->NewNode(common()->IfTrue(), branch);
    734   }
    735 
    736   // Figure out the map for the resulting ConsString.
    737   // TODO(turbofan): We currently just use the cons_string_map here for
    738   // the sake of simplicity; we could also try to be smarter here and
    739   // use the one_byte_cons_string_map instead when the resulting ConsString
    740   // contains only one byte characters.
    741   Node* value_map = jsgraph()->HeapConstant(factory()->cons_string_map());
    742 
    743   // Allocate the resulting ConsString.
    744   effect = graph()->NewNode(
    745       common()->BeginRegion(RegionObservability::kNotObservable), effect);
    746   Node* value = effect =
    747       graph()->NewNode(simplified()->Allocate(NOT_TENURED),
    748                        jsgraph()->Constant(ConsString::kSize), effect, control);
    749   NodeProperties::SetType(value, Type::OtherString());
    750   effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
    751                             value, value_map, effect, control);
    752   effect = graph()->NewNode(
    753       simplified()->StoreField(AccessBuilder::ForNameHashField()), value,
    754       jsgraph()->Constant(Name::kEmptyHashField), effect, control);
    755   effect = graph()->NewNode(
    756       simplified()->StoreField(AccessBuilder::ForStringLength()), value, length,
    757       effect, control);
    758   effect = graph()->NewNode(
    759       simplified()->StoreField(AccessBuilder::ForConsStringFirst()), value,
    760       first, effect, control);
    761   effect = graph()->NewNode(
    762       simplified()->StoreField(AccessBuilder::ForConsStringSecond()), value,
    763       second, effect, control);
    764 
    765   // Morph the {node} into a {FinishRegion}.
    766   ReplaceWithValue(node, node, node, control);
    767   node->ReplaceInput(0, value);
    768   node->ReplaceInput(1, effect);
    769   node->TrimInputCount(2);
    770   NodeProperties::ChangeOp(node, common()->FinishRegion());
    771   return Changed(node);
    772 }
    773 
    774 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
    775   JSBinopReduction r(this, node);
    776   if (r.BothInputsAre(Type::String())) {
    777     // If both inputs are definitely strings, perform a string comparison.
    778     const Operator* stringOp;
    779     switch (node->opcode()) {
    780       case IrOpcode::kJSLessThan:
    781         stringOp = simplified()->StringLessThan();
    782         break;
    783       case IrOpcode::kJSGreaterThan:
    784         stringOp = simplified()->StringLessThan();
    785         r.SwapInputs();  // a > b => b < a
    786         break;
    787       case IrOpcode::kJSLessThanOrEqual:
    788         stringOp = simplified()->StringLessThanOrEqual();
    789         break;
    790       case IrOpcode::kJSGreaterThanOrEqual:
    791         stringOp = simplified()->StringLessThanOrEqual();
    792         r.SwapInputs();  // a >= b => b <= a
    793         break;
    794       default:
    795         return NoChange();
    796     }
    797     r.ChangeToPureOperator(stringOp);
    798     return Changed(node);
    799   }
    800 
    801   NumberOperationHint hint;
    802   const Operator* less_than;
    803   const Operator* less_than_or_equal;
    804   if (r.BothInputsAre(Type::Signed32()) ||
    805       r.BothInputsAre(Type::Unsigned32())) {
    806     less_than = simplified()->NumberLessThan();
    807     less_than_or_equal = simplified()->NumberLessThanOrEqual();
    808   } else if (r.GetCompareNumberOperationHint(&hint)) {
    809     less_than = simplified()->SpeculativeNumberLessThan(hint);
    810     less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
    811   } else if (r.OneInputCannotBe(Type::StringOrReceiver()) &&
    812              (r.BothInputsAre(Type::PlainPrimitive()) ||
    813               !(flags() & kDeoptimizationEnabled))) {
    814     r.ConvertInputsToNumber();
    815     less_than = simplified()->NumberLessThan();
    816     less_than_or_equal = simplified()->NumberLessThanOrEqual();
    817   } else if (r.IsStringCompareOperation()) {
    818     r.CheckInputsToString();
    819     less_than = simplified()->StringLessThan();
    820     less_than_or_equal = simplified()->StringLessThanOrEqual();
    821   } else {
    822     return NoChange();
    823   }
    824   const Operator* comparison;
    825   switch (node->opcode()) {
    826     case IrOpcode::kJSLessThan:
    827       comparison = less_than;
    828       break;
    829     case IrOpcode::kJSGreaterThan:
    830       comparison = less_than;
    831       r.SwapInputs();  // a > b => b < a
    832       break;
    833     case IrOpcode::kJSLessThanOrEqual:
    834       comparison = less_than_or_equal;
    835       break;
    836     case IrOpcode::kJSGreaterThanOrEqual:
    837       comparison = less_than_or_equal;
    838       r.SwapInputs();  // a >= b => b <= a
    839       break;
    840     default:
    841       return NoChange();
    842   }
    843   if (comparison->EffectInputCount() > 0) {
    844     return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
    845   } else {
    846     return r.ChangeToPureOperator(comparison);
    847   }
    848 }
    849 
    850 Reduction JSTypedLowering::ReduceJSTypeOf(Node* node) {
    851   Node* const input = node->InputAt(0);
    852   Type* type = NodeProperties::GetType(input);
    853   Factory* const f = factory();
    854   if (type->Is(Type::Boolean())) {
    855     return Replace(jsgraph()->Constant(f->boolean_string()));
    856   } else if (type->Is(Type::Number())) {
    857     return Replace(jsgraph()->Constant(f->number_string()));
    858   } else if (type->Is(Type::String())) {
    859     return Replace(jsgraph()->Constant(f->string_string()));
    860   } else if (type->Is(Type::Symbol())) {
    861     return Replace(jsgraph()->Constant(f->symbol_string()));
    862   } else if (type->Is(Type::OtherUndetectableOrUndefined())) {
    863     return Replace(jsgraph()->Constant(f->undefined_string()));
    864   } else if (type->Is(Type::NonCallableOrNull())) {
    865     return Replace(jsgraph()->Constant(f->object_string()));
    866   } else if (type->Is(Type::Function())) {
    867     return Replace(jsgraph()->Constant(f->function_string()));
    868   } else if (type->IsHeapConstant()) {
    869     return Replace(jsgraph()->Constant(
    870         Object::TypeOf(isolate(), type->AsHeapConstant()->Value())));
    871   }
    872 
    873   return NoChange();
    874 }
    875 
    876 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
    877   Node* input;
    878   Handle<String> type;
    879   HeapObjectBinopMatcher m(node);
    880   if (m.left().IsJSTypeOf() && m.right().HasValue() &&
    881       m.right().Value()->IsString()) {
    882     input = m.left().InputAt(0);
    883     type = Handle<String>::cast(m.right().Value());
    884   } else if (m.right().IsJSTypeOf() && m.left().HasValue() &&
    885              m.left().Value()->IsString()) {
    886     input = m.right().InputAt(0);
    887     type = Handle<String>::cast(m.left().Value());
    888   } else {
    889     return NoChange();
    890   }
    891   Node* value;
    892   if (String::Equals(type, factory()->boolean_string())) {
    893     value =
    894         graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
    895                          graph()->NewNode(simplified()->ReferenceEqual(), input,
    896                                           jsgraph()->TrueConstant()),
    897                          jsgraph()->TrueConstant(),
    898                          graph()->NewNode(simplified()->ReferenceEqual(), input,
    899                                           jsgraph()->FalseConstant()));
    900   } else if (String::Equals(type, factory()->function_string())) {
    901     value = graph()->NewNode(simplified()->ObjectIsDetectableCallable(), input);
    902   } else if (String::Equals(type, factory()->number_string())) {
    903     value = graph()->NewNode(simplified()->ObjectIsNumber(), input);
    904   } else if (String::Equals(type, factory()->object_string())) {
    905     value = graph()->NewNode(
    906         common()->Select(MachineRepresentation::kTagged),
    907         graph()->NewNode(simplified()->ObjectIsNonCallable(), input),
    908         jsgraph()->TrueConstant(),
    909         graph()->NewNode(simplified()->ReferenceEqual(), input,
    910                          jsgraph()->NullConstant()));
    911   } else if (String::Equals(type, factory()->string_string())) {
    912     value = graph()->NewNode(simplified()->ObjectIsString(), input);
    913   } else if (String::Equals(type, factory()->undefined_string())) {
    914     value = graph()->NewNode(
    915         common()->Select(MachineRepresentation::kTagged),
    916         graph()->NewNode(simplified()->ReferenceEqual(), input,
    917                          jsgraph()->NullConstant()),
    918         jsgraph()->FalseConstant(),
    919         graph()->NewNode(simplified()->ObjectIsUndetectable(), input));
    920   } else {
    921     return NoChange();
    922   }
    923   if (invert) {
    924     value = graph()->NewNode(simplified()->BooleanNot(), value);
    925   }
    926   ReplaceWithValue(node, value);
    927   return Replace(value);
    928 }
    929 
    930 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
    931   Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
    932   if (reduction.Changed()) return reduction;
    933 
    934   JSBinopReduction r(this, node);
    935 
    936   if (r.BothInputsAre(Type::UniqueName())) {
    937     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
    938   }
    939   if (r.IsInternalizedStringCompareOperation()) {
    940     r.CheckInputsToInternalizedString();
    941     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
    942   }
    943   if (r.BothInputsAre(Type::String())) {
    944     return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
    945   }
    946   if (r.BothInputsAre(Type::Boolean())) {
    947     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
    948   }
    949   if (r.BothInputsAre(Type::Receiver())) {
    950     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
    951   }
    952   if (r.OneInputIs(Type::Undetectable())) {
    953     RelaxEffectsAndControls(node);
    954     node->RemoveInput(r.LeftInputIs(Type::Undetectable()) ? 0 : 1);
    955     node->TrimInputCount(1);
    956     NodeProperties::ChangeOp(node, simplified()->ObjectIsUndetectable());
    957     if (invert) {
    958       // Insert an boolean not to invert the value.
    959       Node* value = graph()->NewNode(simplified()->BooleanNot(), node);
    960       node->ReplaceUses(value);
    961       // Note: ReplaceUses() smashes all uses, so smash it back here.
    962       value->ReplaceInput(0, node);
    963       return Replace(value);
    964     }
    965     return Changed(node);
    966   }
    967 
    968   NumberOperationHint hint;
    969   if (r.BothInputsAre(Type::Signed32()) ||
    970       r.BothInputsAre(Type::Unsigned32())) {
    971     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
    972   } else if (r.GetCompareNumberOperationHint(&hint)) {
    973     return r.ChangeToSpeculativeOperator(
    974         simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean());
    975   } else if (r.BothInputsAre(Type::Number())) {
    976     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
    977   } else if (r.IsReceiverCompareOperation()) {
    978     r.CheckInputsToReceiver();
    979     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
    980   } else if (r.IsStringCompareOperation()) {
    981     r.CheckInputsToString();
    982     return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
    983   }
    984   return NoChange();
    985 }
    986 
    987 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
    988   JSBinopReduction r(this, node);
    989   if (r.left() == r.right()) {
    990     // x === x is always true if x != NaN
    991     if (!r.left_type()->Maybe(Type::NaN())) {
    992       Node* replacement = jsgraph()->BooleanConstant(!invert);
    993       ReplaceWithValue(node, replacement);
    994       return Replace(replacement);
    995     }
    996   }
    997   if (r.OneInputCannotBe(Type::NumberOrString())) {
    998     // For values with canonical representation (i.e. neither String, nor
    999     // Number) an empty type intersection means the values cannot be strictly
   1000     // equal.
   1001     if (!r.left_type()->Maybe(r.right_type())) {
   1002       Node* replacement = jsgraph()->BooleanConstant(invert);
   1003       ReplaceWithValue(node, replacement);
   1004       return Replace(replacement);
   1005     }
   1006   }
   1007 
   1008   Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
   1009   if (reduction.Changed()) return reduction;
   1010 
   1011   if (r.BothInputsAre(Type::Unique())) {
   1012     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
   1013   }
   1014   if (r.OneInputIs(pointer_comparable_type_)) {
   1015     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
   1016   }
   1017   if (r.IsInternalizedStringCompareOperation()) {
   1018     r.CheckInputsToInternalizedString();
   1019     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
   1020   }
   1021   if (r.BothInputsAre(Type::String())) {
   1022     return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
   1023   }
   1024 
   1025   NumberOperationHint hint;
   1026   if (r.BothInputsAre(Type::Signed32()) ||
   1027       r.BothInputsAre(Type::Unsigned32())) {
   1028     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
   1029   } else if (r.GetCompareNumberOperationHint(&hint)) {
   1030     return r.ChangeToSpeculativeOperator(
   1031         simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean());
   1032   } else if (r.BothInputsAre(Type::Number())) {
   1033     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
   1034   } else if (r.IsReceiverCompareOperation()) {
   1035     // For strict equality, it's enough to know that one input is a Receiver,
   1036     // as a strict equality comparison with a Receiver can only yield true if
   1037     // both sides refer to the same Receiver than.
   1038     r.CheckLeftInputToReceiver();
   1039     return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
   1040   } else if (r.IsStringCompareOperation()) {
   1041     r.CheckInputsToString();
   1042     return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
   1043   }
   1044   return NoChange();
   1045 }
   1046 
   1047 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
   1048   Node* const input = node->InputAt(0);
   1049   Type* const input_type = NodeProperties::GetType(input);
   1050   if (input_type->Is(Type::Boolean())) {
   1051     // JSToBoolean(x:boolean) => x
   1052     return Replace(input);
   1053   } else if (input_type->Is(Type::OrderedNumber())) {
   1054     // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0))
   1055     node->ReplaceInput(0, graph()->NewNode(simplified()->NumberEqual(), input,
   1056                                            jsgraph()->ZeroConstant()));
   1057     node->TrimInputCount(1);
   1058     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
   1059     return Changed(node);
   1060   } else if (input_type->Is(Type::Number())) {
   1061     // JSToBoolean(x:number) => NumberToBoolean(x)
   1062     node->TrimInputCount(1);
   1063     NodeProperties::ChangeOp(node, simplified()->NumberToBoolean());
   1064     return Changed(node);
   1065   } else if (input_type->Is(Type::DetectableReceiverOrNull())) {
   1066     // JSToBoolean(x:detectable receiver \/ null)
   1067     //   => BooleanNot(ReferenceEqual(x,#null))
   1068     node->ReplaceInput(0, graph()->NewNode(simplified()->ReferenceEqual(),
   1069                                            input, jsgraph()->NullConstant()));
   1070     node->TrimInputCount(1);
   1071     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
   1072     return Changed(node);
   1073   } else if (input_type->Is(Type::ReceiverOrNullOrUndefined())) {
   1074     // JSToBoolean(x:receiver \/ null \/ undefined)
   1075     //   => BooleanNot(ObjectIsUndetectable(x))
   1076     node->ReplaceInput(
   1077         0, graph()->NewNode(simplified()->ObjectIsUndetectable(), input));
   1078     node->TrimInputCount(1);
   1079     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
   1080     return Changed(node);
   1081   } else if (input_type->Is(Type::String())) {
   1082     // JSToBoolean(x:string) => BooleanNot(ReferenceEqual(x,""))
   1083     node->ReplaceInput(0,
   1084                        graph()->NewNode(simplified()->ReferenceEqual(), input,
   1085                                         jsgraph()->EmptyStringConstant()));
   1086     node->TrimInputCount(1);
   1087     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
   1088     return Changed(node);
   1089   }
   1090   return NoChange();
   1091 }
   1092 
   1093 Reduction JSTypedLowering::ReduceJSToInteger(Node* node) {
   1094   Node* const input = NodeProperties::GetValueInput(node, 0);
   1095   Type* const input_type = NodeProperties::GetType(input);
   1096   if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
   1097     // JSToInteger(x:integer) => x
   1098     ReplaceWithValue(node, input);
   1099     return Replace(input);
   1100   }
   1101   return NoChange();
   1102 }
   1103 
   1104 Reduction JSTypedLowering::ReduceJSToName(Node* node) {
   1105   Node* const input = NodeProperties::GetValueInput(node, 0);
   1106   Type* const input_type = NodeProperties::GetType(input);
   1107   if (input_type->Is(Type::Name())) {
   1108     // JSToName(x:name) => x
   1109     ReplaceWithValue(node, input);
   1110     return Replace(input);
   1111   }
   1112   return NoChange();
   1113 }
   1114 
   1115 Reduction JSTypedLowering::ReduceJSToLength(Node* node) {
   1116   Node* input = NodeProperties::GetValueInput(node, 0);
   1117   Type* input_type = NodeProperties::GetType(input);
   1118   if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
   1119     if (input_type->Max() <= 0.0) {
   1120       input = jsgraph()->ZeroConstant();
   1121     } else if (input_type->Min() >= kMaxSafeInteger) {
   1122       input = jsgraph()->Constant(kMaxSafeInteger);
   1123     } else {
   1124       if (input_type->Min() <= 0.0) {
   1125         input = graph()->NewNode(simplified()->NumberMax(),
   1126                                  jsgraph()->ZeroConstant(), input);
   1127       }
   1128       if (input_type->Max() > kMaxSafeInteger) {
   1129         input = graph()->NewNode(simplified()->NumberMin(),
   1130                                  jsgraph()->Constant(kMaxSafeInteger), input);
   1131       }
   1132     }
   1133     ReplaceWithValue(node, input);
   1134     return Replace(input);
   1135   }
   1136   return NoChange();
   1137 }
   1138 
   1139 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
   1140   // Try constant-folding of JSToNumber with constant inputs.
   1141   Type* input_type = NodeProperties::GetType(input);
   1142   if (input_type->Is(Type::String())) {
   1143     HeapObjectMatcher m(input);
   1144     if (m.HasValue() && m.Value()->IsString()) {
   1145       Handle<Object> input_value = m.Value();
   1146       return Replace(jsgraph()->Constant(
   1147           String::ToNumber(Handle<String>::cast(input_value))));
   1148     }
   1149   }
   1150   if (input_type->IsHeapConstant()) {
   1151     Handle<Object> input_value = input_type->AsHeapConstant()->Value();
   1152     if (input_value->IsOddball()) {
   1153       return Replace(jsgraph()->Constant(
   1154           Oddball::ToNumber(Handle<Oddball>::cast(input_value))));
   1155     }
   1156   }
   1157   if (input_type->Is(Type::Number())) {
   1158     // JSToNumber(x:number) => x
   1159     return Changed(input);
   1160   }
   1161   if (input_type->Is(Type::Undefined())) {
   1162     // JSToNumber(undefined) => #NaN
   1163     return Replace(jsgraph()->NaNConstant());
   1164   }
   1165   if (input_type->Is(Type::Null())) {
   1166     // JSToNumber(null) => #0
   1167     return Replace(jsgraph()->ZeroConstant());
   1168   }
   1169   return NoChange();
   1170 }
   1171 
   1172 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
   1173   // Try to reduce the input first.
   1174   Node* const input = node->InputAt(0);
   1175   Reduction reduction = ReduceJSToNumberInput(input);
   1176   if (reduction.Changed()) {
   1177     ReplaceWithValue(node, reduction.replacement());
   1178     return reduction;
   1179   }
   1180   Type* const input_type = NodeProperties::GetType(input);
   1181   if (input_type->Is(Type::PlainPrimitive())) {
   1182     RelaxEffectsAndControls(node);
   1183     node->TrimInputCount(1);
   1184     NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
   1185     return Changed(node);
   1186   }
   1187   return NoChange();
   1188 }
   1189 
   1190 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
   1191   if (input->opcode() == IrOpcode::kJSToString) {
   1192     // Recursively try to reduce the input first.
   1193     Reduction result = ReduceJSToString(input);
   1194     if (result.Changed()) return result;
   1195     return Changed(input);  // JSToString(JSToString(x)) => JSToString(x)
   1196   }
   1197   Type* input_type = NodeProperties::GetType(input);
   1198   if (input_type->Is(Type::String())) {
   1199     return Changed(input);  // JSToString(x:string) => x
   1200   }
   1201   if (input_type->Is(Type::Boolean())) {
   1202     return Replace(graph()->NewNode(
   1203         common()->Select(MachineRepresentation::kTagged), input,
   1204         jsgraph()->HeapConstant(factory()->true_string()),
   1205         jsgraph()->HeapConstant(factory()->false_string())));
   1206   }
   1207   if (input_type->Is(Type::Undefined())) {
   1208     return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
   1209   }
   1210   if (input_type->Is(Type::Null())) {
   1211     return Replace(jsgraph()->HeapConstant(factory()->null_string()));
   1212   }
   1213   // TODO(turbofan): js-typed-lowering of ToString(x:number)
   1214   return NoChange();
   1215 }
   1216 
   1217 Reduction JSTypedLowering::ReduceJSToString(Node* node) {
   1218   // Try to reduce the input first.
   1219   Node* const input = node->InputAt(0);
   1220   Reduction reduction = ReduceJSToStringInput(input);
   1221   if (reduction.Changed()) {
   1222     ReplaceWithValue(node, reduction.replacement());
   1223     return reduction;
   1224   }
   1225   return NoChange();
   1226 }
   1227 
   1228 Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
   1229   DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
   1230   Node* receiver = NodeProperties::GetValueInput(node, 0);
   1231   Type* receiver_type = NodeProperties::GetType(receiver);
   1232   Node* context = NodeProperties::GetContextInput(node);
   1233   Node* frame_state = NodeProperties::GetFrameStateInput(node);
   1234   Node* effect = NodeProperties::GetEffectInput(node);
   1235   Node* control = NodeProperties::GetControlInput(node);
   1236   if (receiver_type->Is(Type::Receiver())) {
   1237     ReplaceWithValue(node, receiver, effect, control);
   1238     return Replace(receiver);
   1239   }
   1240 
   1241   // TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks.
   1242   if (receiver_type->Maybe(Type::NullOrUndefined()) &&
   1243       NodeProperties::IsExceptionalCall(node)) {
   1244     // ToObject throws for null or undefined inputs.
   1245     return NoChange();
   1246   }
   1247 
   1248   // Check whether {receiver} is a spec object.
   1249   Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
   1250   Node* branch =
   1251       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
   1252 
   1253   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
   1254   Node* etrue = effect;
   1255   Node* rtrue = receiver;
   1256 
   1257   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
   1258   Node* efalse = effect;
   1259   Node* rfalse;
   1260   {
   1261     // Convert {receiver} using the ToObjectStub.
   1262     Callable callable = CodeFactory::ToObject(isolate());
   1263     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
   1264         isolate(), graph()->zone(), callable.descriptor(), 0,
   1265         CallDescriptor::kNeedsFrameState, node->op()->properties());
   1266     rfalse = efalse = graph()->NewNode(
   1267         common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
   1268         receiver, context, frame_state, efalse, if_false);
   1269     if_false = graph()->NewNode(common()->IfSuccess(), rfalse);
   1270   }
   1271 
   1272   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
   1273   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
   1274 
   1275   // Morph the {node} into an appropriate Phi.
   1276   ReplaceWithValue(node, node, effect, control);
   1277   node->ReplaceInput(0, rtrue);
   1278   node->ReplaceInput(1, rfalse);
   1279   node->ReplaceInput(2, control);
   1280   node->TrimInputCount(3);
   1281   NodeProperties::ChangeOp(node,
   1282                            common()->Phi(MachineRepresentation::kTagged, 2));
   1283   return Changed(node);
   1284 }
   1285 
   1286 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
   1287   DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
   1288   Node* receiver = NodeProperties::GetValueInput(node, 0);
   1289   Type* receiver_type = NodeProperties::GetType(receiver);
   1290   Node* effect = NodeProperties::GetEffectInput(node);
   1291   Node* control = NodeProperties::GetControlInput(node);
   1292   Handle<Name> name = NamedAccessOf(node->op()).name();
   1293   // Optimize "length" property of strings.
   1294   if (name.is_identical_to(factory()->length_string()) &&
   1295       receiver_type->Is(Type::String())) {
   1296     Node* value = effect = graph()->NewNode(
   1297         simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
   1298         effect, control);
   1299     ReplaceWithValue(node, value, effect);
   1300     return Replace(value);
   1301   }
   1302   return NoChange();
   1303 }
   1304 
   1305 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
   1306   Node* key = NodeProperties::GetValueInput(node, 1);
   1307   Node* base = NodeProperties::GetValueInput(node, 0);
   1308   Type* key_type = NodeProperties::GetType(key);
   1309   HeapObjectMatcher mbase(base);
   1310   if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
   1311     Handle<JSTypedArray> const array =
   1312         Handle<JSTypedArray>::cast(mbase.Value());
   1313     if (!array->GetBuffer()->was_neutered()) {
   1314       array->GetBuffer()->set_is_neuterable(false);
   1315       BufferAccess const access(array->type());
   1316       size_t const k =
   1317           ElementSizeLog2Of(access.machine_type().representation());
   1318       double const byte_length = array->byte_length()->Number();
   1319       CHECK_LT(k, arraysize(shifted_int32_ranges_));
   1320       if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
   1321         // JSLoadProperty(typed-array, int32)
   1322         Handle<FixedTypedArrayBase> elements =
   1323             Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
   1324         Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
   1325         Node* length = jsgraph()->Constant(byte_length);
   1326         Node* effect = NodeProperties::GetEffectInput(node);
   1327         Node* control = NodeProperties::GetControlInput(node);
   1328         // Check if we can avoid the bounds check.
   1329         if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
   1330           Node* load = graph()->NewNode(
   1331               simplified()->LoadElement(
   1332                   AccessBuilder::ForTypedArrayElement(array->type(), true)),
   1333               buffer, key, effect, control);
   1334           ReplaceWithValue(node, load, load);
   1335           return Replace(load);
   1336         }
   1337         // Compute byte offset.
   1338         Node* offset =
   1339             (k == 0) ? key : graph()->NewNode(
   1340                                  simplified()->NumberShiftLeft(), key,
   1341                                  jsgraph()->Constant(static_cast<double>(k)));
   1342         Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer,
   1343                                       offset, length, effect, control);
   1344         ReplaceWithValue(node, load, load);
   1345         return Replace(load);
   1346       }
   1347     }
   1348   }
   1349   return NoChange();
   1350 }
   1351 
   1352 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
   1353   Node* key = NodeProperties::GetValueInput(node, 1);
   1354   Node* base = NodeProperties::GetValueInput(node, 0);
   1355   Node* value = NodeProperties::GetValueInput(node, 2);
   1356   Type* key_type = NodeProperties::GetType(key);
   1357   Type* value_type = NodeProperties::GetType(value);
   1358 
   1359   if (!value_type->Is(Type::PlainPrimitive())) return NoChange();
   1360 
   1361   HeapObjectMatcher mbase(base);
   1362   if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
   1363     Handle<JSTypedArray> const array =
   1364         Handle<JSTypedArray>::cast(mbase.Value());
   1365     if (!array->GetBuffer()->was_neutered()) {
   1366       array->GetBuffer()->set_is_neuterable(false);
   1367       BufferAccess const access(array->type());
   1368       size_t const k =
   1369           ElementSizeLog2Of(access.machine_type().representation());
   1370       double const byte_length = array->byte_length()->Number();
   1371       CHECK_LT(k, arraysize(shifted_int32_ranges_));
   1372       if (access.external_array_type() != kExternalUint8ClampedArray &&
   1373           key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
   1374         // JSLoadProperty(typed-array, int32)
   1375         Handle<FixedTypedArrayBase> elements =
   1376             Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
   1377         Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
   1378         Node* length = jsgraph()->Constant(byte_length);
   1379         Node* effect = NodeProperties::GetEffectInput(node);
   1380         Node* control = NodeProperties::GetControlInput(node);
   1381         // Convert to a number first.
   1382         if (!value_type->Is(Type::Number())) {
   1383           Reduction number_reduction = ReduceJSToNumberInput(value);
   1384           if (number_reduction.Changed()) {
   1385             value = number_reduction.replacement();
   1386           } else {
   1387             value =
   1388                 graph()->NewNode(simplified()->PlainPrimitiveToNumber(), value);
   1389           }
   1390         }
   1391         // Check if we can avoid the bounds check.
   1392         if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
   1393           RelaxControls(node);
   1394           node->ReplaceInput(0, buffer);
   1395           DCHECK_EQ(key, node->InputAt(1));
   1396           node->ReplaceInput(2, value);
   1397           node->ReplaceInput(3, effect);
   1398           node->ReplaceInput(4, control);
   1399           node->TrimInputCount(5);
   1400           NodeProperties::ChangeOp(
   1401               node,
   1402               simplified()->StoreElement(
   1403                   AccessBuilder::ForTypedArrayElement(array->type(), true)));
   1404           return Changed(node);
   1405         }
   1406         // Compute byte offset.
   1407         Node* offset =
   1408             (k == 0) ? key : graph()->NewNode(
   1409                                  simplified()->NumberShiftLeft(), key,
   1410                                  jsgraph()->Constant(static_cast<double>(k)));
   1411         // Turn into a StoreBuffer operation.
   1412         RelaxControls(node);
   1413         node->ReplaceInput(0, buffer);
   1414         node->ReplaceInput(1, offset);
   1415         node->ReplaceInput(2, length);
   1416         node->ReplaceInput(3, value);
   1417         node->ReplaceInput(4, effect);
   1418         node->ReplaceInput(5, control);
   1419         node->TrimInputCount(6);
   1420         NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access));
   1421         return Changed(node);
   1422       }
   1423     }
   1424   }
   1425   return NoChange();
   1426 }
   1427 
   1428 Reduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) {
   1429   DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
   1430   Node* constructor = NodeProperties::GetValueInput(node, 0);
   1431   Type* constructor_type = NodeProperties::GetType(constructor);
   1432   Node* object = NodeProperties::GetValueInput(node, 1);
   1433   Type* object_type = NodeProperties::GetType(object);
   1434   Node* context = NodeProperties::GetContextInput(node);
   1435   Node* frame_state = NodeProperties::GetFrameStateInput(node);
   1436   Node* effect = NodeProperties::GetEffectInput(node);
   1437   Node* control = NodeProperties::GetControlInput(node);
   1438 
   1439   // Check if the {constructor} cannot be callable.
   1440   // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 1.
   1441   if (!constructor_type->Maybe(Type::Callable())) {
   1442     Node* value = jsgraph()->FalseConstant();
   1443     ReplaceWithValue(node, value, effect, control);
   1444     return Replace(value);
   1445   }
   1446 
   1447   // If the {constructor} cannot be a JSBoundFunction and then {object}
   1448   // cannot be a JSReceiver, then this can be constant-folded to false.
   1449   // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 2 and 3.
   1450   if (!object_type->Maybe(Type::Receiver()) &&
   1451       !constructor_type->Maybe(Type::BoundFunction())) {
   1452     Node* value = jsgraph()->FalseConstant();
   1453     ReplaceWithValue(node, value, effect, control);
   1454     return Replace(value);
   1455   }
   1456 
   1457   // Check if the {constructor} is a (known) JSFunction.
   1458   if (!constructor_type->IsHeapConstant() ||
   1459       !constructor_type->AsHeapConstant()->Value()->IsJSFunction()) {
   1460     return NoChange();
   1461   }
   1462   Handle<JSFunction> function =
   1463       Handle<JSFunction>::cast(constructor_type->AsHeapConstant()->Value());
   1464 
   1465   // Check if the {function} already has an initial map (i.e. the
   1466   // {function} has been used as a constructor at least once).
   1467   if (!function->has_initial_map()) return NoChange();
   1468 
   1469   // Check if the {function}s "prototype" is a JSReceiver.
   1470   if (!function->prototype()->IsJSReceiver()) return NoChange();
   1471 
   1472   // Install a code dependency on the {function}s initial map.
   1473   Handle<Map> initial_map(function->initial_map(), isolate());
   1474   dependencies()->AssumeInitialMapCantChange(initial_map);
   1475 
   1476   Node* prototype =
   1477       jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
   1478 
   1479   Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), object);
   1480   Node* branch0 =
   1481       graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
   1482 
   1483   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   1484   Node* etrue0 = effect;
   1485   Node* vtrue0 = jsgraph()->FalseConstant();
   1486 
   1487   control = graph()->NewNode(common()->IfFalse(), branch0);
   1488 
   1489   // Loop through the {object}s prototype chain looking for the {prototype}.
   1490   Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
   1491   Node* eloop = effect =
   1492       graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
   1493   Node* vloop = object = graph()->NewNode(
   1494       common()->Phi(MachineRepresentation::kTagged, 2), object, object, loop);
   1495   // TODO(jarin): This is a very ugly hack to work-around the super-smart
   1496   // implicit typing of the Phi, which goes completely nuts if the {object}
   1497   // is for example a HeapConstant.
   1498   NodeProperties::SetType(vloop, Type::NonInternal());
   1499 
   1500   // Load the {object} map and instance type.
   1501   Node* object_map = effect =
   1502       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), object,
   1503                        effect, control);
   1504   Node* object_instance_type = effect = graph()->NewNode(
   1505       simplified()->LoadField(AccessBuilder::ForMapInstanceType()), object_map,
   1506       effect, control);
   1507 
   1508   // Check if the {object} is a special receiver, because for special
   1509   // receivers, i.e. proxies or API objects that need access checks,
   1510   // we have to use the %HasInPrototypeChain runtime function instead.
   1511   Node* check1 = graph()->NewNode(
   1512       simplified()->NumberLessThanOrEqual(), object_instance_type,
   1513       jsgraph()->Constant(LAST_SPECIAL_RECEIVER_TYPE));
   1514   Node* branch1 =
   1515       graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
   1516 
   1517   control = graph()->NewNode(common()->IfFalse(), branch1);
   1518 
   1519   Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   1520   Node* etrue1 = effect;
   1521   Node* vtrue1;
   1522 
   1523   // Check if the {object} is not a receiver at all.
   1524   Node* check10 =
   1525       graph()->NewNode(simplified()->NumberLessThan(), object_instance_type,
   1526                        jsgraph()->Constant(FIRST_JS_RECEIVER_TYPE));
   1527   Node* branch10 =
   1528       graph()->NewNode(common()->Branch(BranchHint::kTrue), check10, if_true1);
   1529 
   1530   // A primitive value cannot match the {prototype} we're looking for.
   1531   if_true1 = graph()->NewNode(common()->IfTrue(), branch10);
   1532   vtrue1 = jsgraph()->FalseConstant();
   1533 
   1534   Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10);
   1535   Node* efalse1 = etrue1;
   1536   Node* vfalse1;
   1537   {
   1538     // Slow path, need to call the %HasInPrototypeChain runtime function.
   1539     vfalse1 = efalse1 = graph()->NewNode(
   1540         javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object,
   1541         prototype, context, frame_state, efalse1, if_false1);
   1542     if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
   1543 
   1544     // Replace any potential IfException on {node} to catch exceptions
   1545     // from this %HasInPrototypeChain runtime call instead.
   1546     for (Edge edge : node->use_edges()) {
   1547       if (edge.from()->opcode() == IrOpcode::kIfException) {
   1548         edge.UpdateTo(vfalse1);
   1549         Revisit(edge.from());
   1550       }
   1551     }
   1552   }
   1553 
   1554   // Load the {object} prototype.
   1555   Node* object_prototype = effect = graph()->NewNode(
   1556       simplified()->LoadField(AccessBuilder::ForMapPrototype()), object_map,
   1557       effect, control);
   1558 
   1559   // Check if we reached the end of {object}s prototype chain.
   1560   Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(),
   1561                                   object_prototype, jsgraph()->NullConstant());
   1562   Node* branch2 = graph()->NewNode(common()->Branch(), check2, control);
   1563 
   1564   Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
   1565   Node* etrue2 = effect;
   1566   Node* vtrue2 = jsgraph()->FalseConstant();
   1567 
   1568   control = graph()->NewNode(common()->IfFalse(), branch2);
   1569 
   1570   // Check if we reached the {prototype}.
   1571   Node* check3 = graph()->NewNode(simplified()->ReferenceEqual(),
   1572                                   object_prototype, prototype);
   1573   Node* branch3 = graph()->NewNode(common()->Branch(), check3, control);
   1574 
   1575   Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
   1576   Node* etrue3 = effect;
   1577   Node* vtrue3 = jsgraph()->TrueConstant();
   1578 
   1579   control = graph()->NewNode(common()->IfFalse(), branch3);
   1580 
   1581   // Close the loop.
   1582   vloop->ReplaceInput(1, object_prototype);
   1583   eloop->ReplaceInput(1, effect);
   1584   loop->ReplaceInput(1, control);
   1585 
   1586   control = graph()->NewNode(common()->Merge(5), if_true0, if_true1, if_true2,
   1587                              if_true3, if_false1);
   1588   effect = graph()->NewNode(common()->EffectPhi(5), etrue0, etrue1, etrue2,
   1589                             etrue3, efalse1, control);
   1590 
   1591   // Morph the {node} into an appropriate Phi.
   1592   ReplaceWithValue(node, node, effect, control);
   1593   node->ReplaceInput(0, vtrue0);
   1594   node->ReplaceInput(1, vtrue1);
   1595   node->ReplaceInput(2, vtrue2);
   1596   node->ReplaceInput(3, vtrue3);
   1597   node->ReplaceInput(4, vfalse1);
   1598   node->ReplaceInput(5, control);
   1599   node->TrimInputCount(6);
   1600   NodeProperties::ChangeOp(node,
   1601                            common()->Phi(MachineRepresentation::kTagged, 5));
   1602   return Changed(node);
   1603 }
   1604 
   1605 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
   1606   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
   1607   ContextAccess const& access = ContextAccessOf(node->op());
   1608   Node* effect = NodeProperties::GetEffectInput(node);
   1609   Node* context = NodeProperties::GetContextInput(node);
   1610   Node* control = graph()->start();
   1611   for (size_t i = 0; i < access.depth(); ++i) {
   1612     context = effect = graph()->NewNode(
   1613         simplified()->LoadField(
   1614             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
   1615         context, effect, control);
   1616   }
   1617   node->ReplaceInput(0, context);
   1618   node->ReplaceInput(1, effect);
   1619   node->AppendInput(jsgraph()->zone(), control);
   1620   NodeProperties::ChangeOp(
   1621       node,
   1622       simplified()->LoadField(AccessBuilder::ForContextSlot(access.index())));
   1623   return Changed(node);
   1624 }
   1625 
   1626 Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
   1627   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
   1628   ContextAccess const& access = ContextAccessOf(node->op());
   1629   Node* effect = NodeProperties::GetEffectInput(node);
   1630   Node* context = NodeProperties::GetContextInput(node);
   1631   Node* control = graph()->start();
   1632   Node* value = NodeProperties::GetValueInput(node, 0);
   1633   for (size_t i = 0; i < access.depth(); ++i) {
   1634     context = effect = graph()->NewNode(
   1635         simplified()->LoadField(
   1636             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
   1637         context, effect, control);
   1638   }
   1639   node->ReplaceInput(0, context);
   1640   node->ReplaceInput(1, value);
   1641   node->ReplaceInput(2, effect);
   1642   NodeProperties::ChangeOp(
   1643       node,
   1644       simplified()->StoreField(AccessBuilder::ForContextSlot(access.index())));
   1645   return Changed(node);
   1646 }
   1647 
   1648 Reduction JSTypedLowering::ReduceJSLoadModule(Node* node) {
   1649   DCHECK_EQ(IrOpcode::kJSLoadModule, node->opcode());
   1650   Node* effect = NodeProperties::GetEffectInput(node);
   1651   Node* control = NodeProperties::GetControlInput(node);
   1652 
   1653   int32_t cell_index = OpParameter<int32_t>(node);
   1654   Node* module = NodeProperties::GetValueInput(node, 0);
   1655 
   1656   Node* array;
   1657   int index;
   1658   if (ModuleDescriptor::GetCellIndexKind(cell_index) ==
   1659       ModuleDescriptor::kExport) {
   1660     array = effect = graph()->NewNode(
   1661         simplified()->LoadField(AccessBuilder::ForModuleRegularExports()),
   1662         module, effect, control);
   1663     index = cell_index - 1;
   1664   } else {
   1665     DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
   1666               ModuleDescriptor::kImport);
   1667     array = effect = graph()->NewNode(
   1668         simplified()->LoadField(AccessBuilder::ForModuleRegularImports()),
   1669         module, effect, control);
   1670     index = -cell_index - 1;
   1671   }
   1672 
   1673   Node* cell = effect = graph()->NewNode(
   1674       simplified()->LoadField(AccessBuilder::ForFixedArraySlot(index)), array,
   1675       effect, control);
   1676 
   1677   Node* value = effect =
   1678       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForCellValue()),
   1679                        cell, effect, control);
   1680 
   1681   ReplaceWithValue(node, value, effect, control);
   1682   return Changed(value);
   1683 }
   1684 
   1685 Reduction JSTypedLowering::ReduceJSStoreModule(Node* node) {
   1686   DCHECK_EQ(IrOpcode::kJSStoreModule, node->opcode());
   1687   Node* effect = NodeProperties::GetEffectInput(node);
   1688   Node* control = NodeProperties::GetControlInput(node);
   1689 
   1690   int32_t cell_index = OpParameter<int32_t>(node);
   1691   Node* module = NodeProperties::GetValueInput(node, 0);
   1692   Node* value = NodeProperties::GetValueInput(node, 1);
   1693 
   1694   Node* array;
   1695   int index;
   1696   if (ModuleDescriptor::GetCellIndexKind(cell_index) ==
   1697       ModuleDescriptor::kExport) {
   1698     array = effect = graph()->NewNode(
   1699         simplified()->LoadField(AccessBuilder::ForModuleRegularExports()),
   1700         module, effect, control);
   1701     index = cell_index - 1;
   1702   } else {
   1703     DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
   1704               ModuleDescriptor::kImport);
   1705     array = effect = graph()->NewNode(
   1706         simplified()->LoadField(AccessBuilder::ForModuleRegularImports()),
   1707         module, effect, control);
   1708     index = -cell_index - 1;
   1709   }
   1710 
   1711   Node* cell = effect = graph()->NewNode(
   1712       simplified()->LoadField(AccessBuilder::ForFixedArraySlot(index)), array,
   1713       effect, control);
   1714 
   1715   effect =
   1716       graph()->NewNode(simplified()->StoreField(AccessBuilder::ForCellValue()),
   1717                        cell, value, effect, control);
   1718 
   1719   ReplaceWithValue(node, effect, effect, control);
   1720   return Changed(value);
   1721 }
   1722 
   1723 Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
   1724   DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
   1725   ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
   1726   Node* receiver = NodeProperties::GetValueInput(node, 0);
   1727   Type* receiver_type = NodeProperties::GetType(receiver);
   1728   Node* context = NodeProperties::GetContextInput(node);
   1729   Type* context_type = NodeProperties::GetType(context);
   1730   Node* effect = NodeProperties::GetEffectInput(node);
   1731   Node* control = NodeProperties::GetControlInput(node);
   1732 
   1733   // Check if {receiver} is known to be a receiver.
   1734   if (receiver_type->Is(Type::Receiver())) {
   1735     ReplaceWithValue(node, receiver, effect, control);
   1736     return Replace(receiver);
   1737   }
   1738 
   1739   // If the {receiver} is known to be null or undefined, we can just replace it
   1740   // with the global proxy unconditionally.
   1741   if (receiver_type->Is(Type::NullOrUndefined()) ||
   1742       mode == ConvertReceiverMode::kNullOrUndefined) {
   1743     if (context_type->IsHeapConstant()) {
   1744       Handle<JSObject> global_proxy(
   1745           Handle<Context>::cast(context_type->AsHeapConstant()->Value())
   1746               ->global_proxy(),
   1747           isolate());
   1748       receiver = jsgraph()->Constant(global_proxy);
   1749     } else {
   1750       Node* native_context = effect = graph()->NewNode(
   1751           javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1752           context, effect);
   1753       receiver = effect = graph()->NewNode(
   1754           javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
   1755           native_context, effect);
   1756     }
   1757     ReplaceWithValue(node, receiver, effect, control);
   1758     return Replace(receiver);
   1759   }
   1760 
   1761   // If {receiver} cannot be null or undefined we can skip a few checks.
   1762   if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
   1763       mode == ConvertReceiverMode::kNotNullOrUndefined) {
   1764     Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
   1765     Node* branch =
   1766         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
   1767 
   1768     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
   1769     Node* etrue = effect;
   1770     Node* rtrue = receiver;
   1771 
   1772     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
   1773     Node* efalse = effect;
   1774     Node* rfalse;
   1775     {
   1776       // Convert {receiver} using the ToObjectStub. The call does not require a
   1777       // frame-state in this case, because neither null nor undefined is passed.
   1778       Callable callable = CodeFactory::ToObject(isolate());
   1779       CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
   1780           isolate(), graph()->zone(), callable.descriptor(), 0,
   1781           CallDescriptor::kNoFlags, node->op()->properties());
   1782       rfalse = efalse = graph()->NewNode(
   1783           common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
   1784           receiver, context, efalse);
   1785     }
   1786 
   1787     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
   1788     effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
   1789 
   1790     // Morph the {node} into an appropriate Phi.
   1791     ReplaceWithValue(node, node, effect, control);
   1792     node->ReplaceInput(0, rtrue);
   1793     node->ReplaceInput(1, rfalse);
   1794     node->ReplaceInput(2, control);
   1795     node->TrimInputCount(3);
   1796     NodeProperties::ChangeOp(node,
   1797                              common()->Phi(MachineRepresentation::kTagged, 2));
   1798     return Changed(node);
   1799   }
   1800 
   1801   // Check if {receiver} is already a JSReceiver.
   1802   Node* check0 = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
   1803   Node* branch0 =
   1804       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
   1805   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   1806   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   1807 
   1808   // Check {receiver} for undefined.
   1809   Node* check1 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
   1810                                   jsgraph()->UndefinedConstant());
   1811   Node* branch1 =
   1812       graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, if_false0);
   1813   Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   1814   Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   1815 
   1816   // Check {receiver} for null.
   1817   Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
   1818                                   jsgraph()->NullConstant());
   1819   Node* branch2 =
   1820       graph()->NewNode(common()->Branch(BranchHint::kFalse), check2, if_false1);
   1821   Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
   1822   Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
   1823 
   1824   // We just use {receiver} directly.
   1825   Node* if_noop = if_true0;
   1826   Node* enoop = effect;
   1827   Node* rnoop = receiver;
   1828 
   1829   // Convert {receiver} using ToObject.
   1830   Node* if_convert = if_false2;
   1831   Node* econvert = effect;
   1832   Node* rconvert;
   1833   {
   1834     // Convert {receiver} using the ToObjectStub. The call does not require a
   1835     // frame-state in this case, because neither null nor undefined is passed.
   1836     Callable callable = CodeFactory::ToObject(isolate());
   1837     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
   1838         isolate(), graph()->zone(), callable.descriptor(), 0,
   1839         CallDescriptor::kNoFlags, node->op()->properties());
   1840     rconvert = econvert = graph()->NewNode(
   1841         common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
   1842         receiver, context, econvert);
   1843   }
   1844 
   1845   // Replace {receiver} with global proxy of {context}.
   1846   Node* if_global = graph()->NewNode(common()->Merge(2), if_true1, if_true2);
   1847   Node* eglobal = effect;
   1848   Node* rglobal;
   1849   {
   1850     if (context_type->IsHeapConstant()) {
   1851       Handle<JSObject> global_proxy(
   1852           Handle<Context>::cast(context_type->AsHeapConstant()->Value())
   1853               ->global_proxy(),
   1854           isolate());
   1855       rglobal = jsgraph()->Constant(global_proxy);
   1856     } else {
   1857       Node* native_context = eglobal = graph()->NewNode(
   1858           javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
   1859           context, eglobal);
   1860       rglobal = eglobal = graph()->NewNode(
   1861           javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
   1862           native_context, eglobal);
   1863     }
   1864   }
   1865 
   1866   control =
   1867       graph()->NewNode(common()->Merge(3), if_noop, if_convert, if_global);
   1868   effect = graph()->NewNode(common()->EffectPhi(3), enoop, econvert, eglobal,
   1869                             control);
   1870   // Morph the {node} into an appropriate Phi.
   1871   ReplaceWithValue(node, node, effect, control);
   1872   node->ReplaceInput(0, rnoop);
   1873   node->ReplaceInput(1, rconvert);
   1874   node->ReplaceInput(2, rglobal);
   1875   node->ReplaceInput(3, control);
   1876   node->TrimInputCount(4);
   1877   NodeProperties::ChangeOp(node,
   1878                            common()->Phi(MachineRepresentation::kTagged, 3));
   1879   return Changed(node);
   1880 }
   1881 
   1882 namespace {
   1883 
   1884 void ReduceBuiltin(Isolate* isolate, JSGraph* jsgraph, Node* node,
   1885                    int builtin_index, int arity, CallDescriptor::Flags flags) {
   1886   // Patch {node} to a direct CEntryStub call.
   1887   //
   1888   // ----------- A r g u m e n t s -----------
   1889   // -- 0: CEntryStub
   1890   // --- Stack args ---
   1891   // -- 1: receiver
   1892   // -- [2, 2 + n[: the n actual arguments passed to the builtin
   1893   // -- 2 + n: argc, including the receiver and implicit args (Smi)
   1894   // -- 2 + n + 1: target
   1895   // -- 2 + n + 2: new_target
   1896   // --- Register args ---
   1897   // -- 2 + n + 3: the C entry point
   1898   // -- 2 + n + 4: argc (Int32)
   1899   // -----------------------------------
   1900 
   1901   // The logic contained here is mirrored in Builtins::Generate_Adaptor.
   1902   // Keep these in sync.
   1903 
   1904   const bool is_construct = (node->opcode() == IrOpcode::kJSConstruct);
   1905 
   1906   DCHECK(Builtins::HasCppImplementation(builtin_index));
   1907   DCHECK_EQ(0, flags & CallDescriptor::kSupportsTailCalls);
   1908 
   1909   Node* target = NodeProperties::GetValueInput(node, 0);
   1910   Node* new_target = is_construct
   1911                          ? NodeProperties::GetValueInput(node, arity + 1)
   1912                          : jsgraph->UndefinedConstant();
   1913 
   1914   // API and CPP builtins are implemented in C++, and we can inline both.
   1915   // CPP builtins create a builtin exit frame, API builtins don't.
   1916   const bool has_builtin_exit_frame = Builtins::IsCpp(builtin_index);
   1917 
   1918   Node* stub = jsgraph->CEntryStubConstant(1, kDontSaveFPRegs, kArgvOnStack,
   1919                                            has_builtin_exit_frame);
   1920   node->ReplaceInput(0, stub);
   1921 
   1922   Zone* zone = jsgraph->zone();
   1923   if (is_construct) {
   1924     // Unify representations between construct and call nodes.
   1925     // Remove new target and add receiver as a stack parameter.
   1926     Node* receiver = jsgraph->UndefinedConstant();
   1927     node->RemoveInput(arity + 1);
   1928     node->InsertInput(zone, 1, receiver);
   1929   }
   1930 
   1931   const int argc = arity + BuiltinArguments::kNumExtraArgsWithReceiver;
   1932   Node* argc_node = jsgraph->Constant(argc);
   1933 
   1934   static const int kStubAndReceiver = 2;
   1935   int cursor = arity + kStubAndReceiver;
   1936   node->InsertInput(zone, cursor++, argc_node);
   1937   node->InsertInput(zone, cursor++, target);
   1938   node->InsertInput(zone, cursor++, new_target);
   1939 
   1940   Address entry = Builtins::CppEntryOf(builtin_index);
   1941   ExternalReference entry_ref(ExternalReference(entry, isolate));
   1942   Node* entry_node = jsgraph->ExternalConstant(entry_ref);
   1943 
   1944   node->InsertInput(zone, cursor++, entry_node);
   1945   node->InsertInput(zone, cursor++, argc_node);
   1946 
   1947   static const int kReturnCount = 1;
   1948   const char* debug_name = Builtins::name(builtin_index);
   1949   Operator::Properties properties = node->op()->properties();
   1950   CallDescriptor* desc = Linkage::GetCEntryStubCallDescriptor(
   1951       zone, kReturnCount, argc, debug_name, properties, flags);
   1952 
   1953   NodeProperties::ChangeOp(node, jsgraph->common()->Call(desc));
   1954 }
   1955 
   1956 bool NeedsArgumentAdaptorFrame(Handle<SharedFunctionInfo> shared, int arity) {
   1957   static const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
   1958   const int num_decl_parms = shared->internal_formal_parameter_count();
   1959   return (num_decl_parms != arity && num_decl_parms != sentinel);
   1960 }
   1961 
   1962 }  // namespace
   1963 
   1964 Reduction JSTypedLowering::ReduceJSConstruct(Node* node) {
   1965   DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
   1966   ConstructParameters const& p = ConstructParametersOf(node->op());
   1967   DCHECK_LE(2u, p.arity());
   1968   int const arity = static_cast<int>(p.arity() - 2);
   1969   Node* target = NodeProperties::GetValueInput(node, 0);
   1970   Type* target_type = NodeProperties::GetType(target);
   1971   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
   1972   Node* effect = NodeProperties::GetEffectInput(node);
   1973   Node* control = NodeProperties::GetControlInput(node);
   1974 
   1975   // Check if {target} is a known JSFunction.
   1976   if (target_type->IsHeapConstant() &&
   1977       target_type->AsHeapConstant()->Value()->IsJSFunction()) {
   1978     Handle<JSFunction> function =
   1979         Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
   1980     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
   1981     const int builtin_index = shared->construct_stub()->builtin_index();
   1982     const bool is_builtin = (builtin_index != -1);
   1983 
   1984     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
   1985 
   1986     if (is_builtin && Builtins::HasCppImplementation(builtin_index) &&
   1987         !NeedsArgumentAdaptorFrame(shared, arity)) {
   1988       // Patch {node} to a direct CEntryStub call.
   1989 
   1990       // Load the context from the {target}.
   1991       Node* context = effect = graph()->NewNode(
   1992           simplified()->LoadField(AccessBuilder::ForJSFunctionContext()),
   1993           target, effect, control);
   1994       NodeProperties::ReplaceContextInput(node, context);
   1995 
   1996       // Update the effect dependency for the {node}.
   1997       NodeProperties::ReplaceEffectInput(node, effect);
   1998 
   1999       ReduceBuiltin(isolate(), jsgraph(), node, builtin_index, arity, flags);
   2000     } else {
   2001       // Patch {node} to an indirect call via the {function}s construct stub.
   2002       Callable callable(handle(shared->construct_stub(), isolate()),
   2003                         ConstructStubDescriptor(isolate()));
   2004       node->RemoveInput(arity + 1);
   2005       node->InsertInput(graph()->zone(), 0,
   2006                         jsgraph()->HeapConstant(callable.code()));
   2007       node->InsertInput(graph()->zone(), 2, new_target);
   2008       node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
   2009       node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
   2010       node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
   2011       NodeProperties::ChangeOp(
   2012           node, common()->Call(Linkage::GetStubCallDescriptor(
   2013                     isolate(), graph()->zone(), callable.descriptor(),
   2014                     1 + arity, flags)));
   2015     }
   2016     return Changed(node);
   2017   }
   2018 
   2019   // Check if {target} is a JSFunction.
   2020   if (target_type->Is(Type::Function())) {
   2021     // Patch {node} to an indirect call via the ConstructFunction builtin.
   2022     Callable callable = CodeFactory::ConstructFunction(isolate());
   2023     node->RemoveInput(arity + 1);
   2024     node->InsertInput(graph()->zone(), 0,
   2025                       jsgraph()->HeapConstant(callable.code()));
   2026     node->InsertInput(graph()->zone(), 2, new_target);
   2027     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
   2028     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
   2029     NodeProperties::ChangeOp(
   2030         node, common()->Call(Linkage::GetStubCallDescriptor(
   2031                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
   2032                   CallDescriptor::kNeedsFrameState)));
   2033     return Changed(node);
   2034   }
   2035 
   2036   return NoChange();
   2037 }
   2038 
   2039 Reduction JSTypedLowering::ReduceJSCallForwardVarargs(Node* node) {
   2040   DCHECK_EQ(IrOpcode::kJSCallForwardVarargs, node->opcode());
   2041   CallForwardVarargsParameters p = CallForwardVarargsParametersOf(node->op());
   2042   Node* target = NodeProperties::GetValueInput(node, 0);
   2043   Type* target_type = NodeProperties::GetType(target);
   2044 
   2045   // Check if {target} is a JSFunction.
   2046   if (target_type->Is(Type::Function())) {
   2047     // Compute flags for the call.
   2048     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
   2049     if (p.tail_call_mode() == TailCallMode::kAllow) {
   2050       flags |= CallDescriptor::kSupportsTailCalls;
   2051     }
   2052 
   2053     // Patch {node} to an indirect call via CallFunctionForwardVarargs.
   2054     Callable callable = CodeFactory::CallFunctionForwardVarargs(isolate());
   2055     node->InsertInput(graph()->zone(), 0,
   2056                       jsgraph()->HeapConstant(callable.code()));
   2057     node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(p.start_index()));
   2058     NodeProperties::ChangeOp(
   2059         node,
   2060         common()->Call(Linkage::GetStubCallDescriptor(
   2061             isolate(), graph()->zone(), callable.descriptor(), 1, flags)));
   2062     return Changed(node);
   2063   }
   2064 
   2065   return NoChange();
   2066 }
   2067 
   2068 Reduction JSTypedLowering::ReduceJSCall(Node* node) {
   2069   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
   2070   CallParameters const& p = CallParametersOf(node->op());
   2071   int const arity = static_cast<int>(p.arity() - 2);
   2072   ConvertReceiverMode convert_mode = p.convert_mode();
   2073   Node* target = NodeProperties::GetValueInput(node, 0);
   2074   Type* target_type = NodeProperties::GetType(target);
   2075   Node* receiver = NodeProperties::GetValueInput(node, 1);
   2076   Type* receiver_type = NodeProperties::GetType(receiver);
   2077   Node* effect = NodeProperties::GetEffectInput(node);
   2078   Node* control = NodeProperties::GetControlInput(node);
   2079 
   2080   // Try to infer receiver {convert_mode} from {receiver} type.
   2081   if (receiver_type->Is(Type::NullOrUndefined())) {
   2082     convert_mode = ConvertReceiverMode::kNullOrUndefined;
   2083   } else if (!receiver_type->Maybe(Type::NullOrUndefined())) {
   2084     convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
   2085   }
   2086 
   2087   // Check if {target} is a known JSFunction.
   2088   if (target_type->IsHeapConstant() &&
   2089       target_type->AsHeapConstant()->Value()->IsJSFunction()) {
   2090     Handle<JSFunction> function =
   2091         Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
   2092     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
   2093     const int builtin_index = shared->code()->builtin_index();
   2094     const bool is_builtin = (builtin_index != -1);
   2095 
   2096     // Class constructors are callable, but [[Call]] will raise an exception.
   2097     // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
   2098     if (IsClassConstructor(shared->kind())) return NoChange();
   2099 
   2100     // Load the context from the {target}.
   2101     Node* context = effect = graph()->NewNode(
   2102         simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
   2103         effect, control);
   2104     NodeProperties::ReplaceContextInput(node, context);
   2105 
   2106     // Check if we need to convert the {receiver}.
   2107     if (is_sloppy(shared->language_mode()) && !shared->native() &&
   2108         !receiver_type->Is(Type::Receiver())) {
   2109       receiver = effect =
   2110           graph()->NewNode(javascript()->ConvertReceiver(convert_mode),
   2111                            receiver, context, effect, control);
   2112       NodeProperties::ReplaceValueInput(node, receiver, 1);
   2113     }
   2114 
   2115     // Update the effect dependency for the {node}.
   2116     NodeProperties::ReplaceEffectInput(node, effect);
   2117 
   2118     // Compute flags for the call.
   2119     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
   2120     if (p.tail_call_mode() == TailCallMode::kAllow) {
   2121       flags |= CallDescriptor::kSupportsTailCalls;
   2122     }
   2123 
   2124     Node* new_target = jsgraph()->UndefinedConstant();
   2125     Node* argument_count = jsgraph()->Constant(arity);
   2126     if (NeedsArgumentAdaptorFrame(shared, arity)) {
   2127       // Patch {node} to an indirect call via the ArgumentsAdaptorTrampoline.
   2128       Callable callable = CodeFactory::ArgumentAdaptor(isolate());
   2129       node->InsertInput(graph()->zone(), 0,
   2130                         jsgraph()->HeapConstant(callable.code()));
   2131       node->InsertInput(graph()->zone(), 2, new_target);
   2132       node->InsertInput(graph()->zone(), 3, argument_count);
   2133       node->InsertInput(
   2134           graph()->zone(), 4,
   2135           jsgraph()->Constant(shared->internal_formal_parameter_count()));
   2136       NodeProperties::ChangeOp(
   2137           node, common()->Call(Linkage::GetStubCallDescriptor(
   2138                     isolate(), graph()->zone(), callable.descriptor(),
   2139                     1 + arity, flags)));
   2140     } else if (is_builtin && Builtins::HasCppImplementation(builtin_index) &&
   2141                ((flags & CallDescriptor::kSupportsTailCalls) == 0)) {
   2142       // Patch {node} to a direct CEntryStub call.
   2143       ReduceBuiltin(isolate(), jsgraph(), node, builtin_index, arity, flags);
   2144     } else {
   2145       // Patch {node} to a direct call.
   2146       node->InsertInput(graph()->zone(), arity + 2, new_target);
   2147       node->InsertInput(graph()->zone(), arity + 3, argument_count);
   2148       NodeProperties::ChangeOp(node,
   2149                                common()->Call(Linkage::GetJSCallDescriptor(
   2150                                    graph()->zone(), false, 1 + arity, flags)));
   2151     }
   2152     return Changed(node);
   2153   }
   2154 
   2155   // Check if {target} is a JSFunction.
   2156   if (target_type->Is(Type::Function())) {
   2157     // Compute flags for the call.
   2158     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
   2159     if (p.tail_call_mode() == TailCallMode::kAllow) {
   2160       flags |= CallDescriptor::kSupportsTailCalls;
   2161     }
   2162 
   2163     // Patch {node} to an indirect call via the CallFunction builtin.
   2164     Callable callable = CodeFactory::CallFunction(isolate(), convert_mode);
   2165     node->InsertInput(graph()->zone(), 0,
   2166                       jsgraph()->HeapConstant(callable.code()));
   2167     node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(arity));
   2168     NodeProperties::ChangeOp(
   2169         node, common()->Call(Linkage::GetStubCallDescriptor(
   2170                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
   2171                   flags)));
   2172     return Changed(node);
   2173   }
   2174 
   2175   // Maybe we did at least learn something about the {receiver}.
   2176   if (p.convert_mode() != convert_mode) {
   2177     NodeProperties::ChangeOp(
   2178         node,
   2179         javascript()->Call(p.arity(), p.frequency(), p.feedback(), convert_mode,
   2180                            p.tail_call_mode()));
   2181     return Changed(node);
   2182   }
   2183 
   2184   return NoChange();
   2185 }
   2186 
   2187 
   2188 Reduction JSTypedLowering::ReduceJSForInNext(Node* node) {
   2189   DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode());
   2190   Node* receiver = NodeProperties::GetValueInput(node, 0);
   2191   Node* cache_array = NodeProperties::GetValueInput(node, 1);
   2192   Node* cache_type = NodeProperties::GetValueInput(node, 2);
   2193   Node* index = NodeProperties::GetValueInput(node, 3);
   2194   Node* context = NodeProperties::GetContextInput(node);
   2195   Node* frame_state = NodeProperties::GetFrameStateInput(node);
   2196   Node* effect = NodeProperties::GetEffectInput(node);
   2197   Node* control = NodeProperties::GetControlInput(node);
   2198 
   2199   // We don't support lowering JSForInNext inside try blocks.
   2200   if (NodeProperties::IsExceptionalCall(node)) return NoChange();
   2201 
   2202   // We know that the {index} is in Unsigned32 range here, otherwise executing
   2203   // the JSForInNext wouldn't be valid. Unfortunately due to OSR and generators
   2204   // this is not always reflected in the types, hence we might need to rename
   2205   // the {index} here.
   2206   if (!NodeProperties::GetType(index)->Is(Type::Unsigned32())) {
   2207     index = graph()->NewNode(common()->TypeGuard(Type::Unsigned32()), index,
   2208                              control);
   2209   }
   2210 
   2211   // Load the next {key} from the {cache_array}.
   2212   Node* key = effect = graph()->NewNode(
   2213       simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
   2214       cache_array, index, effect, control);
   2215 
   2216   // Load the map of the {receiver}.
   2217   Node* receiver_map = effect =
   2218       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
   2219                        receiver, effect, control);
   2220 
   2221   // Check if the expected map still matches that of the {receiver}.
   2222   Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), receiver_map,
   2223                                   cache_type);
   2224   Node* branch0 =
   2225       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
   2226 
   2227   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   2228   Node* etrue0;
   2229   Node* vtrue0;
   2230   {
   2231     // Don't need filtering since expected map still matches that of the
   2232     // {receiver}.
   2233     etrue0 = effect;
   2234     vtrue0 = key;
   2235   }
   2236 
   2237   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   2238   Node* efalse0;
   2239   Node* vfalse0;
   2240   {
   2241     // Filter the {key} to check if it's still a valid property of the
   2242     // {receiver} (does the ToName conversion implicitly).
   2243     Callable const callable = CodeFactory::ForInFilter(isolate());
   2244     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
   2245         isolate(), graph()->zone(), callable.descriptor(), 0,
   2246         CallDescriptor::kNeedsFrameState);
   2247     vfalse0 = efalse0 = graph()->NewNode(
   2248         common()->Call(desc), jsgraph()->HeapConstant(callable.code()), key,
   2249         receiver, context, frame_state, effect, if_false0);
   2250     if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
   2251   }
   2252 
   2253   control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
   2254   effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
   2255   ReplaceWithValue(node, node, effect, control);
   2256   node->ReplaceInput(0, vtrue0);
   2257   node->ReplaceInput(1, vfalse0);
   2258   node->ReplaceInput(2, control);
   2259   node->TrimInputCount(3);
   2260   NodeProperties::ChangeOp(node,
   2261                            common()->Phi(MachineRepresentation::kTagged, 2));
   2262   return Changed(node);
   2263 }
   2264 
   2265 Reduction JSTypedLowering::ReduceJSLoadMessage(Node* node) {
   2266   DCHECK_EQ(IrOpcode::kJSLoadMessage, node->opcode());
   2267   ExternalReference const ref =
   2268       ExternalReference::address_of_pending_message_obj(isolate());
   2269   node->ReplaceInput(0, jsgraph()->ExternalConstant(ref));
   2270   NodeProperties::ChangeOp(
   2271       node, simplified()->LoadField(AccessBuilder::ForExternalTaggedValue()));
   2272   return Changed(node);
   2273 }
   2274 
   2275 Reduction JSTypedLowering::ReduceJSStoreMessage(Node* node) {
   2276   DCHECK_EQ(IrOpcode::kJSStoreMessage, node->opcode());
   2277   ExternalReference const ref =
   2278       ExternalReference::address_of_pending_message_obj(isolate());
   2279   Node* value = NodeProperties::GetValueInput(node, 0);
   2280   node->ReplaceInput(0, jsgraph()->ExternalConstant(ref));
   2281   node->ReplaceInput(1, value);
   2282   NodeProperties::ChangeOp(
   2283       node, simplified()->StoreField(AccessBuilder::ForExternalTaggedValue()));
   2284   return Changed(node);
   2285 }
   2286 
   2287 Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
   2288   DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode());
   2289   Node* generator = NodeProperties::GetValueInput(node, 0);
   2290   Node* continuation = NodeProperties::GetValueInput(node, 1);
   2291   Node* offset = NodeProperties::GetValueInput(node, 2);
   2292   Node* context = NodeProperties::GetContextInput(node);
   2293   Node* effect = NodeProperties::GetEffectInput(node);
   2294   Node* control = NodeProperties::GetControlInput(node);
   2295   int register_count = OpParameter<int>(node);
   2296 
   2297   FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectRegisterFile();
   2298   FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext();
   2299   FieldAccess continuation_field =
   2300       AccessBuilder::ForJSGeneratorObjectContinuation();
   2301   FieldAccess input_or_debug_pos_field =
   2302       AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
   2303 
   2304   Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
   2305                                           generator, effect, control);
   2306 
   2307   for (int i = 0; i < register_count; ++i) {
   2308     Node* value = NodeProperties::GetValueInput(node, 3 + i);
   2309     effect = graph()->NewNode(
   2310         simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array,
   2311         value, effect, control);
   2312   }
   2313 
   2314   effect = graph()->NewNode(simplified()->StoreField(context_field), generator,
   2315                             context, effect, control);
   2316   effect = graph()->NewNode(simplified()->StoreField(continuation_field),
   2317                             generator, continuation, effect, control);
   2318   effect = graph()->NewNode(simplified()->StoreField(input_or_debug_pos_field),
   2319                             generator, offset, effect, control);
   2320 
   2321   ReplaceWithValue(node, effect, effect, control);
   2322   return Changed(effect);
   2323 }
   2324 
   2325 Reduction JSTypedLowering::ReduceJSGeneratorRestoreContinuation(Node* node) {
   2326   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContinuation, node->opcode());
   2327   Node* generator = NodeProperties::GetValueInput(node, 0);
   2328   Node* effect = NodeProperties::GetEffectInput(node);
   2329   Node* control = NodeProperties::GetControlInput(node);
   2330 
   2331   FieldAccess continuation_field =
   2332       AccessBuilder::ForJSGeneratorObjectContinuation();
   2333 
   2334   Node* continuation = effect = graph()->NewNode(
   2335       simplified()->LoadField(continuation_field), generator, effect, control);
   2336   Node* executing = jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting);
   2337   effect = graph()->NewNode(simplified()->StoreField(continuation_field),
   2338                             generator, executing, effect, control);
   2339 
   2340   ReplaceWithValue(node, continuation, effect, control);
   2341   return Changed(continuation);
   2342 }
   2343 
   2344 Reduction JSTypedLowering::ReduceJSGeneratorRestoreRegister(Node* node) {
   2345   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreRegister, node->opcode());
   2346   Node* generator = NodeProperties::GetValueInput(node, 0);
   2347   Node* effect = NodeProperties::GetEffectInput(node);
   2348   Node* control = NodeProperties::GetControlInput(node);
   2349   int index = OpParameter<int>(node);
   2350 
   2351   FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectRegisterFile();
   2352   FieldAccess element_field = AccessBuilder::ForFixedArraySlot(index);
   2353 
   2354   Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
   2355                                           generator, effect, control);
   2356   Node* element = effect = graph()->NewNode(
   2357       simplified()->LoadField(element_field), array, effect, control);
   2358   Node* stale = jsgraph()->StaleRegisterConstant();
   2359   effect = graph()->NewNode(simplified()->StoreField(element_field), array,
   2360                             stale, effect, control);
   2361 
   2362   ReplaceWithValue(node, element, effect, control);
   2363   return Changed(element);
   2364 }
   2365 
   2366 Reduction JSTypedLowering::Reduce(Node* node) {
   2367   switch (node->opcode()) {
   2368     case IrOpcode::kJSEqual:
   2369       return ReduceJSEqual(node, false);
   2370     case IrOpcode::kJSNotEqual:
   2371       return ReduceJSEqual(node, true);
   2372     case IrOpcode::kJSStrictEqual:
   2373       return ReduceJSStrictEqual(node, false);
   2374     case IrOpcode::kJSStrictNotEqual:
   2375       return ReduceJSStrictEqual(node, true);
   2376     case IrOpcode::kJSLessThan:         // fall through
   2377     case IrOpcode::kJSGreaterThan:      // fall through
   2378     case IrOpcode::kJSLessThanOrEqual:  // fall through
   2379     case IrOpcode::kJSGreaterThanOrEqual:
   2380       return ReduceJSComparison(node);
   2381     case IrOpcode::kJSBitwiseOr:
   2382     case IrOpcode::kJSBitwiseXor:
   2383     case IrOpcode::kJSBitwiseAnd:
   2384       return ReduceInt32Binop(node);
   2385     case IrOpcode::kJSShiftLeft:
   2386     case IrOpcode::kJSShiftRight:
   2387       return ReduceUI32Shift(node, kSigned);
   2388     case IrOpcode::kJSShiftRightLogical:
   2389       return ReduceUI32Shift(node, kUnsigned);
   2390     case IrOpcode::kJSAdd:
   2391       return ReduceJSAdd(node);
   2392     case IrOpcode::kJSSubtract:
   2393     case IrOpcode::kJSMultiply:
   2394     case IrOpcode::kJSDivide:
   2395     case IrOpcode::kJSModulus:
   2396       return ReduceNumberBinop(node);
   2397     case IrOpcode::kJSOrdinaryHasInstance:
   2398       return ReduceJSOrdinaryHasInstance(node);
   2399     case IrOpcode::kJSToBoolean:
   2400       return ReduceJSToBoolean(node);
   2401     case IrOpcode::kJSToInteger:
   2402       return ReduceJSToInteger(node);
   2403     case IrOpcode::kJSToLength:
   2404       return ReduceJSToLength(node);
   2405     case IrOpcode::kJSToName:
   2406       return ReduceJSToName(node);
   2407     case IrOpcode::kJSToNumber:
   2408       return ReduceJSToNumber(node);
   2409     case IrOpcode::kJSToString:
   2410       return ReduceJSToString(node);
   2411     case IrOpcode::kJSToObject:
   2412       return ReduceJSToObject(node);
   2413     case IrOpcode::kJSTypeOf:
   2414       return ReduceJSTypeOf(node);
   2415     case IrOpcode::kJSLoadNamed:
   2416       return ReduceJSLoadNamed(node);
   2417     case IrOpcode::kJSLoadProperty:
   2418       return ReduceJSLoadProperty(node);
   2419     case IrOpcode::kJSStoreProperty:
   2420       return ReduceJSStoreProperty(node);
   2421     case IrOpcode::kJSLoadContext:
   2422       return ReduceJSLoadContext(node);
   2423     case IrOpcode::kJSStoreContext:
   2424       return ReduceJSStoreContext(node);
   2425     case IrOpcode::kJSLoadModule:
   2426       return ReduceJSLoadModule(node);
   2427     case IrOpcode::kJSStoreModule:
   2428       return ReduceJSStoreModule(node);
   2429     case IrOpcode::kJSConvertReceiver:
   2430       return ReduceJSConvertReceiver(node);
   2431     case IrOpcode::kJSConstruct:
   2432       return ReduceJSConstruct(node);
   2433     case IrOpcode::kJSCallForwardVarargs:
   2434       return ReduceJSCallForwardVarargs(node);
   2435     case IrOpcode::kJSCall:
   2436       return ReduceJSCall(node);
   2437     case IrOpcode::kJSForInNext:
   2438       return ReduceJSForInNext(node);
   2439     case IrOpcode::kJSLoadMessage:
   2440       return ReduceJSLoadMessage(node);
   2441     case IrOpcode::kJSStoreMessage:
   2442       return ReduceJSStoreMessage(node);
   2443     case IrOpcode::kJSGeneratorStore:
   2444       return ReduceJSGeneratorStore(node);
   2445     case IrOpcode::kJSGeneratorRestoreContinuation:
   2446       return ReduceJSGeneratorRestoreContinuation(node);
   2447     case IrOpcode::kJSGeneratorRestoreRegister:
   2448       return ReduceJSGeneratorRestoreRegister(node);
   2449     // TODO(mstarzinger): Simplified operations hiding in JS-level reducer not
   2450     // fooling anyone. Consider moving this into a separate reducer.
   2451     case IrOpcode::kSpeculativeNumberAdd:
   2452       return ReduceSpeculativeNumberAdd(node);
   2453     case IrOpcode::kSpeculativeNumberSubtract:
   2454     case IrOpcode::kSpeculativeNumberMultiply:
   2455     case IrOpcode::kSpeculativeNumberDivide:
   2456     case IrOpcode::kSpeculativeNumberModulus:
   2457       return ReduceSpeculativeNumberBinop(node);
   2458     default:
   2459       break;
   2460   }
   2461   return NoChange();
   2462 }
   2463 
   2464 
   2465 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
   2466 
   2467 
   2468 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
   2469 
   2470 
   2471 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); }
   2472 
   2473 
   2474 JSOperatorBuilder* JSTypedLowering::javascript() const {
   2475   return jsgraph()->javascript();
   2476 }
   2477 
   2478 
   2479 CommonOperatorBuilder* JSTypedLowering::common() const {
   2480   return jsgraph()->common();
   2481 }
   2482 
   2483 SimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
   2484   return jsgraph()->simplified();
   2485 }
   2486 
   2487 
   2488 CompilationDependencies* JSTypedLowering::dependencies() const {
   2489   return dependencies_;
   2490 }
   2491 
   2492 }  // namespace compiler
   2493 }  // namespace internal
   2494 }  // namespace v8
   2495