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