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