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