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