js-typed-lowering.cc revision 8389745919cae02139ddc085a63c00d024269cf2
1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/code-factory.h"
6#include "src/compilation-dependencies.h"
7#include "src/compiler/access-builder.h"
8#include "src/compiler/js-graph.h"
9#include "src/compiler/js-typed-lowering.h"
10#include "src/compiler/linkage.h"
11#include "src/compiler/node-matchers.h"
12#include "src/compiler/node-properties.h"
13#include "src/compiler/operator-properties.h"
14#include "src/type-cache.h"
15#include "src/types.h"
16
17namespace v8 {
18namespace internal {
19namespace compiler {
20
21// A helper class to simplify the process of reducing a single binop node with a
22// JSOperator. This class manages the rewriting of context, control, and effect
23// dependencies during lowering of a binop and contains numerous helper
24// functions for matching the types of inputs to an operation.
25class JSBinopReduction final {
26 public:
27  JSBinopReduction(JSTypedLowering* lowering, Node* node)
28      : lowering_(lowering), node_(node) {}
29
30  void ConvertInputsToNumber(Node* frame_state) {
31    // To convert the inputs to numbers, we have to provide frame states
32    // for lazy bailouts in the ToNumber conversions.
33    // We use a little hack here: we take the frame state before the binary
34    // operation and use it to construct the frame states for the conversion
35    // so that after the deoptimization, the binary operation IC gets
36    // already converted values from full code. This way we are sure that we
37    // will not re-do any of the side effects.
38
39    Node* left_input = nullptr;
40    Node* right_input = nullptr;
41    bool left_is_primitive = left_type()->Is(Type::PlainPrimitive());
42    bool right_is_primitive = right_type()->Is(Type::PlainPrimitive());
43    bool handles_exception = NodeProperties::IsExceptionalCall(node_);
44
45    if (!left_is_primitive && !right_is_primitive && handles_exception) {
46      ConvertBothInputsToNumber(&left_input, &right_input, frame_state);
47    } else {
48      left_input = left_is_primitive
49                       ? ConvertPlainPrimitiveToNumber(left())
50                       : ConvertSingleInputToNumber(
51                             left(), CreateFrameStateForLeftInput(frame_state));
52      right_input = right_is_primitive
53                        ? ConvertPlainPrimitiveToNumber(right())
54                        : ConvertSingleInputToNumber(
55                              right(), CreateFrameStateForRightInput(
56                                           frame_state, left_input));
57    }
58
59    node_->ReplaceInput(0, left_input);
60    node_->ReplaceInput(1, right_input);
61  }
62
63  void ConvertInputsToUI32(Signedness left_signedness,
64                           Signedness right_signedness) {
65    node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
66    node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
67  }
68
69  void SwapInputs() {
70    Node* l = left();
71    Node* r = right();
72    node_->ReplaceInput(0, r);
73    node_->ReplaceInput(1, l);
74  }
75
76  // Remove all effect and control inputs and outputs to this node and change
77  // to the pure operator {op}, possibly inserting a boolean inversion.
78  Reduction ChangeToPureOperator(const Operator* op, bool invert = false,
79                                 Type* type = Type::Any()) {
80    DCHECK_EQ(0, op->EffectInputCount());
81    DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
82    DCHECK_EQ(0, op->ControlInputCount());
83    DCHECK_EQ(2, op->ValueInputCount());
84
85    // Remove the effects from the node, and update its effect/control usages.
86    if (node_->op()->EffectInputCount() > 0) {
87      lowering_->RelaxEffectsAndControls(node_);
88    }
89    // Remove the inputs corresponding to context, effect, and control.
90    NodeProperties::RemoveNonValueInputs(node_);
91    // Finally, update the operator to the new one.
92    NodeProperties::ChangeOp(node_, op);
93
94    // TODO(jarin): Replace the explicit typing hack with a call to some method
95    // that encapsulates changing the operator and re-typing.
96    Type* node_type = NodeProperties::GetType(node_);
97    NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
98
99    if (invert) {
100      // Insert an boolean not to invert the value.
101      Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
102      node_->ReplaceUses(value);
103      // Note: ReplaceUses() smashes all uses, so smash it back here.
104      value->ReplaceInput(0, node_);
105      return lowering_->Replace(value);
106    }
107    return lowering_->Changed(node_);
108  }
109
110  Reduction ChangeToStringComparisonOperator(const Operator* op,
111                                             bool invert = false) {
112    if (node_->op()->ControlInputCount() > 0) {
113      lowering_->RelaxControls(node_);
114    }
115    // String comparison operators need effect and control inputs, so copy them
116    // over.
117    Node* effect = NodeProperties::GetEffectInput(node_);
118    Node* control = NodeProperties::GetControlInput(node_);
119    node_->ReplaceInput(2, effect);
120    node_->ReplaceInput(3, control);
121
122    node_->TrimInputCount(4);
123    NodeProperties::ChangeOp(node_, op);
124
125    if (invert) {
126      // Insert a boolean-not to invert the value.
127      Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
128      node_->ReplaceUses(value);
129      // Note: ReplaceUses() smashes all uses, so smash it back here.
130      value->ReplaceInput(0, node_);
131      return lowering_->Replace(value);
132    }
133    return lowering_->Changed(node_);
134  }
135
136  Reduction ChangeToPureOperator(const Operator* op, Type* type) {
137    return ChangeToPureOperator(op, false, type);
138  }
139
140  bool LeftInputIs(Type* t) { return left_type()->Is(t); }
141
142  bool RightInputIs(Type* t) { return right_type()->Is(t); }
143
144  bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
145
146  bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); }
147
148  bool OneInputCannotBe(Type* t) {
149    return !left_type()->Maybe(t) || !right_type()->Maybe(t);
150  }
151
152  bool NeitherInputCanBe(Type* t) {
153    return !left_type()->Maybe(t) && !right_type()->Maybe(t);
154  }
155
156  Node* effect() { return NodeProperties::GetEffectInput(node_); }
157  Node* control() { return NodeProperties::GetControlInput(node_); }
158  Node* context() { return NodeProperties::GetContextInput(node_); }
159  Node* left() { return NodeProperties::GetValueInput(node_, 0); }
160  Node* right() { return NodeProperties::GetValueInput(node_, 1); }
161  Type* left_type() { return NodeProperties::GetType(node_->InputAt(0)); }
162  Type* right_type() { return NodeProperties::GetType(node_->InputAt(1)); }
163
164  SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
165  Graph* graph() const { return lowering_->graph(); }
166  JSGraph* jsgraph() { return lowering_->jsgraph(); }
167  JSOperatorBuilder* javascript() { return lowering_->javascript(); }
168  MachineOperatorBuilder* machine() { return lowering_->machine(); }
169  CommonOperatorBuilder* common() { return jsgraph()->common(); }
170  Zone* zone() const { return graph()->zone(); }
171
172 private:
173  JSTypedLowering* lowering_;  // The containing lowering instance.
174  Node* node_;                 // The original node.
175
176  Node* CreateFrameStateForLeftInput(Node* frame_state) {
177    FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
178
179    if (state_info.bailout_id() == BailoutId::None()) {
180      // Dummy frame state => just leave it as is.
181      return frame_state;
182    }
183
184    // If the frame state is already the right one, just return it.
185    if (state_info.state_combine().kind() == OutputFrameStateCombine::kPokeAt &&
186        state_info.state_combine().GetOffsetToPokeAt() == 1) {
187      return frame_state;
188    }
189
190    // Here, we smash the result of the conversion into the slot just below
191    // the stack top. This is the slot that full code uses to store the
192    // left operand.
193    const Operator* op = jsgraph()->common()->FrameState(
194        state_info.bailout_id(), OutputFrameStateCombine::PokeAt(1),
195        state_info.function_info());
196
197    return graph()->NewNode(op,
198                            frame_state->InputAt(kFrameStateParametersInput),
199                            frame_state->InputAt(kFrameStateLocalsInput),
200                            frame_state->InputAt(kFrameStateStackInput),
201                            frame_state->InputAt(kFrameStateContextInput),
202                            frame_state->InputAt(kFrameStateFunctionInput),
203                            frame_state->InputAt(kFrameStateOuterStateInput));
204  }
205
206  Node* CreateFrameStateForRightInput(Node* frame_state, Node* converted_left) {
207    FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
208
209    if (state_info.bailout_id() == BailoutId::None()) {
210      // Dummy frame state => just leave it as is.
211      return frame_state;
212    }
213
214    // Create a frame state that stores the result of the operation to the
215    // top of the stack (i.e., the slot used for the right operand).
216    const Operator* op = jsgraph()->common()->FrameState(
217        state_info.bailout_id(), OutputFrameStateCombine::PokeAt(0),
218        state_info.function_info());
219
220    // Change the left operand {converted_left} on the expression stack.
221    Node* stack = frame_state->InputAt(2);
222    DCHECK_EQ(stack->opcode(), IrOpcode::kStateValues);
223    DCHECK_GE(stack->InputCount(), 2);
224
225    // TODO(jarin) Allocate in a local zone or a reusable buffer.
226    NodeVector new_values(stack->InputCount(), zone());
227    for (int i = 0; i < stack->InputCount(); i++) {
228      if (i == stack->InputCount() - 2) {
229        new_values[i] = converted_left;
230      } else {
231        new_values[i] = stack->InputAt(i);
232      }
233    }
234    Node* new_stack =
235        graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front());
236
237    return graph()->NewNode(
238        op, frame_state->InputAt(kFrameStateParametersInput),
239        frame_state->InputAt(kFrameStateLocalsInput), new_stack,
240        frame_state->InputAt(kFrameStateContextInput),
241        frame_state->InputAt(kFrameStateFunctionInput),
242        frame_state->InputAt(kFrameStateOuterStateInput));
243  }
244
245  Node* ConvertPlainPrimitiveToNumber(Node* node) {
246    DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
247    // Avoid inserting too many eager ToNumber() operations.
248    Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
249    if (reduction.Changed()) return reduction.replacement();
250    // TODO(jarin) Use PlainPrimitiveToNumber once we have it.
251    return graph()->NewNode(
252        javascript()->ToNumber(), node, jsgraph()->NoContextConstant(),
253        jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
254  }
255
256  Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
257    DCHECK(!NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
258    Node* const n = graph()->NewNode(javascript()->ToNumber(), node, context(),
259                                     frame_state, effect(), control());
260    NodeProperties::ReplaceUses(node_, node_, node_, n, n);
261    update_effect(n);
262    return n;
263  }
264
265  void ConvertBothInputsToNumber(Node** left_result, Node** right_result,
266                                 Node* frame_state) {
267    Node* projections[2];
268
269    // Find {IfSuccess} and {IfException} continuations of the operation.
270    NodeProperties::CollectControlProjections(node_, projections, 2);
271    IfExceptionHint hint = OpParameter<IfExceptionHint>(projections[1]);
272    Node* if_exception = projections[1];
273    Node* if_success = projections[0];
274
275    // Insert two ToNumber() operations that both potentially throw.
276    Node* left_state = CreateFrameStateForLeftInput(frame_state);
277    Node* left_conv =
278        graph()->NewNode(javascript()->ToNumber(), left(), context(),
279                         left_state, effect(), control());
280    Node* left_success = graph()->NewNode(common()->IfSuccess(), left_conv);
281    Node* right_state = CreateFrameStateForRightInput(frame_state, left_conv);
282    Node* right_conv =
283        graph()->NewNode(javascript()->ToNumber(), right(), context(),
284                         right_state, left_conv, left_success);
285    Node* left_exception =
286        graph()->NewNode(common()->IfException(hint), left_conv, left_conv);
287    Node* right_exception =
288        graph()->NewNode(common()->IfException(hint), right_conv, right_conv);
289    NodeProperties::ReplaceControlInput(if_success, right_conv);
290    update_effect(right_conv);
291
292    // Wire conversions to existing {IfException} continuation.
293    Node* exception_merge = if_exception;
294    Node* exception_value =
295        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
296                         left_exception, right_exception, exception_merge);
297    Node* exception_effect =
298        graph()->NewNode(common()->EffectPhi(2), left_exception,
299                         right_exception, exception_merge);
300    for (Edge edge : exception_merge->use_edges()) {
301      if (NodeProperties::IsEffectEdge(edge)) edge.UpdateTo(exception_effect);
302      if (NodeProperties::IsValueEdge(edge)) edge.UpdateTo(exception_value);
303    }
304    NodeProperties::RemoveType(exception_merge);
305    exception_merge->ReplaceInput(0, left_exception);
306    exception_merge->ReplaceInput(1, right_exception);
307    NodeProperties::ChangeOp(exception_merge, common()->Merge(2));
308
309    *left_result = left_conv;
310    *right_result = right_conv;
311  }
312
313  Node* ConvertToUI32(Node* node, Signedness signedness) {
314    // Avoid introducing too many eager NumberToXXnt32() operations.
315    Type* type = NodeProperties::GetType(node);
316    if (signedness == kSigned) {
317      if (!type->Is(Type::Signed32())) {
318        node = graph()->NewNode(simplified()->NumberToInt32(), node);
319      }
320    } else {
321      DCHECK_EQ(kUnsigned, signedness);
322      if (!type->Is(Type::Unsigned32())) {
323        node = graph()->NewNode(simplified()->NumberToUint32(), node);
324      }
325    }
326    return node;
327  }
328
329  void update_effect(Node* effect) {
330    NodeProperties::ReplaceEffectInput(node_, effect);
331  }
332};
333
334
335// TODO(turbofan): js-typed-lowering improvements possible
336// - immediately put in type bounds for all new nodes
337// - relax effects from generic but not-side-effecting operations
338
339
340JSTypedLowering::JSTypedLowering(Editor* editor,
341                                 CompilationDependencies* dependencies,
342                                 Flags flags, JSGraph* jsgraph, Zone* zone)
343    : AdvancedReducer(editor),
344      dependencies_(dependencies),
345      flags_(flags),
346      jsgraph_(jsgraph),
347      true_type_(Type::Constant(factory()->true_value(), graph()->zone())),
348      false_type_(Type::Constant(factory()->false_value(), graph()->zone())),
349      the_hole_type_(
350          Type::Constant(factory()->the_hole_value(), graph()->zone())),
351      type_cache_(TypeCache::Get()) {
352  for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
353    double min = kMinInt / (1 << k);
354    double max = kMaxInt / (1 << k);
355    shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
356  }
357}
358
359
360Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
361  if (flags() & kDisableBinaryOpReduction) return NoChange();
362
363  JSBinopReduction r(this, node);
364  if (r.BothInputsAre(Type::Number())) {
365    // JSAdd(x:number, y:number) => NumberAdd(x, y)
366    return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
367  }
368  if (r.NeitherInputCanBe(Type::StringOrReceiver())) {
369    // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
370    Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
371    r.ConvertInputsToNumber(frame_state);
372    return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
373  }
374  if (r.BothInputsAre(Type::String())) {
375    // JSAdd(x:string, y:string) => CallStub[StringAdd](x, y)
376    Callable const callable =
377        CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
378    CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
379        isolate(), graph()->zone(), callable.descriptor(), 0,
380        CallDescriptor::kNeedsFrameState, node->op()->properties());
381    DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op()));
382    node->RemoveInput(NodeProperties::FirstFrameStateIndex(node) + 1);
383    node->InsertInput(graph()->zone(), 0,
384                      jsgraph()->HeapConstant(callable.code()));
385    NodeProperties::ChangeOp(node, common()->Call(desc));
386    return Changed(node);
387  }
388  return NoChange();
389}
390
391
392Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
393  if (flags() & kDisableBinaryOpReduction) return NoChange();
394
395  JSBinopReduction r(this, node);
396  if (r.BothInputsAre(Type::Number())) {
397    // JSModulus(x:number, x:number) => NumberModulus(x, y)
398    return r.ChangeToPureOperator(simplified()->NumberModulus(),
399                                  Type::Number());
400  }
401  return NoChange();
402}
403
404
405Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
406                                             const Operator* numberOp) {
407  if (flags() & kDisableBinaryOpReduction) return NoChange();
408
409  JSBinopReduction r(this, node);
410  if (numberOp == simplified()->NumberModulus()) {
411    if (r.BothInputsAre(Type::Number())) {
412      return r.ChangeToPureOperator(numberOp, Type::Number());
413    }
414    return NoChange();
415  }
416  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
417  r.ConvertInputsToNumber(frame_state);
418  return r.ChangeToPureOperator(numberOp, Type::Number());
419}
420
421
422Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
423  if (flags() & kDisableBinaryOpReduction) return NoChange();
424
425  JSBinopReduction r(this, node);
426  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
427  r.ConvertInputsToNumber(frame_state);
428  r.ConvertInputsToUI32(kSigned, kSigned);
429  return r.ChangeToPureOperator(intOp, Type::Integral32());
430}
431
432
433Reduction JSTypedLowering::ReduceUI32Shift(Node* node,
434                                           Signedness left_signedness,
435                                           const Operator* shift_op) {
436  if (flags() & kDisableBinaryOpReduction) return NoChange();
437
438  JSBinopReduction r(this, node);
439  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
440  r.ConvertInputsToNumber(frame_state);
441  r.ConvertInputsToUI32(left_signedness, kUnsigned);
442  return r.ChangeToPureOperator(shift_op);
443}
444
445
446Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
447  if (flags() & kDisableBinaryOpReduction) return NoChange();
448
449  JSBinopReduction r(this, node);
450  if (r.BothInputsAre(Type::String())) {
451    // If both inputs are definitely strings, perform a string comparison.
452    const Operator* stringOp;
453    switch (node->opcode()) {
454      case IrOpcode::kJSLessThan:
455        stringOp = simplified()->StringLessThan();
456        break;
457      case IrOpcode::kJSGreaterThan:
458        stringOp = simplified()->StringLessThan();
459        r.SwapInputs();  // a > b => b < a
460        break;
461      case IrOpcode::kJSLessThanOrEqual:
462        stringOp = simplified()->StringLessThanOrEqual();
463        break;
464      case IrOpcode::kJSGreaterThanOrEqual:
465        stringOp = simplified()->StringLessThanOrEqual();
466        r.SwapInputs();  // a >= b => b <= a
467        break;
468      default:
469        return NoChange();
470    }
471    r.ChangeToStringComparisonOperator(stringOp);
472    return Changed(node);
473  }
474  if (r.OneInputCannotBe(Type::StringOrReceiver())) {
475    const Operator* less_than;
476    const Operator* less_than_or_equal;
477    if (r.BothInputsAre(Type::Unsigned32())) {
478      less_than = machine()->Uint32LessThan();
479      less_than_or_equal = machine()->Uint32LessThanOrEqual();
480    } else if (r.BothInputsAre(Type::Signed32())) {
481      less_than = machine()->Int32LessThan();
482      less_than_or_equal = machine()->Int32LessThanOrEqual();
483    } else {
484      // TODO(turbofan): mixed signed/unsigned int32 comparisons.
485      Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
486      r.ConvertInputsToNumber(frame_state);
487      less_than = simplified()->NumberLessThan();
488      less_than_or_equal = simplified()->NumberLessThanOrEqual();
489    }
490    const Operator* comparison;
491    switch (node->opcode()) {
492      case IrOpcode::kJSLessThan:
493        comparison = less_than;
494        break;
495      case IrOpcode::kJSGreaterThan:
496        comparison = less_than;
497        r.SwapInputs();  // a > b => b < a
498        break;
499      case IrOpcode::kJSLessThanOrEqual:
500        comparison = less_than_or_equal;
501        break;
502      case IrOpcode::kJSGreaterThanOrEqual:
503        comparison = less_than_or_equal;
504        r.SwapInputs();  // a >= b => b <= a
505        break;
506      default:
507        return NoChange();
508    }
509    return r.ChangeToPureOperator(comparison);
510  }
511  // TODO(turbofan): relax/remove effects of this operator in other cases.
512  return NoChange();  // Keep a generic comparison.
513}
514
515
516Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
517  if (flags() & kDisableBinaryOpReduction) return NoChange();
518
519  JSBinopReduction r(this, node);
520
521  if (r.BothInputsAre(Type::Number())) {
522    return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
523  }
524  if (r.BothInputsAre(Type::String())) {
525    return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
526                                              invert);
527  }
528  if (r.BothInputsAre(Type::Boolean())) {
529    return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
530                                  invert);
531  }
532  if (r.BothInputsAre(Type::Receiver())) {
533    return r.ChangeToPureOperator(
534        simplified()->ReferenceEqual(Type::Receiver()), invert);
535  }
536  if (r.OneInputIs(Type::NullOrUndefined())) {
537    Callable const callable = CodeFactory::CompareNilIC(isolate(), kNullValue);
538    CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
539        isolate(), graph()->zone(), callable.descriptor(), 0,
540        CallDescriptor::kNeedsFrameState, node->op()->properties());
541    node->RemoveInput(r.LeftInputIs(Type::NullOrUndefined()) ? 0 : 1);
542    node->InsertInput(graph()->zone(), 0,
543                      jsgraph()->HeapConstant(callable.code()));
544    NodeProperties::ChangeOp(node, common()->Call(desc));
545    if (invert) {
546      // Insert an boolean not to invert the value.
547      Node* value = graph()->NewNode(simplified()->BooleanNot(), node);
548      node->ReplaceUses(value);
549      // Note: ReplaceUses() smashes all uses, so smash it back here.
550      value->ReplaceInput(0, node);
551      return Replace(value);
552    }
553    return Changed(node);
554  }
555  return NoChange();
556}
557
558
559Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
560  if (flags() & kDisableBinaryOpReduction) return NoChange();
561
562  JSBinopReduction r(this, node);
563  if (r.left() == r.right()) {
564    // x === x is always true if x != NaN
565    if (!r.left_type()->Maybe(Type::NaN())) {
566      Node* replacement = jsgraph()->BooleanConstant(!invert);
567      ReplaceWithValue(node, replacement);
568      return Replace(replacement);
569    }
570  }
571  if (r.OneInputCannotBe(Type::NumberOrString())) {
572    // For values with canonical representation (i.e. not string nor number) an
573    // empty type intersection means the values cannot be strictly equal.
574    if (!r.left_type()->Maybe(r.right_type())) {
575      Node* replacement = jsgraph()->BooleanConstant(invert);
576      ReplaceWithValue(node, replacement);
577      return Replace(replacement);
578    }
579  }
580  if (r.OneInputIs(the_hole_type_)) {
581    return r.ChangeToPureOperator(simplified()->ReferenceEqual(the_hole_type_),
582                                  invert);
583  }
584  if (r.OneInputIs(Type::Undefined())) {
585    return r.ChangeToPureOperator(
586        simplified()->ReferenceEqual(Type::Undefined()), invert);
587  }
588  if (r.OneInputIs(Type::Null())) {
589    return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()),
590                                  invert);
591  }
592  if (r.OneInputIs(Type::Boolean())) {
593    return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
594                                  invert);
595  }
596  if (r.OneInputIs(Type::Object())) {
597    return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Object()),
598                                  invert);
599  }
600  if (r.OneInputIs(Type::Receiver())) {
601    return r.ChangeToPureOperator(
602        simplified()->ReferenceEqual(Type::Receiver()), invert);
603  }
604  if (r.BothInputsAre(Type::Unique())) {
605    return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()),
606                                  invert);
607  }
608  if (r.BothInputsAre(Type::String())) {
609    return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
610                                              invert);
611  }
612  if (r.BothInputsAre(Type::Number())) {
613    return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
614  }
615  // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
616  return NoChange();
617}
618
619
620Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
621  Node* const input = node->InputAt(0);
622  Type* const input_type = NodeProperties::GetType(input);
623  Node* const effect = NodeProperties::GetEffectInput(node);
624  if (input_type->Is(Type::Boolean())) {
625    // JSToBoolean(x:boolean) => x
626    ReplaceWithValue(node, input, effect);
627    return Replace(input);
628  } else if (input_type->Is(Type::OrderedNumber())) {
629    // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0))
630    RelaxEffectsAndControls(node);
631    node->ReplaceInput(0, graph()->NewNode(simplified()->NumberEqual(), input,
632                                           jsgraph()->ZeroConstant()));
633    node->TrimInputCount(1);
634    NodeProperties::ChangeOp(node, simplified()->BooleanNot());
635    return Changed(node);
636  } else if (input_type->Is(Type::String())) {
637    // JSToBoolean(x:string) => NumberLessThan(#0,x.length)
638    FieldAccess const access = AccessBuilder::ForStringLength();
639    Node* length = graph()->NewNode(simplified()->LoadField(access), input,
640                                    effect, graph()->start());
641    ReplaceWithValue(node, node, length);
642    node->ReplaceInput(0, jsgraph()->ZeroConstant());
643    node->ReplaceInput(1, length);
644    node->TrimInputCount(2);
645    NodeProperties::ChangeOp(node, simplified()->NumberLessThan());
646    return Changed(node);
647  }
648  return NoChange();
649}
650
651
652Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
653  if (input->opcode() == IrOpcode::kJSToNumber) {
654    // Recursively try to reduce the input first.
655    Reduction result = ReduceJSToNumber(input);
656    if (result.Changed()) return result;
657    return Changed(input);  // JSToNumber(JSToNumber(x)) => JSToNumber(x)
658  }
659  // Check for ToNumber truncation of signaling NaN to undefined mapping.
660  if (input->opcode() == IrOpcode::kSelect) {
661    Node* check = NodeProperties::GetValueInput(input, 0);
662    Node* vtrue = NodeProperties::GetValueInput(input, 1);
663    Type* vtrue_type = NodeProperties::GetType(vtrue);
664    Node* vfalse = NodeProperties::GetValueInput(input, 2);
665    Type* vfalse_type = NodeProperties::GetType(vfalse);
666    if (vtrue_type->Is(Type::Undefined()) && vfalse_type->Is(Type::Number())) {
667      if (check->opcode() == IrOpcode::kNumberIsHoleNaN &&
668          check->InputAt(0) == vfalse) {
669        // JSToNumber(Select(NumberIsHoleNaN(x), y:undefined, x:number)) => x
670        return Replace(vfalse);
671      }
672    }
673  }
674  // Try constant-folding of JSToNumber with constant inputs.
675  Type* input_type = NodeProperties::GetType(input);
676  if (input_type->IsConstant()) {
677    Handle<Object> input_value = input_type->AsConstant()->Value();
678    if (input_value->IsString()) {
679      return Replace(jsgraph()->Constant(
680          String::ToNumber(Handle<String>::cast(input_value))));
681    } else if (input_value->IsOddball()) {
682      return Replace(jsgraph()->Constant(
683          Oddball::ToNumber(Handle<Oddball>::cast(input_value))));
684    }
685  }
686  if (input_type->Is(Type::Number())) {
687    // JSToNumber(x:number) => x
688    return Changed(input);
689  }
690  if (input_type->Is(Type::Undefined())) {
691    // JSToNumber(undefined) => #NaN
692    return Replace(jsgraph()->NaNConstant());
693  }
694  if (input_type->Is(Type::Null())) {
695    // JSToNumber(null) => #0
696    return Replace(jsgraph()->ZeroConstant());
697  }
698  if (input_type->Is(Type::Boolean())) {
699    // JSToNumber(x:boolean) => BooleanToNumber(x)
700    return Replace(graph()->NewNode(simplified()->BooleanToNumber(), input));
701  }
702  // TODO(turbofan): js-typed-lowering of ToNumber(x:string)
703  return NoChange();
704}
705
706
707Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
708  // Try to reduce the input first.
709  Node* const input = node->InputAt(0);
710  Reduction reduction = ReduceJSToNumberInput(input);
711  if (reduction.Changed()) {
712    ReplaceWithValue(node, reduction.replacement());
713    return reduction;
714  }
715  Type* const input_type = NodeProperties::GetType(input);
716  if (input_type->Is(Type::PlainPrimitive())) {
717    if (NodeProperties::GetContextInput(node) !=
718            jsgraph()->NoContextConstant() ||
719        NodeProperties::GetEffectInput(node) != graph()->start() ||
720        NodeProperties::GetControlInput(node) != graph()->start()) {
721      // JSToNumber(x:plain-primitive,context,effect,control)
722      //   => JSToNumber(x,no-context,start,start)
723      RelaxEffectsAndControls(node);
724      NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
725      NodeProperties::ReplaceControlInput(node, graph()->start());
726      NodeProperties::ReplaceEffectInput(node, graph()->start());
727      DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
728      NodeProperties::ReplaceFrameStateInput(node, 0,
729                                             jsgraph()->EmptyFrameState());
730      return Changed(node);
731    }
732  }
733  return NoChange();
734}
735
736
737Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
738  if (input->opcode() == IrOpcode::kJSToString) {
739    // Recursively try to reduce the input first.
740    Reduction result = ReduceJSToString(input);
741    if (result.Changed()) return result;
742    return Changed(input);  // JSToString(JSToString(x)) => JSToString(x)
743  }
744  Type* input_type = NodeProperties::GetType(input);
745  if (input_type->Is(Type::String())) {
746    return Changed(input);  // JSToString(x:string) => x
747  }
748  if (input_type->Is(Type::Boolean())) {
749    return Replace(graph()->NewNode(
750        common()->Select(MachineRepresentation::kTagged), input,
751        jsgraph()->HeapConstant(factory()->true_string()),
752        jsgraph()->HeapConstant(factory()->false_string())));
753  }
754  if (input_type->Is(Type::Undefined())) {
755    return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
756  }
757  if (input_type->Is(Type::Null())) {
758    return Replace(jsgraph()->HeapConstant(factory()->null_string()));
759  }
760  // TODO(turbofan): js-typed-lowering of ToString(x:number)
761  return NoChange();
762}
763
764
765Reduction JSTypedLowering::ReduceJSToString(Node* node) {
766  // Try to reduce the input first.
767  Node* const input = node->InputAt(0);
768  Reduction reduction = ReduceJSToStringInput(input);
769  if (reduction.Changed()) {
770    ReplaceWithValue(node, reduction.replacement());
771    return reduction;
772  }
773  return NoChange();
774}
775
776
777Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
778  DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
779  Node* receiver = NodeProperties::GetValueInput(node, 0);
780  Type* receiver_type = NodeProperties::GetType(receiver);
781  Node* context = NodeProperties::GetContextInput(node);
782  Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
783  Node* effect = NodeProperties::GetEffectInput(node);
784  Node* control = NodeProperties::GetControlInput(node);
785  if (!receiver_type->Is(Type::Receiver())) {
786    // TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks.
787    if (receiver_type->Maybe(Type::NullOrUndefined()) &&
788        NodeProperties::IsExceptionalCall(node)) {
789      // ToObject throws for null or undefined inputs.
790      return NoChange();
791    }
792
793    // Check whether {receiver} is a Smi.
794    Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
795    Node* branch0 =
796        graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
797    Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
798    Node* etrue0 = effect;
799
800    Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
801    Node* efalse0 = effect;
802
803    // Determine the instance type of {receiver}.
804    Node* receiver_map = efalse0 =
805        graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
806                         receiver, efalse0, if_false0);
807    Node* receiver_instance_type = efalse0 = graph()->NewNode(
808        simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
809        receiver_map, efalse0, if_false0);
810
811    // Check whether {receiver} is a spec object.
812    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
813    Node* check1 =
814        graph()->NewNode(machine()->Uint32LessThanOrEqual(),
815                         jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
816                         receiver_instance_type);
817    Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
818                                     check1, if_false0);
819    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
820    Node* etrue1 = efalse0;
821
822    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
823    Node* efalse1 = efalse0;
824
825    // Convert {receiver} using the ToObjectStub.
826    Node* if_convert =
827        graph()->NewNode(common()->Merge(2), if_true0, if_false1);
828    Node* econvert =
829        graph()->NewNode(common()->EffectPhi(2), etrue0, efalse1, if_convert);
830    Node* rconvert;
831    {
832      Callable callable = CodeFactory::ToObject(isolate());
833      CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
834          isolate(), graph()->zone(), callable.descriptor(), 0,
835          CallDescriptor::kNeedsFrameState, node->op()->properties());
836      rconvert = econvert = graph()->NewNode(
837          common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
838          receiver, context, frame_state, econvert, if_convert);
839    }
840
841    // The {receiver} is already a spec object.
842    Node* if_done = if_true1;
843    Node* edone = etrue1;
844    Node* rdone = receiver;
845
846    control = graph()->NewNode(common()->Merge(2), if_convert, if_done);
847    effect = graph()->NewNode(common()->EffectPhi(2), econvert, edone, control);
848    receiver =
849        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
850                         rconvert, rdone, control);
851  }
852  ReplaceWithValue(node, receiver, effect, control);
853  return Changed(receiver);
854}
855
856
857Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
858  DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
859  Node* receiver = NodeProperties::GetValueInput(node, 0);
860  Type* receiver_type = NodeProperties::GetType(receiver);
861  Node* effect = NodeProperties::GetEffectInput(node);
862  Node* control = NodeProperties::GetControlInput(node);
863  Handle<Name> name = NamedAccessOf(node->op()).name();
864  // Optimize "length" property of strings.
865  if (name.is_identical_to(factory()->length_string()) &&
866      receiver_type->Is(Type::String())) {
867    Node* value = effect = graph()->NewNode(
868        simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
869        effect, control);
870    ReplaceWithValue(node, value, effect);
871    return Replace(value);
872  }
873  // Optimize "prototype" property of functions.
874  if (name.is_identical_to(factory()->prototype_string()) &&
875      receiver_type->IsConstant() &&
876      receiver_type->AsConstant()->Value()->IsJSFunction()) {
877    // TODO(turbofan): This lowering might not kick in if we ever lower
878    // the C++ accessor for "prototype" in an earlier optimization pass.
879    Handle<JSFunction> function =
880        Handle<JSFunction>::cast(receiver_type->AsConstant()->Value());
881    if (function->has_initial_map()) {
882      // We need to add a code dependency on the initial map of the {function}
883      // in order to be notified about changes to the "prototype" of {function},
884      // so it doesn't make sense to continue unless deoptimization is enabled.
885      if (!(flags() & kDeoptimizationEnabled)) return NoChange();
886      Handle<Map> initial_map(function->initial_map(), isolate());
887      dependencies()->AssumeInitialMapCantChange(initial_map);
888      Node* value =
889          jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
890      ReplaceWithValue(node, value);
891      return Replace(value);
892    }
893  }
894  return NoChange();
895}
896
897
898Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
899  Node* key = NodeProperties::GetValueInput(node, 1);
900  Node* base = NodeProperties::GetValueInput(node, 0);
901  Type* key_type = NodeProperties::GetType(key);
902  HeapObjectMatcher mbase(base);
903  if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
904    Handle<JSTypedArray> const array =
905        Handle<JSTypedArray>::cast(mbase.Value());
906    if (!array->GetBuffer()->was_neutered()) {
907      array->GetBuffer()->set_is_neuterable(false);
908      BufferAccess const access(array->type());
909      size_t const k =
910          ElementSizeLog2Of(access.machine_type().representation());
911      double const byte_length = array->byte_length()->Number();
912      CHECK_LT(k, arraysize(shifted_int32_ranges_));
913      if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
914        // JSLoadProperty(typed-array, int32)
915        Handle<FixedTypedArrayBase> elements =
916            Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
917        Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
918        Node* length = jsgraph()->Constant(byte_length);
919        Node* effect = NodeProperties::GetEffectInput(node);
920        Node* control = NodeProperties::GetControlInput(node);
921        // Check if we can avoid the bounds check.
922        if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
923          Node* load = graph()->NewNode(
924              simplified()->LoadElement(
925                  AccessBuilder::ForTypedArrayElement(array->type(), true)),
926              buffer, key, effect, control);
927          ReplaceWithValue(node, load, load);
928          return Replace(load);
929        }
930        // Compute byte offset.
931        Node* offset = Word32Shl(key, static_cast<int>(k));
932        Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer,
933                                      offset, length, effect, control);
934        ReplaceWithValue(node, load, load);
935        return Replace(load);
936      }
937    }
938  }
939  return NoChange();
940}
941
942
943Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
944  Node* key = NodeProperties::GetValueInput(node, 1);
945  Node* base = NodeProperties::GetValueInput(node, 0);
946  Node* value = NodeProperties::GetValueInput(node, 2);
947  Type* key_type = NodeProperties::GetType(key);
948  Type* value_type = NodeProperties::GetType(value);
949  HeapObjectMatcher mbase(base);
950  if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
951    Handle<JSTypedArray> const array =
952        Handle<JSTypedArray>::cast(mbase.Value());
953    if (!array->GetBuffer()->was_neutered()) {
954      array->GetBuffer()->set_is_neuterable(false);
955      BufferAccess const access(array->type());
956      size_t const k =
957          ElementSizeLog2Of(access.machine_type().representation());
958      double const byte_length = array->byte_length()->Number();
959      CHECK_LT(k, arraysize(shifted_int32_ranges_));
960      if (access.external_array_type() != kExternalUint8ClampedArray &&
961          key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
962        // JSLoadProperty(typed-array, int32)
963        Handle<FixedTypedArrayBase> elements =
964            Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
965        Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
966        Node* length = jsgraph()->Constant(byte_length);
967        Node* context = NodeProperties::GetContextInput(node);
968        Node* effect = NodeProperties::GetEffectInput(node);
969        Node* control = NodeProperties::GetControlInput(node);
970        // Convert to a number first.
971        if (!value_type->Is(Type::Number())) {
972          Reduction number_reduction = ReduceJSToNumberInput(value);
973          if (number_reduction.Changed()) {
974            value = number_reduction.replacement();
975          } else {
976            Node* frame_state_for_to_number =
977                NodeProperties::GetFrameStateInput(node, 1);
978            value = effect =
979                graph()->NewNode(javascript()->ToNumber(), value, context,
980                                 frame_state_for_to_number, effect, control);
981          }
982        }
983        // Check if we can avoid the bounds check.
984        if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
985          RelaxControls(node);
986          node->ReplaceInput(0, buffer);
987          DCHECK_EQ(key, node->InputAt(1));
988          node->ReplaceInput(2, value);
989          node->ReplaceInput(3, effect);
990          node->ReplaceInput(4, control);
991          node->TrimInputCount(5);
992          NodeProperties::ChangeOp(
993              node,
994              simplified()->StoreElement(
995                  AccessBuilder::ForTypedArrayElement(array->type(), true)));
996          return Changed(node);
997        }
998        // Compute byte offset.
999        Node* offset = Word32Shl(key, static_cast<int>(k));
1000        // Turn into a StoreBuffer operation.
1001        RelaxControls(node);
1002        node->ReplaceInput(0, buffer);
1003        node->ReplaceInput(1, offset);
1004        node->ReplaceInput(2, length);
1005        node->ReplaceInput(3, value);
1006        node->ReplaceInput(4, effect);
1007        node->ReplaceInput(5, control);
1008        node->TrimInputCount(6);
1009        NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access));
1010        return Changed(node);
1011      }
1012    }
1013  }
1014  return NoChange();
1015}
1016
1017
1018Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
1019  DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
1020  Node* const context = NodeProperties::GetContextInput(node);
1021  Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
1022
1023  // If deoptimization is disabled, we cannot optimize.
1024  if (!(flags() & kDeoptimizationEnabled) ||
1025      (flags() & kDisableBinaryOpReduction)) {
1026    return NoChange();
1027  }
1028
1029  // If we are in a try block, don't optimize since the runtime call
1030  // in the proxy case can throw.
1031  if (NodeProperties::IsExceptionalCall(node)) return NoChange();
1032
1033  JSBinopReduction r(this, node);
1034  Node* effect = r.effect();
1035  Node* control = r.control();
1036
1037  if (!r.right_type()->IsConstant() ||
1038      !r.right_type()->AsConstant()->Value()->IsJSFunction()) {
1039    return NoChange();
1040  }
1041
1042  Handle<JSFunction> function =
1043      Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value());
1044  Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1045
1046  if (!function->IsConstructor() ||
1047      function->map()->has_non_instance_prototype()) {
1048    return NoChange();
1049  }
1050
1051  JSFunction::EnsureHasInitialMap(function);
1052  DCHECK(function->has_initial_map());
1053  Handle<Map> initial_map(function->initial_map(), isolate());
1054  this->dependencies()->AssumeInitialMapCantChange(initial_map);
1055  Node* prototype =
1056      jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
1057
1058  Node* if_is_smi = nullptr;
1059  Node* e_is_smi = nullptr;
1060  // If the left hand side is an object, no smi check is needed.
1061  if (r.left_type()->Maybe(Type::TaggedSigned())) {
1062    Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
1063    Node* branch_is_smi =
1064        graph()->NewNode(common()->Branch(BranchHint::kFalse), is_smi, control);
1065    if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
1066    e_is_smi = effect;
1067    control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
1068  }
1069
1070  Node* object_map = effect =
1071      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1072                       r.left(), effect, control);
1073
1074  // Loop through the {object}s prototype chain looking for the {prototype}.
1075  Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
1076
1077  Node* loop_effect = effect =
1078      graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
1079
1080  Node* loop_object_map =
1081      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1082                       object_map, r.left(), loop);
1083
1084  // Check if the lhs needs access checks.
1085  Node* map_bit_field = effect =
1086      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMapBitField()),
1087                       loop_object_map, loop_effect, control);
1088  int is_access_check_needed_bit = 1 << Map::kIsAccessCheckNeeded;
1089  Node* is_access_check_needed_num =
1090      graph()->NewNode(simplified()->NumberBitwiseAnd(), map_bit_field,
1091                       jsgraph()->Uint32Constant(is_access_check_needed_bit));
1092  Node* is_access_check_needed =
1093      graph()->NewNode(machine()->Word32Equal(), is_access_check_needed_num,
1094                       jsgraph()->Uint32Constant(is_access_check_needed_bit));
1095
1096  Node* branch_is_access_check_needed = graph()->NewNode(
1097      common()->Branch(BranchHint::kFalse), is_access_check_needed, control);
1098  Node* if_is_access_check_needed =
1099      graph()->NewNode(common()->IfTrue(), branch_is_access_check_needed);
1100  Node* e_is_access_check_needed = effect;
1101
1102  control =
1103      graph()->NewNode(common()->IfFalse(), branch_is_access_check_needed);
1104
1105  // Check if the lhs is a proxy.
1106  Node* map_instance_type = effect = graph()->NewNode(
1107      simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
1108      loop_object_map, loop_effect, control);
1109  Node* is_proxy = graph()->NewNode(machine()->Word32Equal(), map_instance_type,
1110                                    jsgraph()->Uint32Constant(JS_PROXY_TYPE));
1111  Node* branch_is_proxy =
1112      graph()->NewNode(common()->Branch(BranchHint::kFalse), is_proxy, control);
1113  Node* if_is_proxy = graph()->NewNode(common()->IfTrue(), branch_is_proxy);
1114  Node* e_is_proxy = effect;
1115
1116
1117  Node* runtime_has_in_proto_chain = control = graph()->NewNode(
1118      common()->Merge(2), if_is_access_check_needed, if_is_proxy);
1119  effect = graph()->NewNode(common()->EffectPhi(2), e_is_access_check_needed,
1120                            e_is_proxy, control);
1121
1122  // If we need an access check or the object is a Proxy, make a runtime call
1123  // to finish the lowering.
1124  Node* bool_result_runtime_has_in_proto_chain_case = graph()->NewNode(
1125      javascript()->CallRuntime(Runtime::kHasInPrototypeChain), r.left(),
1126      prototype, context, frame_state, effect, control);
1127
1128  control = graph()->NewNode(common()->IfFalse(), branch_is_proxy);
1129
1130  Node* object_prototype = effect = graph()->NewNode(
1131      simplified()->LoadField(AccessBuilder::ForMapPrototype()),
1132      loop_object_map, loop_effect, control);
1133
1134  // Check if object prototype is equal to function prototype.
1135  Node* eq_proto =
1136      graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
1137                       object_prototype, prototype);
1138  Node* branch_eq_proto =
1139      graph()->NewNode(common()->Branch(BranchHint::kFalse), eq_proto, control);
1140  Node* if_eq_proto = graph()->NewNode(common()->IfTrue(), branch_eq_proto);
1141  Node* e_eq_proto = effect;
1142
1143  control = graph()->NewNode(common()->IfFalse(), branch_eq_proto);
1144
1145  // If not, check if object prototype is the null prototype.
1146  Node* null_proto =
1147      graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
1148                       object_prototype, jsgraph()->NullConstant());
1149  Node* branch_null_proto = graph()->NewNode(
1150      common()->Branch(BranchHint::kFalse), null_proto, control);
1151  Node* if_null_proto = graph()->NewNode(common()->IfTrue(), branch_null_proto);
1152  Node* e_null_proto = effect;
1153
1154  control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
1155  Node* load_object_map = effect =
1156      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1157                       object_prototype, effect, control);
1158  // Close the loop.
1159  loop_effect->ReplaceInput(1, effect);
1160  loop_object_map->ReplaceInput(1, load_object_map);
1161  loop->ReplaceInput(1, control);
1162
1163  control = graph()->NewNode(common()->Merge(3), runtime_has_in_proto_chain,
1164                             if_eq_proto, if_null_proto);
1165  effect = graph()->NewNode(common()->EffectPhi(3),
1166                            bool_result_runtime_has_in_proto_chain_case,
1167                            e_eq_proto, e_null_proto, control);
1168
1169  Node* result = graph()->NewNode(
1170      common()->Phi(MachineRepresentation::kTagged, 3),
1171      bool_result_runtime_has_in_proto_chain_case, jsgraph()->TrueConstant(),
1172      jsgraph()->FalseConstant(), control);
1173
1174  if (if_is_smi != nullptr) {
1175    DCHECK_NOT_NULL(e_is_smi);
1176    control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
1177    effect =
1178        graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
1179    result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1180                              jsgraph()->FalseConstant(), result, control);
1181  }
1182
1183  ReplaceWithValue(node, result, effect, control);
1184  return Changed(result);
1185}
1186
1187
1188Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
1189  DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
1190  ContextAccess const& access = ContextAccessOf(node->op());
1191  Node* effect = NodeProperties::GetEffectInput(node);
1192  Node* control = graph()->start();
1193  for (size_t i = 0; i < access.depth(); ++i) {
1194    Node* previous = effect = graph()->NewNode(
1195        simplified()->LoadField(
1196            AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
1197        NodeProperties::GetValueInput(node, 0), effect, control);
1198    node->ReplaceInput(0, previous);
1199  }
1200  node->ReplaceInput(1, effect);
1201  node->ReplaceInput(2, control);
1202  NodeProperties::ChangeOp(
1203      node,
1204      simplified()->LoadField(AccessBuilder::ForContextSlot(access.index())));
1205  return Changed(node);
1206}
1207
1208
1209Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
1210  DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
1211  ContextAccess const& access = ContextAccessOf(node->op());
1212  Node* effect = NodeProperties::GetEffectInput(node);
1213  Node* control = graph()->start();
1214  for (size_t i = 0; i < access.depth(); ++i) {
1215    Node* previous = effect = graph()->NewNode(
1216        simplified()->LoadField(
1217            AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
1218        NodeProperties::GetValueInput(node, 0), effect, control);
1219    node->ReplaceInput(0, previous);
1220  }
1221  node->RemoveInput(2);
1222  node->ReplaceInput(2, effect);
1223  NodeProperties::ChangeOp(
1224      node,
1225      simplified()->StoreField(AccessBuilder::ForContextSlot(access.index())));
1226  return Changed(node);
1227}
1228
1229
1230Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
1231  DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
1232  ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
1233  Node* receiver = NodeProperties::GetValueInput(node, 0);
1234  Type* receiver_type = NodeProperties::GetType(receiver);
1235  Node* context = NodeProperties::GetContextInput(node);
1236  Type* context_type = NodeProperties::GetType(context);
1237  Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
1238  Node* effect = NodeProperties::GetEffectInput(node);
1239  Node* control = NodeProperties::GetControlInput(node);
1240  if (!receiver_type->Is(Type::Receiver())) {
1241    if (receiver_type->Is(Type::NullOrUndefined()) ||
1242        mode == ConvertReceiverMode::kNullOrUndefined) {
1243      if (context_type->IsConstant()) {
1244        Handle<JSObject> global_proxy(
1245            Handle<Context>::cast(context_type->AsConstant()->Value())
1246                ->global_proxy(),
1247            isolate());
1248        receiver = jsgraph()->Constant(global_proxy);
1249      } else {
1250        Node* native_context = effect = graph()->NewNode(
1251            javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
1252            context, context, effect);
1253        receiver = effect = graph()->NewNode(
1254            javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
1255            native_context, native_context, effect);
1256      }
1257    } else if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
1258               mode == ConvertReceiverMode::kNotNullOrUndefined) {
1259      receiver = effect =
1260          graph()->NewNode(javascript()->ToObject(), receiver, context,
1261                           frame_state, effect, control);
1262    } else {
1263      // Check {receiver} for undefined.
1264      Node* check0 =
1265          graph()->NewNode(simplified()->ReferenceEqual(receiver_type),
1266                           receiver, jsgraph()->UndefinedConstant());
1267      Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1268                                       check0, control);
1269      Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1270      Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1271
1272      // Check {receiver} for null.
1273      Node* check1 =
1274          graph()->NewNode(simplified()->ReferenceEqual(receiver_type),
1275                           receiver, jsgraph()->NullConstant());
1276      Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1277                                       check1, if_false0);
1278      Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1279      Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1280
1281      // Convert {receiver} using ToObject.
1282      Node* if_convert = if_false1;
1283      Node* econvert = effect;
1284      Node* rconvert;
1285      {
1286        rconvert = econvert =
1287            graph()->NewNode(javascript()->ToObject(), receiver, context,
1288                             frame_state, econvert, if_convert);
1289      }
1290
1291      // Replace {receiver} with global proxy of {context}.
1292      Node* if_global =
1293          graph()->NewNode(common()->Merge(2), if_true0, if_true1);
1294      Node* eglobal = effect;
1295      Node* rglobal;
1296      {
1297        if (context_type->IsConstant()) {
1298          Handle<JSObject> global_proxy(
1299              Handle<Context>::cast(context_type->AsConstant()->Value())
1300                  ->global_proxy(),
1301              isolate());
1302          rglobal = jsgraph()->Constant(global_proxy);
1303        } else {
1304          Node* native_context = eglobal = graph()->NewNode(
1305              javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
1306              context, context, eglobal);
1307          rglobal = eglobal = graph()->NewNode(
1308              javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
1309              native_context, native_context, eglobal);
1310        }
1311      }
1312
1313      control = graph()->NewNode(common()->Merge(2), if_convert, if_global);
1314      effect =
1315          graph()->NewNode(common()->EffectPhi(2), econvert, eglobal, control);
1316      receiver =
1317          graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1318                           rconvert, rglobal, control);
1319    }
1320  }
1321  ReplaceWithValue(node, receiver, effect, control);
1322  return Changed(receiver);
1323}
1324
1325
1326Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
1327  DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
1328  CallConstructParameters const& p = CallConstructParametersOf(node->op());
1329  DCHECK_LE(2u, p.arity());
1330  int const arity = static_cast<int>(p.arity() - 2);
1331  Node* target = NodeProperties::GetValueInput(node, 0);
1332  Type* target_type = NodeProperties::GetType(target);
1333  Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
1334
1335  // Check if {target} is a known JSFunction.
1336  if (target_type->IsConstant() &&
1337      target_type->AsConstant()->Value()->IsJSFunction()) {
1338    Handle<JSFunction> function =
1339        Handle<JSFunction>::cast(target_type->AsConstant()->Value());
1340    Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1341
1342    // Remove the eager bailout frame state.
1343    NodeProperties::RemoveFrameStateInput(node, 1);
1344
1345    // Patch {node} to an indirect call via the {function}s construct stub.
1346    Callable callable(handle(shared->construct_stub(), isolate()),
1347                      ConstructStubDescriptor(isolate()));
1348    node->RemoveInput(arity + 1);
1349    node->InsertInput(graph()->zone(), 0,
1350                      jsgraph()->HeapConstant(callable.code()));
1351    node->InsertInput(graph()->zone(), 2, new_target);
1352    node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
1353    node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
1354    node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
1355    NodeProperties::ChangeOp(
1356        node, common()->Call(Linkage::GetStubCallDescriptor(
1357                  isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
1358                  CallDescriptor::kNeedsFrameState)));
1359    return Changed(node);
1360  }
1361
1362  // Check if {target} is a JSFunction.
1363  if (target_type->Is(Type::Function())) {
1364    // Remove the eager bailout frame state.
1365    NodeProperties::RemoveFrameStateInput(node, 1);
1366
1367    // Patch {node} to an indirect call via the ConstructFunction builtin.
1368    Callable callable = CodeFactory::ConstructFunction(isolate());
1369    node->RemoveInput(arity + 1);
1370    node->InsertInput(graph()->zone(), 0,
1371                      jsgraph()->HeapConstant(callable.code()));
1372    node->InsertInput(graph()->zone(), 2, new_target);
1373    node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
1374    node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
1375    NodeProperties::ChangeOp(
1376        node, common()->Call(Linkage::GetStubCallDescriptor(
1377                  isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
1378                  CallDescriptor::kNeedsFrameState)));
1379    return Changed(node);
1380  }
1381
1382  return NoChange();
1383}
1384
1385
1386Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
1387  DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
1388  CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
1389  int const arity = static_cast<int>(p.arity() - 2);
1390  ConvertReceiverMode convert_mode = p.convert_mode();
1391  Node* target = NodeProperties::GetValueInput(node, 0);
1392  Type* target_type = NodeProperties::GetType(target);
1393  Node* receiver = NodeProperties::GetValueInput(node, 1);
1394  Type* receiver_type = NodeProperties::GetType(receiver);
1395  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
1396  Node* effect = NodeProperties::GetEffectInput(node);
1397  Node* control = NodeProperties::GetControlInput(node);
1398
1399  // Try to infer receiver {convert_mode} from {receiver} type.
1400  if (receiver_type->Is(Type::NullOrUndefined())) {
1401    convert_mode = ConvertReceiverMode::kNullOrUndefined;
1402  } else if (!receiver_type->Maybe(Type::NullOrUndefined())) {
1403    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
1404  }
1405
1406  // Check if {target} is a known JSFunction.
1407  if (target_type->IsConstant() &&
1408      target_type->AsConstant()->Value()->IsJSFunction()) {
1409    Handle<JSFunction> function =
1410        Handle<JSFunction>::cast(target_type->AsConstant()->Value());
1411    Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1412
1413    // Class constructors are callable, but [[Call]] will raise an exception.
1414    // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
1415    if (IsClassConstructor(shared->kind())) return NoChange();
1416
1417    // Load the context from the {target}.
1418    Node* context = effect = graph()->NewNode(
1419        simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
1420        effect, control);
1421    NodeProperties::ReplaceContextInput(node, context);
1422
1423    // Check if we need to convert the {receiver}.
1424    if (is_sloppy(shared->language_mode()) && !shared->native() &&
1425        !receiver_type->Is(Type::Receiver())) {
1426      receiver = effect =
1427          graph()->NewNode(javascript()->ConvertReceiver(convert_mode),
1428                           receiver, context, frame_state, effect, control);
1429      NodeProperties::ReplaceValueInput(node, receiver, 1);
1430    }
1431
1432    // Update the effect dependency for the {node}.
1433    NodeProperties::ReplaceEffectInput(node, effect);
1434
1435    // Remove the eager bailout frame state.
1436    NodeProperties::RemoveFrameStateInput(node, 1);
1437
1438    // Compute flags for the call.
1439    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1440    if (p.tail_call_mode() == TailCallMode::kAllow) {
1441      flags |= CallDescriptor::kSupportsTailCalls;
1442    }
1443
1444    Node* new_target = jsgraph()->UndefinedConstant();
1445    Node* argument_count = jsgraph()->Int32Constant(arity);
1446    if (shared->internal_formal_parameter_count() == arity ||
1447        shared->internal_formal_parameter_count() ==
1448            SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
1449      // Patch {node} to a direct call.
1450      node->InsertInput(graph()->zone(), arity + 2, new_target);
1451      node->InsertInput(graph()->zone(), arity + 3, argument_count);
1452      NodeProperties::ChangeOp(node,
1453                               common()->Call(Linkage::GetJSCallDescriptor(
1454                                   graph()->zone(), false, 1 + arity, flags)));
1455    } else {
1456      // Patch {node} to an indirect call via the ArgumentsAdaptorTrampoline.
1457      Callable callable = CodeFactory::ArgumentAdaptor(isolate());
1458      node->InsertInput(graph()->zone(), 0,
1459                        jsgraph()->HeapConstant(callable.code()));
1460      node->InsertInput(graph()->zone(), 2, new_target);
1461      node->InsertInput(graph()->zone(), 3, argument_count);
1462      node->InsertInput(
1463          graph()->zone(), 4,
1464          jsgraph()->Int32Constant(shared->internal_formal_parameter_count()));
1465      NodeProperties::ChangeOp(
1466          node, common()->Call(Linkage::GetStubCallDescriptor(
1467                    isolate(), graph()->zone(), callable.descriptor(),
1468                    1 + arity, flags)));
1469    }
1470    return Changed(node);
1471  }
1472
1473  // Check if {target} is a JSFunction.
1474  if (target_type->Is(Type::Function())) {
1475    // Remove the eager bailout frame state.
1476    NodeProperties::RemoveFrameStateInput(node, 1);
1477
1478    // Compute flags for the call.
1479    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1480    if (p.tail_call_mode() == TailCallMode::kAllow) {
1481      flags |= CallDescriptor::kSupportsTailCalls;
1482    }
1483
1484    // Patch {node} to an indirect call via the CallFunction builtin.
1485    Callable callable = CodeFactory::CallFunction(isolate(), convert_mode);
1486    node->InsertInput(graph()->zone(), 0,
1487                      jsgraph()->HeapConstant(callable.code()));
1488    node->InsertInput(graph()->zone(), 2, jsgraph()->Int32Constant(arity));
1489    NodeProperties::ChangeOp(
1490        node, common()->Call(Linkage::GetStubCallDescriptor(
1491                  isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
1492                  flags)));
1493    return Changed(node);
1494  }
1495
1496  // Maybe we did at least learn something about the {receiver}.
1497  if (p.convert_mode() != convert_mode) {
1498    NodeProperties::ChangeOp(
1499        node, javascript()->CallFunction(p.arity(), p.feedback(), convert_mode,
1500                                         p.tail_call_mode()));
1501    return Changed(node);
1502  }
1503
1504  return NoChange();
1505}
1506
1507
1508Reduction JSTypedLowering::ReduceJSForInDone(Node* node) {
1509  DCHECK_EQ(IrOpcode::kJSForInDone, node->opcode());
1510  node->TrimInputCount(2);
1511  NodeProperties::ChangeOp(node, machine()->Word32Equal());
1512  return Changed(node);
1513}
1514
1515
1516Reduction JSTypedLowering::ReduceJSForInNext(Node* node) {
1517  DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode());
1518  Node* receiver = NodeProperties::GetValueInput(node, 0);
1519  Node* cache_array = NodeProperties::GetValueInput(node, 1);
1520  Node* cache_type = NodeProperties::GetValueInput(node, 2);
1521  Node* index = NodeProperties::GetValueInput(node, 3);
1522  Node* context = NodeProperties::GetContextInput(node);
1523  Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
1524  Node* effect = NodeProperties::GetEffectInput(node);
1525  Node* control = NodeProperties::GetControlInput(node);
1526
1527  // Load the next {key} from the {cache_array}.
1528  Node* key = effect = graph()->NewNode(
1529      simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
1530      cache_array, index, effect, control);
1531
1532  // Load the map of the {receiver}.
1533  Node* receiver_map = effect =
1534      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1535                       receiver, effect, control);
1536
1537  // Check if the expected map still matches that of the {receiver}.
1538  Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()),
1539                                  receiver_map, cache_type);
1540  Node* branch0 =
1541      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
1542
1543  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1544  Node* etrue0;
1545  Node* vtrue0;
1546  {
1547    // Don't need filtering since expected map still matches that of the
1548    // {receiver}.
1549    etrue0 = effect;
1550    vtrue0 = key;
1551  }
1552
1553  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1554  Node* efalse0;
1555  Node* vfalse0;
1556  {
1557    // Filter the {key} to check if it's still a valid property of the
1558    // {receiver} (does the ToName conversion implicitly).
1559    vfalse0 = efalse0 = graph()->NewNode(
1560        javascript()->CallRuntime(Runtime::kForInFilter), receiver, key,
1561        context, frame_state, effect, if_false0);
1562    if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
1563  }
1564
1565  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1566  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1567  ReplaceWithValue(node, node, effect, control);
1568  node->ReplaceInput(0, vtrue0);
1569  node->ReplaceInput(1, vfalse0);
1570  node->ReplaceInput(2, control);
1571  node->TrimInputCount(3);
1572  NodeProperties::ChangeOp(node,
1573                           common()->Phi(MachineRepresentation::kTagged, 2));
1574  return Changed(node);
1575}
1576
1577
1578Reduction JSTypedLowering::ReduceJSForInStep(Node* node) {
1579  DCHECK_EQ(IrOpcode::kJSForInStep, node->opcode());
1580  node->ReplaceInput(1, jsgraph()->Int32Constant(1));
1581  NodeProperties::ChangeOp(node, machine()->Int32Add());
1582  return Changed(node);
1583}
1584
1585
1586Reduction JSTypedLowering::ReduceSelect(Node* node) {
1587  DCHECK_EQ(IrOpcode::kSelect, node->opcode());
1588  Node* const condition = NodeProperties::GetValueInput(node, 0);
1589  Type* const condition_type = NodeProperties::GetType(condition);
1590  Node* const vtrue = NodeProperties::GetValueInput(node, 1);
1591  Type* const vtrue_type = NodeProperties::GetType(vtrue);
1592  Node* const vfalse = NodeProperties::GetValueInput(node, 2);
1593  Type* const vfalse_type = NodeProperties::GetType(vfalse);
1594  if (condition_type->Is(true_type_)) {
1595    // Select(condition:true, vtrue, vfalse) => vtrue
1596    return Replace(vtrue);
1597  }
1598  if (condition_type->Is(false_type_)) {
1599    // Select(condition:false, vtrue, vfalse) => vfalse
1600    return Replace(vfalse);
1601  }
1602  if (vtrue_type->Is(true_type_) && vfalse_type->Is(false_type_)) {
1603    // Select(condition, vtrue:true, vfalse:false) => condition
1604    return Replace(condition);
1605  }
1606  if (vtrue_type->Is(false_type_) && vfalse_type->Is(true_type_)) {
1607    // Select(condition, vtrue:false, vfalse:true) => BooleanNot(condition)
1608    node->TrimInputCount(1);
1609    NodeProperties::ChangeOp(node, simplified()->BooleanNot());
1610    return Changed(node);
1611  }
1612  return NoChange();
1613}
1614
1615
1616Reduction JSTypedLowering::Reduce(Node* node) {
1617  // Check if the output type is a singleton.  In that case we already know the
1618  // result value and can simply replace the node if it's eliminable.
1619  if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
1620      node->op()->HasProperty(Operator::kEliminatable)) {
1621    Type* upper = NodeProperties::GetType(node);
1622    if (upper->IsConstant()) {
1623      Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
1624      ReplaceWithValue(node, replacement);
1625      return Changed(replacement);
1626    } else if (upper->Is(Type::MinusZero())) {
1627      Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
1628      ReplaceWithValue(node, replacement);
1629      return Changed(replacement);
1630    } else if (upper->Is(Type::NaN())) {
1631      Node* replacement = jsgraph()->NaNConstant();
1632      ReplaceWithValue(node, replacement);
1633      return Changed(replacement);
1634    } else if (upper->Is(Type::Null())) {
1635      Node* replacement = jsgraph()->NullConstant();
1636      ReplaceWithValue(node, replacement);
1637      return Changed(replacement);
1638    } else if (upper->Is(Type::PlainNumber()) && upper->Min() == upper->Max()) {
1639      Node* replacement = jsgraph()->Constant(upper->Min());
1640      ReplaceWithValue(node, replacement);
1641      return Changed(replacement);
1642    } else if (upper->Is(Type::Undefined())) {
1643      Node* replacement = jsgraph()->UndefinedConstant();
1644      ReplaceWithValue(node, replacement);
1645      return Changed(replacement);
1646    }
1647  }
1648  switch (node->opcode()) {
1649    case IrOpcode::kJSEqual:
1650      return ReduceJSEqual(node, false);
1651    case IrOpcode::kJSNotEqual:
1652      return ReduceJSEqual(node, true);
1653    case IrOpcode::kJSStrictEqual:
1654      return ReduceJSStrictEqual(node, false);
1655    case IrOpcode::kJSStrictNotEqual:
1656      return ReduceJSStrictEqual(node, true);
1657    case IrOpcode::kJSLessThan:         // fall through
1658    case IrOpcode::kJSGreaterThan:      // fall through
1659    case IrOpcode::kJSLessThanOrEqual:  // fall through
1660    case IrOpcode::kJSGreaterThanOrEqual:
1661      return ReduceJSComparison(node);
1662    case IrOpcode::kJSBitwiseOr:
1663      return ReduceInt32Binop(node, simplified()->NumberBitwiseOr());
1664    case IrOpcode::kJSBitwiseXor:
1665      return ReduceInt32Binop(node, simplified()->NumberBitwiseXor());
1666    case IrOpcode::kJSBitwiseAnd:
1667      return ReduceInt32Binop(node, simplified()->NumberBitwiseAnd());
1668    case IrOpcode::kJSShiftLeft:
1669      return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft());
1670    case IrOpcode::kJSShiftRight:
1671      return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftRight());
1672    case IrOpcode::kJSShiftRightLogical:
1673      return ReduceUI32Shift(node, kUnsigned,
1674                             simplified()->NumberShiftRightLogical());
1675    case IrOpcode::kJSAdd:
1676      return ReduceJSAdd(node);
1677    case IrOpcode::kJSSubtract:
1678      return ReduceNumberBinop(node, simplified()->NumberSubtract());
1679    case IrOpcode::kJSMultiply:
1680      return ReduceNumberBinop(node, simplified()->NumberMultiply());
1681    case IrOpcode::kJSDivide:
1682      return ReduceNumberBinop(node, simplified()->NumberDivide());
1683    case IrOpcode::kJSModulus:
1684      return ReduceJSModulus(node);
1685    case IrOpcode::kJSToBoolean:
1686      return ReduceJSToBoolean(node);
1687    case IrOpcode::kJSToNumber:
1688      return ReduceJSToNumber(node);
1689    case IrOpcode::kJSToString:
1690      return ReduceJSToString(node);
1691    case IrOpcode::kJSToObject:
1692      return ReduceJSToObject(node);
1693    case IrOpcode::kJSLoadNamed:
1694      return ReduceJSLoadNamed(node);
1695    case IrOpcode::kJSLoadProperty:
1696      return ReduceJSLoadProperty(node);
1697    case IrOpcode::kJSStoreProperty:
1698      return ReduceJSStoreProperty(node);
1699    case IrOpcode::kJSInstanceOf:
1700      return ReduceJSInstanceOf(node);
1701    case IrOpcode::kJSLoadContext:
1702      return ReduceJSLoadContext(node);
1703    case IrOpcode::kJSStoreContext:
1704      return ReduceJSStoreContext(node);
1705    case IrOpcode::kJSConvertReceiver:
1706      return ReduceJSConvertReceiver(node);
1707    case IrOpcode::kJSCallConstruct:
1708      return ReduceJSCallConstruct(node);
1709    case IrOpcode::kJSCallFunction:
1710      return ReduceJSCallFunction(node);
1711    case IrOpcode::kJSForInDone:
1712      return ReduceJSForInDone(node);
1713    case IrOpcode::kJSForInNext:
1714      return ReduceJSForInNext(node);
1715    case IrOpcode::kJSForInStep:
1716      return ReduceJSForInStep(node);
1717    case IrOpcode::kSelect:
1718      return ReduceSelect(node);
1719    default:
1720      break;
1721  }
1722  return NoChange();
1723}
1724
1725
1726Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
1727  if (rhs == 0) return lhs;
1728  return graph()->NewNode(machine()->Word32Shl(), lhs,
1729                          jsgraph()->Int32Constant(rhs));
1730}
1731
1732
1733Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
1734
1735
1736Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
1737
1738
1739Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); }
1740
1741
1742JSOperatorBuilder* JSTypedLowering::javascript() const {
1743  return jsgraph()->javascript();
1744}
1745
1746
1747CommonOperatorBuilder* JSTypedLowering::common() const {
1748  return jsgraph()->common();
1749}
1750
1751
1752SimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
1753  return jsgraph()->simplified();
1754}
1755
1756
1757MachineOperatorBuilder* JSTypedLowering::machine() const {
1758  return jsgraph()->machine();
1759}
1760
1761
1762CompilationDependencies* JSTypedLowering::dependencies() const {
1763  return dependencies_;
1764}
1765
1766}  // namespace compiler
1767}  // namespace internal
1768}  // namespace v8
1769