js-typed-lowering.cc revision f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3
1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler/js-typed-lowering.h"
6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/builtins/builtins-utils.h"
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/code-factory.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compilation-dependencies.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/access-builder.h"
11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/compiler/js-graph.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/linkage.h"
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/compiler/node-matchers.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/node-properties.h"
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/operator-properties.h"
16f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler/type-cache.h"
17f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler/types.h"
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class to simplify the process of reducing a single binop node with a
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// JSOperator. This class manages the rewriting of context, control, and effect
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// dependencies during lowering of a binop and contains numerous helper
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// functions for matching the types of inputs to an operation.
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass JSBinopReduction final {
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSBinopReduction(JSTypedLowering* lowering, Node* node)
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : lowering_(lowering), node_(node) {}
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool GetBinaryNumberOperationHint(NumberOperationHint* hint) {
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_NE(0, node_->op()->ControlOutputCount());
35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_EQ(1, node_->op()->EffectOutputCount());
36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      switch (BinaryOperationHintOf(node_->op())) {
38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case BinaryOperationHint::kSignedSmall:
39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          *hint = NumberOperationHint::kSignedSmall;
40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return true;
41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case BinaryOperationHint::kSigned32:
42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          *hint = NumberOperationHint::kSigned32;
43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return true;
44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case BinaryOperationHint::kNumberOrOddball:
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          *hint = NumberOperationHint::kNumberOrOddball;
46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return true;
47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case BinaryOperationHint::kAny:
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case BinaryOperationHint::kNone:
49f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        case BinaryOperationHint::kString:
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          break;
51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
5213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return false;
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_EQ(1, node_->op()->EffectOutputCount());
59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      switch (CompareOperationHintOf(node_->op())) {
60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case CompareOperationHint::kSignedSmall:
61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          *hint = NumberOperationHint::kSignedSmall;
62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return true;
63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case CompareOperationHint::kNumber:
64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          *hint = NumberOperationHint::kNumber;
65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return true;
66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case CompareOperationHint::kNumberOrOddball:
67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          *hint = NumberOperationHint::kNumberOrOddball;
68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return true;
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case CompareOperationHint::kAny:
70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        case CompareOperationHint::kNone:
71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          break;
72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
7313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return false;
7513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
7613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
77f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if a string addition will definitely result in creating a ConsString,
78f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // i.e. if the combined length of the resulting string exceeds the ConsString
79f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // minimum length.
80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  bool ShouldCreateConsString() {
81f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode());
82f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (BothInputsAre(Type::String()) ||
83f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) &&
84f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch         BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) {
85f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (right_type()->IsConstant() &&
86f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          right_type()->AsConstant()->Value()->IsString()) {
87f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Handle<String> right_string =
88f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            Handle<String>::cast(right_type()->AsConstant()->Value());
89f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        if (right_string->length() >= ConsString::kMinLength) return true;
90f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
91f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (left_type()->IsConstant() &&
92f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          left_type()->AsConstant()->Value()->IsString()) {
93f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Handle<String> left_string =
94f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            Handle<String>::cast(left_type()->AsConstant()->Value());
95f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        if (left_string->length() >= ConsString::kMinLength) {
96f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          // The invariant for ConsString requires the left hand side to be
97f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          // a sequential or external string if the right hand side is the
98f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          // empty string. Since we don't know anything about the right hand
99f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          // side here, we must ensure that the left hand side satisfy the
100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          // constraints independent of the right hand side.
101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          return left_string->IsSeqString() || left_string->IsExternalString();
102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        }
103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return false;
106f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ConvertInputsToNumber() {
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // To convert the inputs to numbers, we have to provide frame states
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // for lazy bailouts in the ToNumber conversions.
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We use a little hack here: we take the frame state before the binary
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // operation and use it to construct the frame states for the conversion
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // so that after the deoptimization, the binary operation IC gets
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // already converted values from full code. This way we are sure that we
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // will not re-do any of the side effects.
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* left_input = nullptr;
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* right_input = nullptr;
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bool left_is_primitive = left_type()->Is(Type::PlainPrimitive());
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bool right_is_primitive = right_type()->Is(Type::PlainPrimitive());
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bool handles_exception = NodeProperties::IsExceptionalCall(node_);
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!left_is_primitive && !right_is_primitive && handles_exception) {
124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ConvertBothInputsToNumber(&left_input, &right_input);
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      left_input = left_is_primitive
12713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                       ? ConvertPlainPrimitiveToNumber(left())
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       : ConvertSingleInputToNumber(
129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             left(), CreateFrameStateForLeftInput());
130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      right_input =
131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          right_is_primitive
132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              ? ConvertPlainPrimitiveToNumber(right())
133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              : ConvertSingleInputToNumber(
134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    right(), CreateFrameStateForRightInput(left_input));
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node_->ReplaceInput(0, left_input);
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node_->ReplaceInput(1, right_input);
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ConvertInputsToUI32(Signedness left_signedness,
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           Signedness right_signedness) {
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SwapInputs() {
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Node* l = left();
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Node* r = right();
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    node_->ReplaceInput(0, r);
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    node_->ReplaceInput(1, l);
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Remove all effect and control inputs and outputs to this node and change
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to the pure operator {op}, possibly inserting a boolean inversion.
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Reduction ChangeToPureOperator(const Operator* op, bool invert = false,
157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                 Type* type = Type::Any()) {
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK_EQ(0, op->EffectInputCount());
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK_EQ(0, op->ControlInputCount());
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK_EQ(2, op->ValueInputCount());
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Remove the effects from the node, and update its effect/control usages.
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (node_->op()->EffectInputCount() > 0) {
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      lowering_->RelaxEffectsAndControls(node_);
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Remove the inputs corresponding to context, effect, and control.
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NodeProperties::RemoveNonValueInputs(node_);
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Finally, update the operator to the new one.
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(node_, op);
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // TODO(jarin): Replace the explicit typing hack with a call to some method
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // that encapsulates changing the operator and re-typing.
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Type* node_type = NodeProperties::GetType(node_);
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (invert) {
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Insert an boolean not to invert the value.
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      node_->ReplaceUses(value);
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Note: ReplaceUses() smashes all uses, so smash it back here.
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      value->ReplaceInput(0, node_);
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return lowering_->Replace(value);
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return lowering_->Changed(node_);
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Reduction ChangeToSpeculativeOperator(const Operator* op, bool invert,
189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                        Type* upper_bound) {
19013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(1, op->EffectInputCount());
19113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(1, op->EffectOutputCount());
19213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
19313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(1, op->ControlInputCount());
19413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(0, op->ControlOutputCount());
19513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
19613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(2, op->ValueInputCount());
19713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
19813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(1, node_->op()->EffectInputCount());
19913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(1, node_->op()->EffectOutputCount());
20013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(1, node_->op()->ControlInputCount());
20113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(2, node_->op()->ValueInputCount());
20213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
20313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Reconnect the control output to bypass the IfSuccess node and
20413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // possibly disconnect from the IfException node.
20513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    for (Edge edge : node_->use_edges()) {
20613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Node* const user = edge.from();
20713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      DCHECK(!user->IsDead());
20813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (NodeProperties::IsControlEdge(edge)) {
20913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        if (user->opcode() == IrOpcode::kIfSuccess) {
21013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          user->ReplaceUses(NodeProperties::GetControlInput(node_));
21113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          user->Kill();
21213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        } else {
21313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          DCHECK_EQ(user->opcode(), IrOpcode::kIfException);
21413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          edge.UpdateTo(jsgraph()->Dead());
21513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        }
21613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
21713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
21813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Remove the frame state and the context.
220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (OperatorProperties::HasFrameStateInput(node_->op())) {
221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
22313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
22413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
22513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    NodeProperties::ChangeOp(node_, op);
22613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
22713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Update the type to number.
22813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Type* node_type = NodeProperties::GetType(node_);
22913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    NodeProperties::SetType(node_,
23013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            Type::Intersect(node_type, upper_bound, zone()));
23113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (invert) {
233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Insert an boolean not to invert the value.
234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node_->ReplaceUses(value);
236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Note: ReplaceUses() smashes all uses, so smash it back here.
237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      value->ReplaceInput(0, node_);
238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return lowering_->Replace(value);
239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
24013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return lowering_->Changed(node_);
24113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
24213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Reduction ChangeToPureOperator(const Operator* op, Type* type) {
244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return ChangeToPureOperator(op, false, type);
245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Reduction ChangeToSpeculativeOperator(const Operator* op, Type* type) {
248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return ChangeToSpeculativeOperator(op, false, type);
249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const Operator* NumberOp() {
252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    switch (node_->opcode()) {
253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSAdd:
254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberAdd();
255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSSubtract:
256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberSubtract();
257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSMultiply:
258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberMultiply();
259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSDivide:
260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberDivide();
261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSModulus:
262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberModulus();
263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSBitwiseAnd:
264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberBitwiseAnd();
265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSBitwiseOr:
266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberBitwiseOr();
267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSBitwiseXor:
268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberBitwiseXor();
269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSShiftLeft:
270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberShiftLeft();
271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSShiftRight:
272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberShiftRight();
273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSShiftRightLogical:
274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->NumberShiftRightLogical();
275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      default:
276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        break;
277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    UNREACHABLE();
279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return nullptr;
280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const Operator* SpeculativeNumberOp(NumberOperationHint hint) {
283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    switch (node_->opcode()) {
284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSAdd:
285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberAdd(hint);
286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSSubtract:
287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberSubtract(hint);
288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSMultiply:
289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberMultiply(hint);
290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSDivide:
291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberDivide(hint);
292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSModulus:
293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberModulus(hint);
294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSBitwiseAnd:
295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberBitwiseAnd(hint);
296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSBitwiseOr:
297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberBitwiseOr(hint);
298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSBitwiseXor:
299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberBitwiseXor(hint);
300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSShiftLeft:
301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberShiftLeft(hint);
302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSShiftRight:
303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberShiftRight(hint);
304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case IrOpcode::kJSShiftRightLogical:
305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return simplified()->SpeculativeNumberShiftRightLogical(hint);
306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      default:
307f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        break;
308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
309f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    UNREACHABLE();
310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return nullptr;
311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
312f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool LeftInputIs(Type* t) { return left_type()->Is(t); }
314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool RightInputIs(Type* t) { return right_type()->Is(t); }
316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); }
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool OneInputCannotBe(Type* t) {
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return !left_type()->Maybe(t) || !right_type()->Maybe(t);
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool NeitherInputCanBe(Type* t) {
326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return !left_type()->Maybe(t) && !right_type()->Maybe(t);
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* effect() { return NodeProperties::GetEffectInput(node_); }
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* control() { return NodeProperties::GetControlInput(node_); }
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* context() { return NodeProperties::GetContextInput(node_); }
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* left() { return NodeProperties::GetValueInput(node_, 0); }
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* right() { return NodeProperties::GetValueInput(node_, 1); }
334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* left_type() { return NodeProperties::GetType(node_->InputAt(0)); }
335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* right_type() { return NodeProperties::GetType(node_->InputAt(1)); }
336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Type* type() { return NodeProperties::GetType(node_); }
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Graph* graph() const { return lowering_->graph(); }
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSGraph* jsgraph() { return lowering_->jsgraph(); }
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSOperatorBuilder* javascript() { return lowering_->javascript(); }
342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CommonOperatorBuilder* common() { return jsgraph()->common(); }
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Zone* zone() const { return graph()->zone(); }
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSTypedLowering* lowering_;  // The containing lowering instance.
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* node_;                 // The original node.
348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* CreateFrameStateForLeftInput() {
350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Deoptimization is disabled => return dummy frame state instead.
351f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* dummy_state = NodeProperties::GetFrameStateInput(node_);
352f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(OpParameter<FrameStateInfo>(dummy_state).bailout_id().IsNone());
353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return dummy_state;
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* CreateFrameStateForRightInput(Node* converted_left) {
357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Deoptimization is disabled => return dummy frame state instead.
358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* dummy_state = NodeProperties::GetFrameStateInput(node_);
359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(OpParameter<FrameStateInfo>(dummy_state).bailout_id().IsNone());
360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return dummy_state;
361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
36313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* ConvertPlainPrimitiveToNumber(Node* node) {
364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Avoid inserting too many eager ToNumber() operations.
366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (reduction.Changed()) return reduction.replacement();
36813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (NodeProperties::GetType(node)->Is(Type::Number())) {
369bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return node;
370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
37113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* const n = graph()->NewNode(javascript()->ToNumber(), node, context(),
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     frame_state, effect(), control());
378bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* const if_success = graph()->NewNode(common()->IfSuccess(), n);
379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    NodeProperties::ReplaceControlInput(node_, if_success);
380bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    NodeProperties::ReplaceUses(node_, node_, node_, node_, n);
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    update_effect(n);
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return n;
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ConvertBothInputsToNumber(Node** left_result, Node** right_result) {
386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* projections[2];
387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Find {IfSuccess} and {IfException} continuations of the operation.
389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::CollectControlProjections(node_, projections, 2);
390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* if_exception = projections[1];
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* if_success = projections[0];
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Insert two ToNumber() operations that both potentially throw.
394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* left_state = CreateFrameStateForLeftInput();
395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* left_conv =
396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        graph()->NewNode(javascript()->ToNumber(), left(), context(),
397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         left_state, effect(), control());
398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* left_success = graph()->NewNode(common()->IfSuccess(), left_conv);
399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* right_state = CreateFrameStateForRightInput(left_conv);
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* right_conv =
401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        graph()->NewNode(javascript()->ToNumber(), right(), context(),
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         right_state, left_conv, left_success);
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* left_exception =
404f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        graph()->NewNode(common()->IfException(), left_conv, left_conv);
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* right_exception =
406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        graph()->NewNode(common()->IfException(), right_conv, right_conv);
407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ReplaceControlInput(if_success, right_conv);
408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    update_effect(right_conv);
409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Wire conversions to existing {IfException} continuation.
411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* exception_merge = if_exception;
412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* exception_value =
413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         left_exception, right_exception, exception_merge);
415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* exception_effect =
416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        graph()->NewNode(common()->EffectPhi(2), left_exception,
417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         right_exception, exception_merge);
418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (Edge edge : exception_merge->use_edges()) {
419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (NodeProperties::IsEffectEdge(edge)) edge.UpdateTo(exception_effect);
420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (NodeProperties::IsValueEdge(edge)) edge.UpdateTo(exception_value);
421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::RemoveType(exception_merge);
423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    exception_merge->ReplaceInput(0, left_exception);
424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    exception_merge->ReplaceInput(1, right_exception);
425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(exception_merge, common()->Merge(2));
426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *left_result = left_conv;
428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *right_result = right_conv;
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* ConvertToUI32(Node* node, Signedness signedness) {
432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Avoid introducing too many eager NumberToXXnt32() operations.
433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Type* type = NodeProperties::GetType(node);
434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (signedness == kSigned) {
435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (!type->Is(Type::Signed32())) {
436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        node = graph()->NewNode(simplified()->NumberToInt32(), node);
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK_EQ(kUnsigned, signedness);
440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (!type->Is(Type::Unsigned32())) {
441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        node = graph()->NewNode(simplified()->NumberToUint32(), node);
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return node;
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void update_effect(Node* effect) {
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NodeProperties::ReplaceEffectInput(node_, effect);
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// TODO(turbofan): js-typed-lowering improvements possible
454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - immediately put in type bounds for all new nodes
455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - relax effects from generic but not-side-effecting operations
456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochJSTypedLowering::JSTypedLowering(Editor* editor,
459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 CompilationDependencies* dependencies,
460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Flags flags, JSGraph* jsgraph, Zone* zone)
461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    : AdvancedReducer(editor),
462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      dependencies_(dependencies),
463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      flags_(flags),
464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      jsgraph_(jsgraph),
465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      the_hole_type_(
466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Type::Constant(factory()->the_hole_value(), graph()->zone())),
467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      type_cache_(TypeCache::Get()) {
468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    double min = kMinInt / (1 << k);
470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    double max = kMaxInt / (1 << k);
471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::ReduceJSAdd(Node* node) {
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSBinopReduction r(this, node);
477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NumberOperationHint hint;
478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.GetBinaryNumberOperationHint(&hint)) {
479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (hint == NumberOperationHint::kNumberOrOddball &&
480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        r.BothInputsAre(Type::PlainPrimitive()) &&
481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        r.NeitherInputCanBe(Type::StringOrReceiver())) {
482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      r.ConvertInputsToNumber();
484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
48613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return r.ChangeToSpeculativeOperator(
487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        simplified()->SpeculativeNumberAdd(hint), Type::Number());
48813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
48913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (r.BothInputsAre(Type::Number())) {
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // JSAdd(x:number, y:number) => NumberAdd(x, y)
491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r.ConvertInputsToNumber();
49213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
494f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if ((r.BothInputsAre(Type::PlainPrimitive()) ||
495f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch       !(flags() & kDeoptimizationEnabled)) &&
496f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      r.NeitherInputCanBe(Type::StringOrReceiver())) {
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
498f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r.ConvertInputsToNumber();
499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (r.OneInputIs(Type::String())) {
502f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (r.ShouldCreateConsString()) {
503f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return ReduceCreateConsString(node);
504f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
505bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    StringAddFlags flags = STRING_ADD_CHECK_NONE;
506bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (!r.LeftInputIs(Type::String())) {
507bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      flags = STRING_ADD_CONVERT_LEFT;
508bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else if (!r.RightInputIs(Type::String())) {
509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      flags = STRING_ADD_CONVERT_RIGHT;
510bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
511bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // JSAdd(x:string, y) => CallStub[StringAdd](x, y)
512bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // JSAdd(x, y:string) => CallStub[StringAdd](x, y)
513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Callable const callable =
514bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isolate(), graph()->zone(), callable.descriptor(), 0,
517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        CallDescriptor::kNeedsFrameState, node->op()->properties());
518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->InsertInput(graph()->zone(), 0,
520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      jsgraph()->HeapConstant(callable.code()));
521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(node, common()->Call(desc));
522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return NoChange();
525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochReduction JSTypedLowering::ReduceNumberBinop(Node* node) {
528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JSBinopReduction r(this, node);
529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NumberOperationHint hint;
530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.GetBinaryNumberOperationHint(&hint)) {
531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (hint == NumberOperationHint::kNumberOrOddball &&
532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        r.BothInputsAre(Type::PlainPrimitive())) {
533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      r.ConvertInputsToNumber();
534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToSpeculativeOperator(r.SpeculativeNumberOp(hint),
537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                         Type::Number());
538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.BothInputsAre(Type::PlainPrimitive()) ||
540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      !(flags() & kDeoptimizationEnabled)) {
541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r.ConvertInputsToNumber();
542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
54313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return NoChange();
545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochReduction JSTypedLowering::ReduceInt32Binop(Node* node) {
54813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  JSBinopReduction r(this, node);
549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NumberOperationHint hint;
550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.GetBinaryNumberOperationHint(&hint)) {
551f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToSpeculativeOperator(r.SpeculativeNumberOp(hint),
552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                         Type::Signed32());
55313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
554f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.BothInputsAre(Type::PlainPrimitive()) ||
555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      !(flags() & kDeoptimizationEnabled)) {
556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r.ConvertInputsToNumber();
557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r.ConvertInputsToUI32(kSigned, kSigned);
558f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(r.NumberOp(), Type::Signed32());
55913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return NoChange();
56113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
56213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochReduction JSTypedLowering::ReduceUI32Shift(Node* node, Signedness signedness) {
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSBinopReduction r(this, node);
565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NumberOperationHint hint;
566f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.GetBinaryNumberOperationHint(&hint)) {
56713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return r.ChangeToSpeculativeOperator(
568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        r.SpeculativeNumberOp(hint),
569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        signedness == kUnsigned ? Type::Unsigned32() : Type::Signed32());
570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.BothInputsAre(Type::PlainPrimitive()) ||
572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      !(flags() & kDeoptimizationEnabled)) {
573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r.ConvertInputsToNumber();
574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r.ConvertInputsToUI32(signedness, kUnsigned);
575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(r.NumberOp(), signedness == kUnsigned
576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                                    ? Type::Unsigned32()
577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                                    : Type::Signed32());
578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return NoChange();
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
582f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochReduction JSTypedLowering::ReduceCreateConsString(Node* node) {
583f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* first = NodeProperties::GetValueInput(node, 0);
584f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* second = NodeProperties::GetValueInput(node, 1);
585f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* context = NodeProperties::GetContextInput(node);
586f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* frame_state = NodeProperties::GetFrameStateInput(node);
587f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
588f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
589f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
590f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Make sure {first} is actually a String.
591f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Type* first_type = NodeProperties::GetType(first);
592f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (!first_type->Is(Type::String())) {
593f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    first = effect =
594f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        graph()->NewNode(simplified()->CheckString(), first, effect, control);
595f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    first_type = NodeProperties::GetType(first);
596f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
597f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
598f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Make sure {second} is actually a String.
599f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Type* second_type = NodeProperties::GetType(second);
600f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (!second_type->Is(Type::String())) {
601f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    second = effect =
602f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        graph()->NewNode(simplified()->CheckString(), second, effect, control);
603f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    second_type = NodeProperties::GetType(second);
604f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
605f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
606f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Determine the {first} length.
607f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* first_length =
608f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      first_type->IsConstant()
609f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          ? jsgraph()->Constant(
610f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Handle<String>::cast(first_type->AsConstant()->Value())
611f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                    ->length())
612f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          : effect = graph()->NewNode(
613f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                simplified()->LoadField(AccessBuilder::ForStringLength()),
614f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                first, effect, control);
615f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
616f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Determine the {second} length.
617f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* second_length =
618f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      second_type->IsConstant()
619f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          ? jsgraph()->Constant(
620f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Handle<String>::cast(second_type->AsConstant()->Value())
621f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                    ->length())
622f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          : effect = graph()->NewNode(
623f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                simplified()->LoadField(AccessBuilder::ForStringLength()),
624f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                second, effect, control);
625f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
626f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Compute the resulting length.
627f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* length =
628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      graph()->NewNode(simplified()->NumberAdd(), first_length, second_length);
629f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
630f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if we would overflow the allowed maximum string length.
631f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* check = graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
632f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                 jsgraph()->Constant(String::kMaxLength));
633f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* branch =
634f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
635f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
636f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* efalse = effect;
637f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
638f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Throw a RangeError in case of overflow.
639f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Node* vfalse = efalse = graph()->NewNode(
640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        javascript()->CallRuntime(Runtime::kThrowInvalidStringLength), context,
641f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        frame_state, efalse, if_false);
642f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if_false = graph()->NewNode(common()->IfSuccess(), vfalse);
643f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if_false = graph()->NewNode(common()->Throw(), vfalse, efalse, if_false);
644f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // TODO(bmeurer): This should be on the AdvancedReducer somehow.
645f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    NodeProperties::MergeControlToEnd(graph(), common(), if_false);
646f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Revisit(graph()->end());
647f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
648f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Update potential {IfException} uses of {node} to point to the
649f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // %ThrowInvalidStringLength runtime call node instead.
650f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    for (Edge edge : node->use_edges()) {
651f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (edge.from()->opcode() == IrOpcode::kIfException) {
652f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        DCHECK(NodeProperties::IsControlEdge(edge) ||
653f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch               NodeProperties::IsEffectEdge(edge));
654f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        edge.UpdateTo(vfalse);
655f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Revisit(edge.from());
656f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
657f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
658f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
659f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  control = graph()->NewNode(common()->IfTrue(), branch);
660f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
661f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Figure out the map for the resulting ConsString.
662f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // TODO(turbofan): We currently just use the cons_string_map here for
663f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // the sake of simplicity; we could also try to be smarter here and
664f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // use the one_byte_cons_string_map instead when the resulting ConsString
665f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // contains only one byte characters.
666f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* value_map = jsgraph()->HeapConstant(factory()->cons_string_map());
667f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
668f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Allocate the resulting ConsString.
669f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  effect = graph()->NewNode(
670f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      common()->BeginRegion(RegionObservability::kNotObservable), effect);
671f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* value = effect =
672f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      graph()->NewNode(simplified()->Allocate(NOT_TENURED),
673f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       jsgraph()->Constant(ConsString::kSize), effect, control);
674f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  NodeProperties::SetType(value, Type::OtherString());
675f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
676f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                            value, value_map, effect, control);
677f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  effect = graph()->NewNode(
678f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      simplified()->StoreField(AccessBuilder::ForNameHashField()), value,
679f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      jsgraph()->Uint32Constant(Name::kEmptyHashField), effect, control);
680f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  effect = graph()->NewNode(
681f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      simplified()->StoreField(AccessBuilder::ForStringLength()), value, length,
682f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      effect, control);
683f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  effect = graph()->NewNode(
684f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      simplified()->StoreField(AccessBuilder::ForConsStringFirst()), value,
685f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      first, effect, control);
686f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  effect = graph()->NewNode(
687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      simplified()->StoreField(AccessBuilder::ForConsStringSecond()), value,
688f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      second, effect, control);
689f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
690f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Morph the {node} into a {FinishRegion}.
691f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  ReplaceWithValue(node, node, node, control);
692f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->ReplaceInput(0, value);
693f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->ReplaceInput(1, effect);
694f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->TrimInputCount(2);
695f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  NodeProperties::ChangeOp(node, common()->FinishRegion());
696f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return Changed(node);
697f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
698f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::ReduceJSComparison(Node* node) {
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSBinopReduction r(this, node);
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.BothInputsAre(Type::String())) {
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If both inputs are definitely strings, perform a string comparison.
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const Operator* stringOp;
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (node->opcode()) {
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kJSLessThan:
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stringOp = simplified()->StringLessThan();
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kJSGreaterThan:
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stringOp = simplified()->StringLessThan();
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        r.SwapInputs();  // a > b => b < a
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kJSLessThanOrEqual:
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stringOp = simplified()->StringLessThanOrEqual();
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kJSGreaterThanOrEqual:
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stringOp = simplified()->StringLessThanOrEqual();
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        r.SwapInputs();  // a >= b => b <= a
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return NoChange();
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
722bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    r.ChangeToPureOperator(stringOp);
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
72513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
726f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NumberOperationHint hint;
727f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const Operator* less_than;
728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const Operator* less_than_or_equal;
729f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.BothInputsAre(Type::Signed32()) ||
730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      r.BothInputsAre(Type::Unsigned32())) {
731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    less_than = simplified()->NumberLessThan();
732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    less_than_or_equal = simplified()->NumberLessThanOrEqual();
733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (r.GetCompareNumberOperationHint(&hint)) {
734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    less_than = simplified()->SpeculativeNumberLessThan(hint);
735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (r.OneInputCannotBe(Type::StringOrReceiver()) &&
737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch             (r.BothInputsAre(Type::PlainPrimitive()) ||
738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              !(flags() & kDeoptimizationEnabled))) {
739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r.ConvertInputsToNumber();
740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    less_than = simplified()->NumberLessThan();
741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    less_than_or_equal = simplified()->NumberLessThanOrEqual();
742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return NoChange();
744f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
745f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const Operator* comparison;
746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (node->opcode()) {
747f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kJSLessThan:
748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      comparison = less_than;
749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
750f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kJSGreaterThan:
751f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      comparison = less_than;
752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      r.SwapInputs();  // a > b => b < a
753f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kJSLessThanOrEqual:
755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      comparison = less_than_or_equal;
756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kJSGreaterThanOrEqual:
758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      comparison = less_than_or_equal;
759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      r.SwapInputs();  // a >= b => b <= a
760f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    default:
762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return NoChange();
763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
764f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (comparison->EffectInputCount() > 0) {
765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
767f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(comparison);
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
771bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochReduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
772bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  HeapObjectBinopMatcher m(node);
773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (m.left().IsJSTypeOf() && m.right().HasValue() &&
774bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      m.right().Value()->IsString()) {
775bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* replacement;
776bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* input = m.left().InputAt(0);
777bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Handle<String> value = Handle<String>::cast(m.right().Value());
778bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (String::Equals(value, factory()->boolean_string())) {
779f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      replacement =
780f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           graph()->NewNode(simplified()->ReferenceEqual(),
782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                            input, jsgraph()->TrueConstant()),
783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           jsgraph()->TrueConstant(),
784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           graph()->NewNode(simplified()->ReferenceEqual(),
785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                            input, jsgraph()->FalseConstant()));
786bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else if (String::Equals(value, factory()->function_string())) {
787bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      replacement = graph()->NewNode(simplified()->ObjectIsCallable(), input);
788bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else if (String::Equals(value, factory()->number_string())) {
789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      replacement = graph()->NewNode(simplified()->ObjectIsNumber(), input);
790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else if (String::Equals(value, factory()->string_string())) {
791bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      replacement = graph()->NewNode(simplified()->ObjectIsString(), input);
792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else if (String::Equals(value, factory()->undefined_string())) {
793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      replacement = graph()->NewNode(
794bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          common()->Select(MachineRepresentation::kTagged),
795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          graph()->NewNode(simplified()->ReferenceEqual(), input,
796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           jsgraph()->NullConstant()),
797bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          jsgraph()->FalseConstant(),
798bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          graph()->NewNode(simplified()->ObjectIsUndetectable(), input));
799bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
800bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return NoChange();
801bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
802bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (invert) {
803bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      replacement = graph()->NewNode(simplified()->BooleanNot(), replacement);
804bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
805f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ReplaceWithValue(node, replacement);
806bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return Replace(replacement);
807bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
808bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return NoChange();
809bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
812bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
813f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (reduction.Changed()) return reduction;
814bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSBinopReduction r(this, node);
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.BothInputsAre(Type::String())) {
818bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (r.BothInputsAre(Type::Boolean())) {
821f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.BothInputsAre(Type::Receiver())) {
824f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
8263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (r.OneInputIs(Type::Undetectable())) {
8273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    RelaxEffectsAndControls(node);
8283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    node->RemoveInput(r.LeftInputIs(Type::Undetectable()) ? 0 : 1);
8293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    node->TrimInputCount(1);
8303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    NodeProperties::ChangeOp(node, simplified()->ObjectIsUndetectable());
831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (invert) {
832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Insert an boolean not to invert the value.
833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* value = graph()->NewNode(simplified()->BooleanNot(), node);
834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node->ReplaceUses(value);
835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Note: ReplaceUses() smashes all uses, so smash it back here.
836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      value->ReplaceInput(0, node);
837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Replace(value);
838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
841f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
842f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NumberOperationHint hint;
843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.BothInputsAre(Type::Signed32()) ||
844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      r.BothInputsAre(Type::Unsigned32())) {
845f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
846f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (r.GetCompareNumberOperationHint(&hint)) {
847f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToSpeculativeOperator(
848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean());
849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (r.BothInputsAre(Type::Number())) {
850f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
851f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoChange();
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSBinopReduction r(this, node);
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.left() == r.right()) {
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // x === x is always true if x != NaN
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!r.left_type()->Maybe(Type::NaN())) {
860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* replacement = jsgraph()->BooleanConstant(!invert);
861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ReplaceWithValue(node, replacement);
862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Replace(replacement);
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
86513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (r.OneInputCannotBe(Type::NumberOrSimdOrString())) {
86613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // For values with canonical representation (i.e. neither String, nor
86713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Simd128Value nor Number) an empty type intersection means the values
86813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // cannot be strictly equal.
869958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!r.left_type()->Maybe(r.right_type())) {
870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* replacement = jsgraph()->BooleanConstant(invert);
871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ReplaceWithValue(node, replacement);
872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Replace(replacement);
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
875f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
876bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
877f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (reduction.Changed()) return reduction;
878f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (r.OneInputIs(the_hole_type_)) {
880f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.OneInputIs(Type::Undefined())) {
883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.OneInputIs(Type::Null())) {
886f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.OneInputIs(Type::Boolean())) {
889f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.OneInputIs(Type::Object())) {
892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.OneInputIs(Type::Receiver())) {
895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (r.BothInputsAre(Type::Unique())) {
898f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.BothInputsAre(Type::String())) {
901bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
903f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
904f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NumberOperationHint hint;
905f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (r.BothInputsAre(Type::Signed32()) ||
906f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      r.BothInputsAre(Type::Unsigned32())) {
907f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
908f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (r.GetCompareNumberOperationHint(&hint)) {
909f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return r.ChangeToSpeculativeOperator(
910f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean());
911f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (r.BothInputsAre(Type::Number())) {
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoChange();
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
917958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierReduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* const input = node->InputAt(0);
919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* const input_type = NodeProperties::GetType(input);
920958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (input_type->Is(Type::Boolean())) {
921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // JSToBoolean(x:boolean) => x
922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return Replace(input);
923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (input_type->Is(Type::OrderedNumber())) {
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0))
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RelaxEffectsAndControls(node);
926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->ReplaceInput(0, graph()->NewNode(simplified()->NumberEqual(), input,
927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           jsgraph()->ZeroConstant()));
928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->TrimInputCount(1);
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(node, simplified()->BooleanNot());
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
931f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (input_type->Is(Type::Number())) {
932f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // JSToBoolean(x:number) => NumberToBoolean(x)
933f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    RelaxEffectsAndControls(node);
934f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    node->TrimInputCount(1);
935f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    NodeProperties::ChangeOp(node, simplified()->NumberToBoolean());
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
9413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochReduction JSTypedLowering::ReduceJSToInteger(Node* node) {
9423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* const input = NodeProperties::GetValueInput(node, 0);
9433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Type* const input_type = NodeProperties::GetType(input);
9443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
9453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // JSToInteger(x:integer) => x
9463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ReplaceWithValue(node, input);
9473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return Replace(input);
9483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
9493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return NoChange();
9503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
9513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
9523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochReduction JSTypedLowering::ReduceJSToLength(Node* node) {
9533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* input = NodeProperties::GetValueInput(node, 0);
9543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Type* input_type = NodeProperties::GetType(input);
9553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
9563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (input_type->Max() <= 0.0) {
9573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      input = jsgraph()->ZeroConstant();
9583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else if (input_type->Min() >= kMaxSafeInteger) {
9593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      input = jsgraph()->Constant(kMaxSafeInteger);
9603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
9613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (input_type->Min() <= 0.0) {
962f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        input = graph()->NewNode(simplified()->NumberMax(),
963f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                 jsgraph()->ZeroConstant(), input);
9643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
9653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (input_type->Max() > kMaxSafeInteger) {
966f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        input = graph()->NewNode(simplified()->NumberMin(),
967f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                 jsgraph()->Constant(kMaxSafeInteger), input);
9683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
9693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
9703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ReplaceWithValue(node, input);
9713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return Replace(input);
9723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
9733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return NoChange();
9743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Try constant-folding of JSToNumber with constant inputs.
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* input_type = NodeProperties::GetType(input);
979109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (input_type->IsConstant()) {
980109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Handle<Object> input_value = input_type->AsConstant()->Value();
981109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (input_value->IsString()) {
982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return Replace(jsgraph()->Constant(
983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          String::ToNumber(Handle<String>::cast(input_value))));
984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (input_value->IsOddball()) {
985109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return Replace(jsgraph()->Constant(
986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          Oddball::ToNumber(Handle<Oddball>::cast(input_value))));
987109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
988109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input_type->Is(Type::Number())) {
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // JSToNumber(x:number) => x
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Changed(input);
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input_type->Is(Type::Undefined())) {
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // JSToNumber(undefined) => #NaN
995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return Replace(jsgraph()->NaNConstant());
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input_type->Is(Type::Null())) {
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // JSToNumber(null) => #0
999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return Replace(jsgraph()->ZeroConstant());
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoChange();
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierReduction JSTypedLowering::ReduceJSToNumber(Node* node) {
1005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Try to reduce the input first.
1006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const input = node->InputAt(0);
1007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Reduction reduction = ReduceJSToNumberInput(input);
1008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (reduction.Changed()) {
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReplaceWithValue(node, reduction.replacement());
1010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return reduction;
1011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* const input_type = NodeProperties::GetType(input);
1013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (input_type->Is(Type::PlainPrimitive())) {
101413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    RelaxEffectsAndControls(node);
101513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    node->TrimInputCount(1);
101613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
101713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return Changed(node);
1018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return NoChange();
1020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input->opcode() == IrOpcode::kJSToString) {
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Recursively try to reduce the input first.
1025958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Reduction result = ReduceJSToString(input);
1026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (result.Changed()) return result;
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Changed(input);  // JSToString(JSToString(x)) => JSToString(x)
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* input_type = NodeProperties::GetType(input);
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input_type->Is(Type::String())) {
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Changed(input);  // JSToString(x:string) => x
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (input_type->Is(Type::Boolean())) {
1034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Replace(graph()->NewNode(
1035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        common()->Select(MachineRepresentation::kTagged), input,
1036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        jsgraph()->HeapConstant(factory()->true_string()),
1037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        jsgraph()->HeapConstant(factory()->false_string())));
1038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input_type->Is(Type::Undefined())) {
1040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input_type->Is(Type::Null())) {
1043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return Replace(jsgraph()->HeapConstant(factory()->null_string()));
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(turbofan): js-typed-lowering of ToString(x:number)
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoChange();
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1049958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierReduction JSTypedLowering::ReduceJSToString(Node* node) {
1050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Try to reduce the input first.
1051958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const input = node->InputAt(0);
1052958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Reduction reduction = ReduceJSToStringInput(input);
1053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (reduction.Changed()) {
1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReplaceWithValue(node, reduction.replacement());
1055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return reduction;
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoChange();
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSTypedLowering::ReduceJSToObject(Node* node) {
1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* receiver = NodeProperties::GetValueInput(node, 0);
1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* receiver_type = NodeProperties::GetType(receiver);
1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* context = NodeProperties::GetContextInput(node);
1065f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* frame_state = NodeProperties::GetFrameStateInput(node);
1066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
1068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (receiver_type->Is(Type::Receiver())) {
1069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ReplaceWithValue(node, receiver, effect, control);
1070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Replace(receiver);
1071f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks.
1074f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (receiver_type->Maybe(Type::NullOrUndefined()) &&
1075f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::IsExceptionalCall(node)) {
1076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // ToObject throws for null or undefined inputs.
1077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return NoChange();
1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check whether {receiver} is a spec object.
1081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
1082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* branch =
1083f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* etrue = effect;
1087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rtrue = receiver;
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1090f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* efalse = effect;
1091f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rfalse;
1092f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
1093f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Convert {receiver} using the ToObjectStub.
1094f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Callable callable = CodeFactory::ToObject(isolate());
1095f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
1096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate(), graph()->zone(), callable.descriptor(), 0,
1097f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        CallDescriptor::kNeedsFrameState, node->op()->properties());
1098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    rfalse = efalse = graph()->NewNode(
1099f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
1100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        receiver, context, frame_state, efalse, if_false);
1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if_false = graph()->NewNode(common()->IfSuccess(), rfalse);
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Morph the {node} into an appropriate Phi.
1108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ReplaceWithValue(node, node, effect, control);
1109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->ReplaceInput(0, rtrue);
1110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->ReplaceInput(1, rfalse);
1111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->ReplaceInput(2, control);
1112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->TrimInputCount(3);
1113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NodeProperties::ChangeOp(node,
1114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           common()->Phi(MachineRepresentation::kTagged, 2));
1115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return Changed(node);
1116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* receiver = NodeProperties::GetValueInput(node, 0);
1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* receiver_type = NodeProperties::GetType(receiver);
1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
1124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Name> name = NamedAccessOf(node->op()).name();
1125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Optimize "length" property of strings.
1126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (name.is_identical_to(factory()->length_string()) &&
1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      receiver_type->Is(Type::String())) {
1128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* value = effect = graph()->NewNode(
1129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
1130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        effect, control);
1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReplaceWithValue(node, value, effect);
1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Replace(value);
1133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
1135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* key = NodeProperties::GetValueInput(node, 1);
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* base = NodeProperties::GetValueInput(node, 0);
1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* key_type = NodeProperties::GetType(key);
1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HeapObjectMatcher mbase(base);
1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<JSTypedArray> const array =
1144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<JSTypedArray>::cast(mbase.Value());
1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!array->GetBuffer()->was_neutered()) {
1146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      array->GetBuffer()->set_is_neuterable(false);
1147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BufferAccess const access(array->type());
1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      size_t const k =
1149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ElementSizeLog2Of(access.machine_type().representation());
1150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      double const byte_length = array->byte_length()->Number();
1151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CHECK_LT(k, arraysize(shifted_int32_ranges_));
1152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
1153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // JSLoadProperty(typed-array, int32)
1154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<FixedTypedArrayBase> elements =
1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
1157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* length = jsgraph()->Constant(byte_length);
1158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* effect = NodeProperties::GetEffectInput(node);
1159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* control = NodeProperties::GetControlInput(node);
1160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Check if we can avoid the bounds check.
1161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
1162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Node* load = graph()->NewNode(
1163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              simplified()->LoadElement(
1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  AccessBuilder::ForTypedArrayElement(array->type(), true)),
1165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              buffer, key, effect, control);
1166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ReplaceWithValue(node, load, load);
1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return Replace(load);
1168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Compute byte offset.
1170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Node* offset =
1171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            (k == 0) ? key : graph()->NewNode(
1172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                 simplified()->NumberShiftLeft(), key,
1173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                 jsgraph()->Constant(static_cast<double>(k)));
1174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer,
1175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      offset, length, effect, control);
1176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ReplaceWithValue(node, load, load);
1177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return Replace(load);
1178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoChange();
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* key = NodeProperties::GetValueInput(node, 1);
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* base = NodeProperties::GetValueInput(node, 0);
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* value = NodeProperties::GetValueInput(node, 2);
1188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* key_type = NodeProperties::GetType(key);
1189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* value_type = NodeProperties::GetType(value);
1190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HeapObjectMatcher mbase(base);
1191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
1192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<JSTypedArray> const array =
1193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<JSTypedArray>::cast(mbase.Value());
1194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!array->GetBuffer()->was_neutered()) {
1195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      array->GetBuffer()->set_is_neuterable(false);
1196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BufferAccess const access(array->type());
1197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      size_t const k =
1198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ElementSizeLog2Of(access.machine_type().representation());
1199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      double const byte_length = array->byte_length()->Number();
1200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CHECK_LT(k, arraysize(shifted_int32_ranges_));
1201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (access.external_array_type() != kExternalUint8ClampedArray &&
1202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
1203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // JSLoadProperty(typed-array, int32)
1204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<FixedTypedArrayBase> elements =
1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
1207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* length = jsgraph()->Constant(byte_length);
1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* context = NodeProperties::GetContextInput(node);
1209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* effect = NodeProperties::GetEffectInput(node);
1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Node* control = NodeProperties::GetControlInput(node);
1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Convert to a number first.
121213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        if (!value_type->Is(Type::Number())) {
1213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Reduction number_reduction = ReduceJSToNumberInput(value);
1214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (number_reduction.Changed()) {
1215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            value = number_reduction.replacement();
1216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
1217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Node* frame_state_for_to_number =
121813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                NodeProperties::FindFrameStateBefore(node);
1219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            value = effect =
1220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                graph()->NewNode(javascript()->ToNumber(), value, context,
1221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 frame_state_for_to_number, effect, control);
1222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            control = graph()->NewNode(common()->IfSuccess(), value);
1223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
1225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Check if we can avoid the bounds check.
1226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          RelaxControls(node);
1228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          node->ReplaceInput(0, buffer);
1229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK_EQ(key, node->InputAt(1));
1230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          node->ReplaceInput(2, value);
1231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          node->ReplaceInput(3, effect);
1232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          node->ReplaceInput(4, control);
1233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          node->TrimInputCount(5);
1234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          NodeProperties::ChangeOp(
1235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              node,
1236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              simplified()->StoreElement(
1237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  AccessBuilder::ForTypedArrayElement(array->type(), true)));
1238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return Changed(node);
1239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Compute byte offset.
1241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Node* offset =
1242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            (k == 0) ? key : graph()->NewNode(
1243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                 simplified()->NumberShiftLeft(), key,
1244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                 jsgraph()->Constant(static_cast<double>(k)));
1245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Turn into a StoreBuffer operation.
1246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        RelaxControls(node);
1247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        node->ReplaceInput(0, buffer);
1248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node->ReplaceInput(1, offset);
1249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node->ReplaceInput(2, length);
1250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node->ReplaceInput(3, value);
1251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node->ReplaceInput(4, effect);
1252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node->ReplaceInput(5, control);
1253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node->TrimInputCount(6);
1254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access));
1255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return Changed(node);
1256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoChange();
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1262f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochReduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) {
1263f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
1264f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* constructor = NodeProperties::GetValueInput(node, 0);
1265f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Type* constructor_type = NodeProperties::GetType(constructor);
1266f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* object = NodeProperties::GetValueInput(node, 1);
1267f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* context = NodeProperties::GetContextInput(node);
1268f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* frame_state = NodeProperties::GetFrameStateInput(node);
1269f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1270f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1272f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if the {constructor} is a (known) JSFunction.
1273f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (!constructor_type->IsConstant() ||
1274f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      !constructor_type->AsConstant()->Value()->IsJSFunction()) {
1275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return NoChange();
1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSFunction> function =
1278f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Handle<JSFunction>::cast(constructor_type->AsConstant()->Value());
1279f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1280f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if the {function} already has an initial map (i.e. the
1281f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // {function} has been used as a constructor at least once).
1282f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (!function->has_initial_map()) return NoChange();
1283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1284f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if the {function}s "prototype" is a JSReceiver.
1285f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (!function->prototype()->IsJSReceiver()) return NoChange();
1286bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1287f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Install a code dependency on the {function}s initial map.
1288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Map> initial_map(function->initial_map(), isolate());
1289bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  dependencies()->AssumeInitialMapCantChange(initial_map);
1290f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* prototype =
1292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
1293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1294f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), object);
1295f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* branch0 =
1296f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1298f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1299f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* etrue0 = effect;
1300f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* vtrue0 = jsgraph()->FalseConstant();
1301f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1302f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  control = graph()->NewNode(common()->IfFalse(), branch0);
1303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Loop through the {object}s prototype chain looking for the {prototype}.
1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
1306f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* eloop = effect =
1307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
1308f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* vloop = object = graph()->NewNode(
1309f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      common()->Phi(MachineRepresentation::kTagged, 2), object, object, loop);
1310f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // TODO(jarin): This is a very ugly hack to work-around the super-smart
1311f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // implicit typing of the Phi, which goes completely nuts if the {object}
1312f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // is for example a HeapConstant.
1313f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  NodeProperties::SetType(vloop, Type::NonInternal());
1314f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1315f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Load the {object} map and instance type.
1316f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* object_map = effect =
1317f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), object,
1318f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       effect, control);
1319f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* object_instance_type = effect = graph()->NewNode(
1320f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      simplified()->LoadField(AccessBuilder::ForMapInstanceType()), object_map,
1321f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      effect, control);
1322f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1323f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if the {object} is a special receiver, because for special
1324f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // receivers, i.e. proxies or API objects that need access checks,
1325f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // we have to use the %HasInPrototypeChain runtime function instead.
1326f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* check1 = graph()->NewNode(
1327f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      simplified()->NumberLessThanOrEqual(), object_instance_type,
1328f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      jsgraph()->Constant(LAST_SPECIAL_RECEIVER_TYPE));
1329f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* branch1 =
1330f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1332f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  control = graph()->NewNode(common()->IfFalse(), branch1);
1333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1334f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1335f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* etrue1 = effect;
1336f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* vtrue1;
1337f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1338f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if the {object} is not a receiver at all.
1339f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* check10 =
1340f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      graph()->NewNode(simplified()->NumberLessThan(), object_instance_type,
1341f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       jsgraph()->Constant(FIRST_JS_RECEIVER_TYPE));
1342f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* branch10 =
1343f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      graph()->NewNode(common()->Branch(BranchHint::kTrue), check10, if_true1);
1344f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1345f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // A primitive value cannot match the {prototype} we're looking for.
1346f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if_true1 = graph()->NewNode(common()->IfTrue(), branch10);
1347f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  vtrue1 = jsgraph()->FalseConstant();
1348f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1349f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10);
1350f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* efalse1 = etrue1;
1351f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* vfalse1;
1352f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
1353f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Slow path, need to call the %HasInPrototypeChain runtime function.
1354f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    vfalse1 = efalse1 = graph()->NewNode(
1355f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object,
1356f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        prototype, context, frame_state, efalse1, if_false1);
1357f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
1358f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1359f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Replace any potential IfException on {node} to catch exceptions
1360f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // from this %HasInPrototypeChain runtime call instead.
1361f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    for (Edge edge : node->use_edges()) {
1362f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (edge.from()->opcode() == IrOpcode::kIfException) {
1363f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        edge.UpdateTo(vfalse1);
1364f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Revisit(edge.from());
1365f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1366f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1367f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1369f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Load the {object} prototype.
1370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* object_prototype = effect = graph()->NewNode(
1371f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      simplified()->LoadField(AccessBuilder::ForMapPrototype()), object_map,
1372f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      effect, control);
1373f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1374f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if we reached the end of {object}s prototype chain.
1375f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(),
1376f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                  object_prototype, jsgraph()->NullConstant());
1377f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* branch2 = graph()->NewNode(common()->Branch(), check2, control);
1378f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1379f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1380f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* etrue2 = effect;
1381f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* vtrue2 = jsgraph()->FalseConstant();
1382f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1383f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  control = graph()->NewNode(common()->IfFalse(), branch2);
1384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1385f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if we reached the {prototype}.
1386f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* check3 = graph()->NewNode(simplified()->ReferenceEqual(),
1387f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                  object_prototype, prototype);
1388f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* branch3 = graph()->NewNode(common()->Branch(), check3, control);
1389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1390f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
1391f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* etrue3 = effect;
1392f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* vtrue3 = jsgraph()->TrueConstant();
1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1394f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  control = graph()->NewNode(common()->IfFalse(), branch3);
1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1396f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Close the loop.
1397f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  vloop->ReplaceInput(1, object_prototype);
1398f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  eloop->ReplaceInput(1, effect);
1399f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  loop->ReplaceInput(1, control);
1400f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1401f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  control = graph()->NewNode(common()->Merge(5), if_true0, if_true1, if_true2,
1402f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                             if_true3, if_false1);
1403f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  effect = graph()->NewNode(common()->EffectPhi(5), etrue0, etrue1, etrue2,
1404f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                            etrue3, efalse1, control);
1405f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1406f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Morph the {node} into an appropriate Phi.
1407f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  ReplaceWithValue(node, node, effect, control);
1408f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->ReplaceInput(0, vtrue0);
1409f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->ReplaceInput(1, vtrue1);
1410f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->ReplaceInput(2, vtrue2);
1411f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->ReplaceInput(3, vtrue3);
1412f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->ReplaceInput(4, vfalse1);
1413f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->ReplaceInput(5, control);
1414f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->TrimInputCount(6);
1415f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  NodeProperties::ChangeOp(node,
1416f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                           common()->Phi(MachineRepresentation::kTagged, 5));
1417f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return Changed(node);
1418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierReduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
1421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
1422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ContextAccess const& access = ContextAccessOf(node->op());
1423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = graph()->start();
1425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (size_t i = 0; i < access.depth(); ++i) {
1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* previous = effect = graph()->NewNode(
1427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        simplified()->LoadField(
1428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
1429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::GetValueInput(node, 0), effect, control);
1430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->ReplaceInput(0, previous);
1431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  node->ReplaceInput(1, effect);
1433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  node->ReplaceInput(2, control);
1434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(
1435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node,
1436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      simplified()->LoadField(AccessBuilder::ForContextSlot(access.index())));
1437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return Changed(node);
1438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierReduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
1441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
1442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ContextAccess const& access = ContextAccessOf(node->op());
1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = graph()->start();
1445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (size_t i = 0; i < access.depth(); ++i) {
1446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* previous = effect = graph()->NewNode(
1447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        simplified()->LoadField(
1448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
1449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::GetValueInput(node, 0), effect, control);
1450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->ReplaceInput(0, previous);
1451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  node->RemoveInput(2);
1453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->ReplaceInput(2, effect);
1454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(
1455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node,
1456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      simplified()->StoreField(AccessBuilder::ForContextSlot(access.index())));
1457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Changed(node);
1458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
1461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
1462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* receiver = NodeProperties::GetValueInput(node, 0);
1464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* receiver_type = NodeProperties::GetType(receiver);
1465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* context = NodeProperties::GetContextInput(node);
1466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* context_type = NodeProperties::GetType(context);
1467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* frame_state = NodeProperties::GetFrameStateInput(node);
1468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
1470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if {receiver} is known to be a receiver.
1472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (receiver_type->Is(Type::Receiver())) {
1473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ReplaceWithValue(node, receiver, effect, control);
1474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Replace(receiver);
1475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // If the {receiver} is known to be null or undefined, we can just replace it
1478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // with the global proxy unconditionally.
1479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (receiver_type->Is(Type::NullOrUndefined()) ||
1480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      mode == ConvertReceiverMode::kNullOrUndefined) {
1481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (context_type->IsConstant()) {
1482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Handle<JSObject> global_proxy(
1483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          Handle<Context>::cast(context_type->AsConstant()->Value())
1484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              ->global_proxy(),
1485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          isolate());
1486f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      receiver = jsgraph()->Constant(global_proxy);
1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* native_context = effect = graph()->NewNode(
1489f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
1490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          context, context, effect);
1491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      receiver = effect = graph()->NewNode(
1492f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
1493f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          native_context, native_context, effect);
1494f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1495f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ReplaceWithValue(node, receiver, effect, control);
1496f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Replace(receiver);
1497f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1499f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // If {receiver} cannot be null or undefined we can skip a few checks.
1500f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
1501f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      mode == ConvertReceiverMode::kNotNullOrUndefined) {
1502f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
1503f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* branch =
1504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* etrue = effect;
1508f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* rtrue = receiver;
1509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* efalse = effect;
1512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* rfalse;
1513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
1514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Convert {receiver} using the ToObjectStub.
1515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Callable callable = CodeFactory::ToObject(isolate());
1516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
1517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          isolate(), graph()->zone(), callable.descriptor(), 0,
1518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          CallDescriptor::kNeedsFrameState, node->op()->properties());
1519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      rfalse = efalse = graph()->NewNode(
1520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
1521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          receiver, context, frame_state, efalse);
1522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Morph the {node} into an appropriate Phi.
1528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ReplaceWithValue(node, node, effect, control);
1529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    node->ReplaceInput(0, rtrue);
1530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    node->ReplaceInput(1, rfalse);
1531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    node->ReplaceInput(2, control);
1532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    node->TrimInputCount(3);
1533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    NodeProperties::ChangeOp(node,
1534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             common()->Phi(MachineRepresentation::kTagged, 2));
1535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Changed(node);
1536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if {receiver} is already a JSReceiver.
1539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* check0 = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
1540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* branch0 =
1541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
1542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check {receiver} for undefined.
1546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* check1 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
1547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  jsgraph()->UndefinedConstant());
1548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* branch1 =
1549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, if_false0);
1550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1551f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1553f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check {receiver} for null.
1554f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
1555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  jsgraph()->NullConstant());
1556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* branch2 =
1557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      graph()->NewNode(common()->Branch(BranchHint::kFalse), check2, if_false1);
1558f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1559f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1561f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // We just use {receiver} directly.
1562f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_noop = if_true0;
1563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* enoop = effect;
1564f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rnoop = receiver;
1565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1566f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Convert {receiver} using ToObject.
1567f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_convert = if_false2;
1568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* econvert = effect;
1569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rconvert;
1570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
1571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Convert {receiver} using the ToObjectStub.
1572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Callable callable = CodeFactory::ToObject(isolate());
1573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
1574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate(), graph()->zone(), callable.descriptor(), 0,
1575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        CallDescriptor::kNeedsFrameState, node->op()->properties());
1576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    rconvert = econvert = graph()->NewNode(
1577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
1578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        receiver, context, frame_state, econvert);
1579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Replace {receiver} with global proxy of {context}.
1582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* if_global = graph()->NewNode(common()->Merge(2), if_true1, if_true2);
1583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* eglobal = effect;
1584f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rglobal;
1585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
1586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (context_type->IsConstant()) {
1587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Handle<JSObject> global_proxy(
1588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          Handle<Context>::cast(context_type->AsConstant()->Value())
1589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              ->global_proxy(),
1590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          isolate());
1591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      rglobal = jsgraph()->Constant(global_proxy);
1592f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
1593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* native_context = eglobal = graph()->NewNode(
1594f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
1595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          context, context, eglobal);
1596f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      rglobal = eglobal = graph()->NewNode(
1597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
1598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          native_context, native_context, eglobal);
1599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  control =
1603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      graph()->NewNode(common()->Merge(3), if_noop, if_convert, if_global);
1604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  effect = graph()->NewNode(common()->EffectPhi(3), enoop, econvert, eglobal,
1605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                            control);
1606f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Morph the {node} into an appropriate Phi.
1607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ReplaceWithValue(node, node, effect, control);
1608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->ReplaceInput(0, rnoop);
1609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->ReplaceInput(1, rconvert);
1610f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->ReplaceInput(2, rglobal);
1611f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->ReplaceInput(3, control);
1612f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->TrimInputCount(4);
1613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NodeProperties::ChangeOp(node,
1614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           common()->Phi(MachineRepresentation::kTagged, 3));
1615f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return Changed(node);
1616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace {
1619f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid ReduceBuiltin(Isolate* isolate, JSGraph* jsgraph, Node* node,
1621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   int builtin_index, int arity, CallDescriptor::Flags flags) {
1622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Patch {node} to a direct CEntryStub call.
1623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
1624f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // ----------- A r g u m e n t s -----------
1625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -- 0: CEntryStub
1626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // --- Stack args ---
1627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -- 1: receiver
1628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -- [2, 2 + n[: the n actual arguments passed to the builtin
1629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -- 2 + n: argc, including the receiver and implicit args (Smi)
1630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -- 2 + n + 1: target
1631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -- 2 + n + 2: new_target
1632f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // --- Register args ---
1633f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -- 2 + n + 3: the C entry point
1634f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -- 2 + n + 4: argc (Int32)
1635f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // -----------------------------------
1636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // The logic contained here is mirrored in Builtins::Generate_Adaptor.
1638f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Keep these in sync.
1639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const bool is_construct = (node->opcode() == IrOpcode::kJSCallConstruct);
1641f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(Builtins::HasCppImplementation(builtin_index));
1643f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1644f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* target = NodeProperties::GetValueInput(node, 0);
1645f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* new_target = is_construct
1646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                         ? NodeProperties::GetValueInput(node, arity + 1)
1647f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                         : jsgraph->UndefinedConstant();
1648f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // API and CPP builtins are implemented in C++, and we can inline both.
1650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // CPP builtins create a builtin exit frame, API builtins don't.
1651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const bool has_builtin_exit_frame = Builtins::IsCpp(builtin_index);
1652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1653f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* stub = jsgraph->CEntryStubConstant(1, kDontSaveFPRegs, kArgvOnStack,
1654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                           has_builtin_exit_frame);
1655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  node->ReplaceInput(0, stub);
1656f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Zone* zone = jsgraph->zone();
1658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (is_construct) {
1659f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Unify representations between construct and call nodes.
1660f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Remove new target and add receiver as a stack parameter.
1661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* receiver = jsgraph->UndefinedConstant();
1662f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    node->RemoveInput(arity + 1);
1663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    node->InsertInput(zone, 1, receiver);
1664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1666f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const int argc = arity + BuiltinArguments::kNumExtraArgsWithReceiver;
1667f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* argc_node = jsgraph->Int32Constant(argc);
1668f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1669f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static const int kStubAndReceiver = 2;
1670f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int cursor = arity + kStubAndReceiver;
1671f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->InsertInput(zone, cursor++, argc_node);
1672f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->InsertInput(zone, cursor++, target);
1673f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->InsertInput(zone, cursor++, new_target);
1674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Address entry = Builtins::CppEntryOf(builtin_index);
1676f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ExternalReference entry_ref(ExternalReference(entry, isolate));
1677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* entry_node = jsgraph->ExternalConstant(entry_ref);
1678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1679f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->InsertInput(zone, cursor++, entry_node);
1680f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  node->InsertInput(zone, cursor++, argc_node);
1681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const int kReturnCount = 1;
1683f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const char* debug_name = Builtins::name(builtin_index);
1684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Operator::Properties properties = node->op()->properties();
1685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CallDescriptor* desc = Linkage::GetCEntryStubCallDescriptor(
1686f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      zone, kReturnCount, argc, debug_name, properties, flags);
1687f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NodeProperties::ChangeOp(node, jsgraph->common()->Call(desc));
1689f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1690f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1691f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochbool NeedsArgumentAdaptorFrame(Handle<SharedFunctionInfo> shared, int arity) {
1692f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
1693f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  const int num_decl_parms = shared->internal_formal_parameter_count();
1694f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return (num_decl_parms != arity && num_decl_parms != sentinel);
1695f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
1696f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace
1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
1700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
1701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallConstructParameters const& p = CallConstructParametersOf(node->op());
1702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2u, p.arity());
1703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const arity = static_cast<int>(p.arity() - 2);
1704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* target = NodeProperties::GetValueInput(node, 0);
1705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* target_type = NodeProperties::GetType(target);
1706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
1707f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1708f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* control = NodeProperties::GetControlInput(node);
1709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if {target} is a known JSFunction.
1711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (target_type->IsConstant() &&
1712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      target_type->AsConstant()->Value()->IsJSFunction()) {
1713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<JSFunction> function =
1714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<JSFunction>::cast(target_type->AsConstant()->Value());
1715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1716f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const int builtin_index = shared->construct_stub()->builtin_index();
1717f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const bool is_builtin = (builtin_index != -1);
1718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1720f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (is_builtin && Builtins::HasCppImplementation(builtin_index) &&
1722f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        !NeedsArgumentAdaptorFrame(shared, arity)) {
1723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Patch {node} to a direct CEntryStub call.
1724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Load the context from the {target}.
1726f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* context = effect = graph()->NewNode(
1727f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          simplified()->LoadField(AccessBuilder::ForJSFunctionContext()),
1728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          target, effect, control);
1729f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::ReplaceContextInput(node, context);
1730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Update the effect dependency for the {node}.
1732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::ReplaceEffectInput(node, effect);
1733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ReduceBuiltin(isolate(), jsgraph(), node, builtin_index, arity, flags);
1735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
1736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Patch {node} to an indirect call via the {function}s construct stub.
1737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Callable callable(handle(shared->construct_stub(), isolate()),
1738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                        ConstructStubDescriptor(isolate()));
1739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node->RemoveInput(arity + 1);
1740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node->InsertInput(graph()->zone(), 0,
1741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                        jsgraph()->HeapConstant(callable.code()));
1742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node->InsertInput(graph()->zone(), 2, new_target);
1743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
1744f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
1745f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
1746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::ChangeOp(
1747f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          node, common()->Call(Linkage::GetStubCallDescriptor(
1748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    isolate(), graph()->zone(), callable.descriptor(),
1749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    1 + arity, flags)));
1750f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
1752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if {target} is a JSFunction.
1755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (target_type->Is(Type::Function())) {
1756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Patch {node} to an indirect call via the ConstructFunction builtin.
1757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Callable callable = CodeFactory::ConstructFunction(isolate());
1758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->RemoveInput(arity + 1);
1759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->InsertInput(graph()->zone(), 0,
1760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      jsgraph()->HeapConstant(callable.code()));
1761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->InsertInput(graph()->zone(), 2, new_target);
1762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
1763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
1764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(
1765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node, common()->Call(Linkage::GetStubCallDescriptor(
1766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  CallDescriptor::kNeedsFrameState)));
1768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
1769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
1776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
1777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
1778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const arity = static_cast<int>(p.arity() - 2);
1779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConvertReceiverMode convert_mode = p.convert_mode();
1780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* target = NodeProperties::GetValueInput(node, 0);
1781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* target_type = NodeProperties::GetType(target);
1782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* receiver = NodeProperties::GetValueInput(node, 1);
1783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Type* receiver_type = NodeProperties::GetType(receiver);
1784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
178613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
1787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Try to infer receiver {convert_mode} from {receiver} type.
1789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (receiver_type->Is(Type::NullOrUndefined())) {
1790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNullOrUndefined;
1791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (!receiver_type->Maybe(Type::NullOrUndefined())) {
1792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
1793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if {target} is a known JSFunction.
1796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (target_type->IsConstant() &&
1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      target_type->AsConstant()->Value()->IsJSFunction()) {
1798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<JSFunction> function =
1799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<JSFunction>::cast(target_type->AsConstant()->Value());
1800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1801f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const int builtin_index = shared->code()->builtin_index();
1802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const bool is_builtin = (builtin_index != -1);
1803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Class constructors are callable, but [[Call]] will raise an exception.
1805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
1806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsClassConstructor(shared->kind())) return NoChange();
1807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load the context from the {target}.
1809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* context = effect = graph()->NewNode(
1810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
1811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        effect, control);
1812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ReplaceContextInput(node, context);
1813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check if we need to convert the {receiver}.
1815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_sloppy(shared->language_mode()) && !shared->native() &&
1816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        !receiver_type->Is(Type::Receiver())) {
1817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      receiver = effect =
1818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          graph()->NewNode(javascript()->ConvertReceiver(convert_mode),
1819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           receiver, context, frame_state, effect, control);
1820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ReplaceValueInput(node, receiver, 1);
1821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Update the effect dependency for the {node}.
1824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ReplaceEffectInput(node, effect);
1825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Compute flags for the call.
1827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (p.tail_call_mode() == TailCallMode::kAllow) {
1829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      flags |= CallDescriptor::kSupportsTailCalls;
1830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* new_target = jsgraph()->UndefinedConstant();
1833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* argument_count = jsgraph()->Int32Constant(arity);
1834f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (NeedsArgumentAdaptorFrame(shared, arity)) {
1835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Patch {node} to an indirect call via the ArgumentsAdaptorTrampoline.
1836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Callable callable = CodeFactory::ArgumentAdaptor(isolate());
1837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node->InsertInput(graph()->zone(), 0,
1838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        jsgraph()->HeapConstant(callable.code()));
1839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node->InsertInput(graph()->zone(), 2, new_target);
1840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node->InsertInput(graph()->zone(), 3, argument_count);
1841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node->InsertInput(
1842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          graph()->zone(), 4,
1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          jsgraph()->Int32Constant(shared->internal_formal_parameter_count()));
1844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ChangeOp(
1845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          node, common()->Call(Linkage::GetStubCallDescriptor(
1846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    isolate(), graph()->zone(), callable.descriptor(),
1847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    1 + arity, flags)));
1848f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else if (is_builtin && Builtins::HasCppImplementation(builtin_index)) {
1849f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Patch {node} to a direct CEntryStub call.
1850f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      ReduceBuiltin(isolate(), jsgraph(), node, builtin_index, arity, flags);
1851f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else {
1852f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Patch {node} to a direct call.
1853f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      node->InsertInput(graph()->zone(), arity + 2, new_target);
1854f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      node->InsertInput(graph()->zone(), arity + 3, argument_count);
1855f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      NodeProperties::ChangeOp(node,
1856f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                               common()->Call(Linkage::GetJSCallDescriptor(
1857f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                   graph()->zone(), false, 1 + arity, flags)));
1858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
1860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if {target} is a JSFunction.
1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (target_type->Is(Type::Function())) {
1864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Compute flags for the call.
1865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (p.tail_call_mode() == TailCallMode::kAllow) {
1867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      flags |= CallDescriptor::kSupportsTailCalls;
1868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Patch {node} to an indirect call via the CallFunction builtin.
1871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Callable callable = CodeFactory::CallFunction(isolate(), convert_mode);
1872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->InsertInput(graph()->zone(), 0,
1873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      jsgraph()->HeapConstant(callable.code()));
1874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->InsertInput(graph()->zone(), 2, jsgraph()->Int32Constant(arity));
1875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(
1876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node, common()->Call(Linkage::GetStubCallDescriptor(
1877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
1878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  flags)));
1879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
1880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Maybe we did at least learn something about the {receiver}.
1883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (p.convert_mode() != convert_mode) {
1884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(
1885f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        node, javascript()->CallFunction(p.arity(), p.frequency(), p.feedback(),
1886f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                         convert_mode, p.tail_call_mode()));
1887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
1888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
1891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSTypedLowering::ReduceJSForInNext(Node* node) {
1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode());
1896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* receiver = NodeProperties::GetValueInput(node, 0);
1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* cache_array = NodeProperties::GetValueInput(node, 1);
1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* cache_type = NodeProperties::GetValueInput(node, 2);
1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* index = NodeProperties::GetValueInput(node, 3);
1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* context = NodeProperties::GetContextInput(node);
1901f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* frame_state = NodeProperties::GetFrameStateInput(node);
1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the next {key} from the {cache_array}.
1906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* key = effect = graph()->NewNode(
1907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
1908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      cache_array, index, effect, control);
1909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the map of the {receiver}.
1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* receiver_map = effect =
1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       receiver, effect, control);
1914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if the expected map still matches that of the {receiver}.
1916f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), receiver_map,
1917f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  cache_type);
1918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* branch0 =
1919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
1920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* etrue0;
1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* vtrue0;
1924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
1925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Don't need filtering since expected map still matches that of the
1926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // {receiver}.
1927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    etrue0 = effect;
1928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vtrue0 = key;
1929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* efalse0;
1933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* vfalse0;
1934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
1935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Filter the {key} to check if it's still a valid property of the
1936109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // {receiver} (does the ToName conversion implicitly).
1937f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Callable const callable = CodeFactory::ForInFilter(isolate());
1938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
1939f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate(), graph()->zone(), callable.descriptor(), 0,
1940f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        CallDescriptor::kNeedsFrameState);
1941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    vfalse0 = efalse0 = graph()->NewNode(
1942f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        common()->Call(desc), jsgraph()->HeapConstant(callable.code()), key,
1943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        receiver, context, frame_state, effect, if_false0);
1944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ReplaceWithValue(node, node, effect, control);
1950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->ReplaceInput(0, vtrue0);
1951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->ReplaceInput(1, vfalse0);
1952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->ReplaceInput(2, control);
1953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->TrimInputCount(3);
1954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(node,
1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           common()->Phi(MachineRepresentation::kTagged, 2));
1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Changed(node);
1957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
195913e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochReduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
196013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode());
196113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* generator = NodeProperties::GetValueInput(node, 0);
196213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* continuation = NodeProperties::GetValueInput(node, 1);
196313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* offset = NodeProperties::GetValueInput(node, 2);
196413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* context = NodeProperties::GetContextInput(node);
196513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
196613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* control = NodeProperties::GetControlInput(node);
196713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int register_count = OpParameter<int>(node);
196813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
196913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectOperandStack();
197013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext();
197113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FieldAccess continuation_field =
197213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      AccessBuilder::ForJSGeneratorObjectContinuation();
197313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FieldAccess input_or_debug_pos_field =
197413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
197513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
197613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
197713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                          generator, effect, control);
197813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
197913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (int i = 0; i < register_count; ++i) {
198013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Node* value = NodeProperties::GetValueInput(node, 3 + i);
198113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    effect = graph()->NewNode(
198213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array,
198313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        value, effect, control);
198413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
198513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
198613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  effect = graph()->NewNode(simplified()->StoreField(context_field), generator,
198713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            context, effect, control);
198813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  effect = graph()->NewNode(simplified()->StoreField(continuation_field),
198913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            generator, continuation, effect, control);
199013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  effect = graph()->NewNode(simplified()->StoreField(input_or_debug_pos_field),
199113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            generator, offset, effect, control);
199213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
199313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ReplaceWithValue(node, effect, effect, control);
199413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return Changed(effect);
199513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
199613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
199713e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochReduction JSTypedLowering::ReduceJSGeneratorRestoreContinuation(Node* node) {
199813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContinuation, node->opcode());
199913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* generator = NodeProperties::GetValueInput(node, 0);
200013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
200113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* control = NodeProperties::GetControlInput(node);
200213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
200313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FieldAccess continuation_field =
200413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      AccessBuilder::ForJSGeneratorObjectContinuation();
200513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
200613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* continuation = effect = graph()->NewNode(
200713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      simplified()->LoadField(continuation_field), generator, effect, control);
200813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* executing = jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting);
200913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  effect = graph()->NewNode(simplified()->StoreField(continuation_field),
201013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            generator, executing, effect, control);
201113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
201213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ReplaceWithValue(node, continuation, effect, control);
201313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return Changed(continuation);
201413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
201513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
201613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochReduction JSTypedLowering::ReduceJSGeneratorRestoreRegister(Node* node) {
201713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK_EQ(IrOpcode::kJSGeneratorRestoreRegister, node->opcode());
201813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* generator = NodeProperties::GetValueInput(node, 0);
201913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
202013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* control = NodeProperties::GetControlInput(node);
202113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int index = OpParameter<int>(node);
202213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
202313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectOperandStack();
202413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FieldAccess element_field = AccessBuilder::ForFixedArraySlot(index);
202513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
202613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
202713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                          generator, effect, control);
202813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* element = effect = graph()->NewNode(
202913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      simplified()->LoadField(element_field), array, effect, control);
203013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* stale = jsgraph()->StaleRegisterConstant();
203113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  effect = graph()->NewNode(simplified()->StoreField(element_field), array,
203213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            stale, effect, control);
203313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
203413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ReplaceWithValue(node, element, effect, control);
203513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return Changed(element);
203613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
2037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochReduction JSTypedLowering::Reduce(Node* node) {
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (node->opcode()) {
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSEqual:
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ReduceJSEqual(node, false);
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSNotEqual:
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ReduceJSEqual(node, true);
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSStrictEqual:
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ReduceJSStrictEqual(node, false);
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSStrictNotEqual:
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ReduceJSStrictEqual(node, true);
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSLessThan:         // fall through
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSGreaterThan:      // fall through
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSLessThanOrEqual:  // fall through
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSGreaterThanOrEqual:
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ReduceJSComparison(node);
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSBitwiseOr:
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSBitwiseXor:
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSBitwiseAnd:
2056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return ReduceInt32Binop(node);
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSShiftLeft:
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSShiftRight:
2059f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return ReduceUI32Shift(node, kSigned);
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSShiftRightLogical:
2061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return ReduceUI32Shift(node, kUnsigned);
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSAdd:
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ReduceJSAdd(node);
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSSubtract:
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSMultiply:
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSDivide:
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSModulus:
2068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return ReduceNumberBinop(node);
2069f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kJSOrdinaryHasInstance:
2070f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return ReduceJSOrdinaryHasInstance(node);
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSToBoolean:
2072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReduceJSToBoolean(node);
20733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case IrOpcode::kJSToInteger:
20743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return ReduceJSToInteger(node);
20753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case IrOpcode::kJSToLength:
20763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return ReduceJSToLength(node);
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSToNumber:
2078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReduceJSToNumber(node);
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSToString:
2080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReduceJSToString(node);
2081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kJSToObject:
2082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceJSToObject(node);
2083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kJSLoadNamed:
2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceJSLoadNamed(node);
2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSLoadProperty:
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ReduceJSLoadProperty(node);
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case IrOpcode::kJSStoreProperty:
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ReduceJSStoreProperty(node);
2089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case IrOpcode::kJSLoadContext:
2090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReduceJSLoadContext(node);
2091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case IrOpcode::kJSStoreContext:
2092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReduceJSStoreContext(node);
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kJSConvertReceiver:
2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceJSConvertReceiver(node);
2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kJSCallConstruct:
2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceJSCallConstruct(node);
2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kJSCallFunction:
2098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceJSCallFunction(node);
2099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kJSForInNext:
2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceJSForInNext(node);
210113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kJSGeneratorStore:
210213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return ReduceJSGeneratorStore(node);
210313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kJSGeneratorRestoreContinuation:
210413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return ReduceJSGeneratorRestoreContinuation(node);
210513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kJSGeneratorRestoreRegister:
210613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return ReduceJSGeneratorRestoreRegister(node);
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoChange();
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierFactory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
2115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierGraph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
2118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochIsolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); }
2121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierJSOperatorBuilder* JSTypedLowering::javascript() const {
2124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return jsgraph()->javascript();
2125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierCommonOperatorBuilder* JSTypedLowering::common() const {
2129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return jsgraph()->common();
2130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochSimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return jsgraph()->simplified();
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCompilationDependencies* JSTypedLowering::dependencies() const {
2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return dependencies_;
2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace compiler
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace internal
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8
2144