5 #include "src/compiler/js-typed-lowering.h" 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" 34 : lowering_(lowering), node_(node) {}
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;
42 case CompareOperationHint::kNumber:
43 *hint = NumberOperationHint::kNumber;
45 case CompareOperationHint::kNumberOrOddball:
46 *hint = NumberOperationHint::kNumberOrOddball;
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:
61 bool IsInternalizedStringCompareOperation() {
62 DCHECK_EQ(1, node_->op()->EffectOutputCount());
63 return (CompareOperationHintOf(node_->op()) ==
64 CompareOperationHint::kInternalizedString) &&
65 BothInputsMaybe(Type::InternalizedString());
68 bool IsReceiverCompareOperation() {
69 DCHECK_EQ(1, node_->op()->EffectOutputCount());
70 return (CompareOperationHintOf(node_->op()) ==
71 CompareOperationHint::kReceiver) &&
72 BothInputsMaybe(Type::Receiver());
75 bool IsReceiverOrNullOrUndefinedCompareOperation() {
76 DCHECK_EQ(1, node_->op()->EffectOutputCount());
77 return (CompareOperationHintOf(node_->op()) ==
78 CompareOperationHint::kReceiverOrNullOrUndefined) &&
79 BothInputsMaybe(Type::ReceiverOrNullOrUndefined());
82 bool IsStringCompareOperation() {
83 DCHECK_EQ(1, node_->op()->EffectOutputCount());
84 return (CompareOperationHintOf(node_->op()) ==
85 CompareOperationHint::kString) &&
86 BothInputsMaybe(Type::String());
89 bool IsSymbolCompareOperation() {
90 DCHECK_EQ(1, node_->op()->EffectOutputCount());
91 return (CompareOperationHintOf(node_->op()) ==
92 CompareOperationHint::kSymbol) &&
93 BothInputsMaybe(Type::Symbol());
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) {
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;
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) {
118 return left_string.IsSeqString() || left_string.IsExternalString();
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);
134 void CheckLeftInputToReceiverOrNullOrUndefined() {
136 graph()->NewNode(simplified()->CheckReceiverOrNullOrUndefined(), left(),
137 effect(), control());
138 node_->ReplaceInput(0, left_input);
139 update_effect(left_input);
145 void CheckInputsToReceiver() {
146 if (!left_type().Is(Type::Receiver())) {
147 CheckLeftInputToReceiver();
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);
160 void CheckInputsToReceiverOrNullOrUndefined() {
161 if (!left_type().Is(Type::ReceiverOrNullOrUndefined())) {
162 CheckLeftInputToReceiverOrNullOrUndefined();
164 if (!right_type().Is(Type::ReceiverOrNullOrUndefined())) {
166 graph()->NewNode(simplified()->CheckReceiverOrNullOrUndefined(),
167 right(), effect(), control());
168 node_->ReplaceInput(1, right_input);
169 update_effect(right_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);
184 void CheckInputsToSymbol() {
185 if (!left_type().Is(Type::Symbol())) {
186 CheckLeftInputToSymbol();
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);
199 void CheckInputsToString() {
200 if (!left_type().Is(Type::String())) {
202 graph()->NewNode(simplified()->CheckString(
VectorSlotPair()), left(),
203 effect(), control());
204 node_->ReplaceInput(0, left_input);
205 update_effect(left_input);
207 if (!right_type().Is(Type::String())) {
209 graph()->NewNode(simplified()->CheckString(
VectorSlotPair()), right(),
210 effect(), control());
211 node_->ReplaceInput(1, right_input);
212 update_effect(right_input);
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);
226 if (!right_type().Is(Type::UniqueName())) {
228 graph()->NewNode(simplified()->CheckInternalizedString(), right(),
229 effect(), control());
230 node_->ReplaceInput(1, right_input);
231 update_effect(right_input);
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()));
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));
251 node_->ReplaceInput(0, r);
252 node_->ReplaceInput(1, l);
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());
264 if (node_->op()->EffectInputCount() > 0) {
265 lowering_->RelaxEffectsAndControls(node_);
268 NodeProperties::RemoveNonValueInputs(node_);
270 NodeProperties::ChangeOp(node_, op);
274 Type node_type = NodeProperties::GetType(node_);
275 NodeProperties::SetType(node_, Type::Intersect(node_type,
type, zone()));
277 return lowering_->Changed(node_);
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());
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());
296 lowering_->RelaxControls(node_);
299 if (OperatorProperties::HasFrameStateInput(node_->op())) {
300 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
302 node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
304 NodeProperties::ChangeOp(node_, op);
307 Type node_type = NodeProperties::GetType(node_);
308 NodeProperties::SetType(node_,
309 Type::Intersect(node_type, upper_bound, zone()));
311 return lowering_->Changed(node_);
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();
346 bool LeftInputIs(
Type t) {
return left_type().Is(t); }
348 bool RightInputIs(
Type t) {
return right_type().Is(t); }
350 bool OneInputIs(
Type t) {
return LeftInputIs(t) || RightInputIs(t); }
352 bool BothInputsAre(
Type t) {
return LeftInputIs(t) && RightInputIs(t); }
354 bool BothInputsMaybe(
Type t) {
355 return left_type().Maybe(t) && right_type().Maybe(t);
358 bool OneInputCannotBe(
Type t) {
359 return !left_type().Maybe(t) || !right_type().Maybe(t);
362 bool NeitherInputCanBe(
Type t) {
363 return !left_type().Maybe(t) && !right_type().Maybe(t);
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_); }
376 Graph* graph()
const {
return lowering_->graph(); }
377 JSGraph* jsgraph() {
return lowering_->jsgraph(); }
378 Isolate* isolate() {
return jsgraph()->isolate(); }
381 Zone* zone()
const {
return graph()->zone(); }
387 Node* ConvertPlainPrimitiveToNumber(
Node* node) {
388 DCHECK(NodeProperties::GetType(node).Is(Type::PlainPrimitive()));
390 Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
391 if (reduction.Changed())
return reduction.replacement();
392 if (NodeProperties::GetType(node).Is(Type::Number())) {
395 return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
398 Node* ConvertToUI32(
Node* node, Signedness signedness) {
400 Type type = NodeProperties::GetType(node);
401 if (signedness == kSigned) {
402 if (!
type.Is(Type::Signed32())) {
403 node = graph()->NewNode(simplified()->NumberToInt32(), node);
406 DCHECK_EQ(kUnsigned, signedness);
407 if (!
type.Is(Type::Unsigned32())) {
408 node = graph()->NewNode(simplified()->NumberToUint32(), node);
414 void update_effect(
Node* effect) {
415 NodeProperties::ReplaceEffectInput(node_, effect);
424 JSTypedLowering::JSTypedLowering(Editor* editor,
JSGraph* jsgraph,
429 empty_string_type_(
Type::HeapConstant(broker, factory()->empty_string(),
431 pointer_comparable_type_(
433 Type::Union(
Type::SymbolOrReceiver(), empty_string_type_,
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())) {
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());
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())) {
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());
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())) {
473 node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant());
474 BinaryOperationHint hint = BinaryOperationHint::kAny;
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());
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())) {
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());
498 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
499 JSBinopReduction r(
this, node);
500 if (r.BothInputsAre(Type::Number())) {
502 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
504 if (r.BothInputsAre(Type::PlainPrimitive()) &&
505 r.NeitherInputCanBe(Type::StringOrReceiver())) {
507 r.ConvertInputsToNumber();
508 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
512 if (r.LeftInputIs(Type::String())) {
514 Reduction
const reduction = ReduceJSToStringInput(r.right());
515 if (reduction.Changed()) {
516 NodeProperties::ReplaceValueInput(node, reduction.replacement(), 1);
518 }
else if (r.RightInputIs(Type::String())) {
520 Reduction
const reduction = ReduceJSToStringInput(r.left());
521 if (reduction.Changed()) {
522 NodeProperties::ReplaceValueInput(node, reduction.replacement(), 0);
527 if (BinaryOperationHintOf(node->op()) == BinaryOperationHint::kString) {
528 r.CheckInputsToString();
534 if (r.BothInputsAre(Type::Primitive())) {
535 if (r.LeftInputIs(empty_string_type_)) {
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_)) {
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);
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);
559 graph()->NewNode(simplified()->StringLength(), r.left());
561 graph()->NewNode(simplified()->StringLength(), r.right());
563 graph()->NewNode(simplified()->NumberAdd(), left_length, right_length);
565 CellRef string_length_protector(broker(),
566 factory()->string_length_protector());
567 if (string_length_protector.value().AsSmi() == Isolate::kProtectorValid) {
573 length = effect = graph()->NewNode(
574 simplified()->CheckBounds(VectorSlotPair()), length,
575 jsgraph()->Constant(String::kMaxLength + 1), effect, control);
579 graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
580 jsgraph()->Constant(String::kMaxLength));
582 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
583 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
584 Node* efalse = effect;
587 Node* vfalse = efalse = if_false = graph()->NewNode(
588 javascript()->CallRuntime(Runtime::kThrowInvalidStringLength),
589 context, frame_state, efalse, if_false);
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);
604 if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
606 NodeProperties::MergeControlToEnd(graph(), common(), if_false);
607 Revisit(graph()->end());
609 control = graph()->NewNode(common()->IfTrue(), branch);
611 graph()->NewNode(common()->TypeGuard(type_cache_.kStringLengthType),
612 length, effect, control);
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);
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;
635 Operator::Properties properties = node->op()->properties();
636 if (r.NeitherInputCanBe(Type::Receiver())) {
640 properties = Operator::kNoWrite | Operator::kNoDeopt;
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);
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());
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());
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
690 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
691 JSBinopReduction r(
this, node);
692 if (r.BothInputsAre(Type::String())) {
694 const Operator* stringOp;
695 switch (node->opcode()) {
696 case IrOpcode::kJSLessThan:
697 stringOp = simplified()->StringLessThan();
699 case IrOpcode::kJSGreaterThan:
700 stringOp = simplified()->StringLessThan();
703 case IrOpcode::kJSLessThanOrEqual:
704 stringOp = simplified()->StringLessThanOrEqual();
706 case IrOpcode::kJSGreaterThanOrEqual:
707 stringOp = simplified()->StringLessThanOrEqual();
713 r.ChangeToPureOperator(stringOp);
714 return Changed(node);
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();
735 const Operator* comparison;
736 switch (node->opcode()) {
737 case IrOpcode::kJSLessThan:
738 comparison = less_than;
740 case IrOpcode::kJSGreaterThan:
741 comparison = less_than;
744 case IrOpcode::kJSLessThanOrEqual:
745 comparison = less_than_or_equal;
747 case IrOpcode::kJSGreaterThanOrEqual:
748 comparison = less_than_or_equal;
754 return r.ChangeToPureOperator(comparison);
757 Reduction JSTypedLowering::ReduceJSEqual(Node* node) {
758 JSBinopReduction r(
this, node);
760 if (r.BothInputsAre(Type::UniqueName())) {
761 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
763 if (r.IsInternalizedStringCompareOperation()) {
764 r.CheckInputsToInternalizedString();
765 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
767 if (r.BothInputsAre(Type::String())) {
768 return r.ChangeToPureOperator(simplified()->StringEqual());
770 if (r.BothInputsAre(Type::Boolean())) {
771 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
773 if (r.BothInputsAre(Type::Receiver())) {
774 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
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);
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()) {
794 r.CheckInputsToReceiverOrNullOrUndefined();
799 if (r.OneInputIs(Type::DetectableReceiver())) {
800 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
810 Node* left = r.left();
811 Node* right = r.right();
812 Node* effect = r.effect();
813 Node* control = r.control();
815 Node* check = graph()->NewNode(simplified()->ObjectIsUndetectable(), left);
817 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
819 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
820 Node* vtrue = graph()->NewNode(simplified()->ObjectIsUndetectable(), right);
822 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
824 graph()->NewNode(simplified()->ReferenceEqual(), left, right);
826 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
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());
842 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node) {
843 JSBinopReduction r(
this, node);
844 if (r.left() == r.right()) {
846 Node* replacement = graph()->NewNode(
847 simplified()->BooleanNot(),
848 graph()->NewNode(simplified()->ObjectIsNaN(), r.left()));
849 ReplaceWithValue(node, replacement);
850 return Replace(replacement);
852 if (r.OneInputCannotBe(Type::NumericOrString())) {
856 if (!r.left_type().Maybe(r.right_type())) {
857 Node* replacement = jsgraph()->FalseConstant();
858 ReplaceWithValue(node, replacement);
859 return Replace(replacement);
863 if (r.BothInputsAre(Type::Unique())) {
864 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
866 if (r.OneInputIs(pointer_comparable_type_)) {
867 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
869 if (r.IsInternalizedStringCompareOperation()) {
870 r.CheckInputsToInternalizedString();
871 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
873 if (r.BothInputsAre(Type::String())) {
874 return r.ChangeToPureOperator(simplified()->StringEqual());
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()) {
890 r.CheckLeftInputToReceiver();
891 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
892 }
else if (r.IsReceiverOrNullOrUndefinedCompareOperation()) {
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()) {
906 r.CheckLeftInputToSymbol();
907 return r.ChangeToPureOperator(simplified()->ReferenceEqual());
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())) {
917 ReplaceWithValue(node, input);
918 return Replace(input);
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);
932 if (input_type.Min() <= 0.0) {
933 input = graph()->NewNode(simplified()->NumberMax(),
934 jsgraph()->ZeroConstant(), input);
936 if (input_type.Max() > kMaxSafeInteger) {
937 input = graph()->NewNode(simplified()->NumberMin(),
938 jsgraph()->Constant(kMaxSafeInteger), input);
941 ReplaceWithValue(node, input);
942 return Replace(input);
947 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
949 Type input_type = NodeProperties::GetType(input);
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();
956 ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(number, input_value.ToNumber());
957 return Replace(jsgraph()->Constant(number));
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()));
966 if (input_type.Is(Type::Number())) {
968 return Changed(input);
970 if (input_type.Is(Type::Undefined())) {
972 return Replace(jsgraph()->NaNConstant());
974 if (input_type.Is(Type::Null())) {
976 return Replace(jsgraph()->ZeroConstant());
981 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
983 Node*
const input = node->InputAt(0);
984 Reduction reduction = ReduceJSToNumberInput(input);
985 if (reduction.Changed()) {
986 ReplaceWithValue(node, reduction.replacement());
989 Type const input_type = NodeProperties::GetType(input);
990 if (input_type.Is(Type::PlainPrimitive())) {
991 RelaxEffectsAndControls(node);
992 node->TrimInputCount(1);
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);
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())) {
1008 NodeProperties::ChangeOp(node, javascript()->ToNumber());
1009 Reduction
const reduction = ReduceJSToNumber(node);
1010 return reduction.Changed() ? reduction : Changed(node);
1015 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
1016 if (input->opcode() == IrOpcode::kJSToString) {
1018 Reduction result = ReduceJSToString(input);
1019 if (result.Changed())
return result;
1020 return Changed(input);
1022 Type input_type = NodeProperties::GetType(input);
1023 if (input_type.Is(Type::String())) {
1024 return Changed(input);
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())));
1032 if (input_type.Is(Type::Undefined())) {
1033 return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
1035 if (input_type.Is(Type::Null())) {
1036 return Replace(jsgraph()->HeapConstant(factory()->null_string()));
1038 if (input_type.Is(Type::NaN())) {
1039 return Replace(jsgraph()->HeapConstant(factory()->NaN_string()));
1041 if (input_type.Is(Type::Number())) {
1042 return Replace(graph()->NewNode(simplified()->NumberToString(), input));
1047 Reduction JSTypedLowering::ReduceJSToString(Node* node) {
1048 DCHECK_EQ(IrOpcode::kJSToString, node->opcode());
1050 Node*
const input = node->InputAt(0);
1051 Reduction reduction = ReduceJSToStringInput(input);
1052 if (reduction.Changed()) {
1053 ReplaceWithValue(node, reduction.replacement());
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);
1073 Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
1075 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1077 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1078 Node* etrue = effect;
1079 Node* rtrue = receiver;
1081 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1082 Node* efalse = effect;
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);
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);
1109 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1110 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
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);
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());
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);
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);
1150 if (value_type.Is(Type::Primitive())) {
1151 Node* value = jsgraph()->FalseConstant();
1152 ReplaceWithValue(node, value, effect, control);
1153 return Replace(value);
1156 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
1158 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
1160 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1161 Node* etrue0 = effect;
1162 Node* vtrue0 = jsgraph()->FalseConstant();
1164 control = graph()->NewNode(common()->IfFalse(), branch0);
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());
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,
1186 Node* check1 = graph()->NewNode(
1187 simplified()->NumberLessThanOrEqual(), value_instance_type,
1188 jsgraph()->Constant(LAST_SPECIAL_RECEIVER_TYPE));
1190 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
1192 control = graph()->NewNode(common()->IfFalse(), branch1);
1194 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1195 Node* etrue1 = effect;
1200 graph()->NewNode(simplified()->NumberLessThan(), value_instance_type,
1201 jsgraph()->Constant(FIRST_JS_RECEIVER_TYPE));
1203 graph()->NewNode(common()->Branch(BranchHint::kTrue), check10, if_true1);
1206 if_true1 = graph()->NewNode(common()->IfTrue(), branch10);
1207 vtrue1 = jsgraph()->FalseConstant();
1209 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10);
1210 Node* efalse1 = etrue1;
1214 vfalse1 = efalse1 = if_false1 = graph()->NewNode(
1215 javascript()->CallRuntime(Runtime::kHasInPrototypeChain), value,
1216 prototype, context, frame_state, efalse1, if_false1);
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);
1230 Node* value_prototype = effect = graph()->NewNode(
1231 simplified()->LoadField(AccessBuilder::ForMapPrototype()), value_map,
1235 Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(),
1236 value_prototype, jsgraph()->NullConstant());
1237 Node* branch2 = graph()->NewNode(common()->Branch(), check2, control);
1239 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1240 Node* etrue2 = effect;
1241 Node* vtrue2 = jsgraph()->FalseConstant();
1243 control = graph()->NewNode(common()->IfFalse(), branch2);
1246 Node* check3 = graph()->NewNode(simplified()->ReferenceEqual(),
1247 value_prototype, prototype);
1248 Node* branch3 = graph()->NewNode(common()->Branch(), check3, control);
1250 Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
1251 Node* etrue3 = effect;
1252 Node* vtrue3 = jsgraph()->TrueConstant();
1254 control = graph()->NewNode(common()->IfFalse(), branch3);
1257 vloop->ReplaceInput(1, value_prototype);
1258 eloop->ReplaceInput(1, effect);
1259 loop->ReplaceInput(1, control);
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);
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);
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);
1289 if (!constructor_type.Maybe(Type::Callable())) {
1290 Node* value = jsgraph()->FalseConstant();
1291 ReplaceWithValue(node, value);
1292 return Replace(value);
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);
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);
1320 node->ReplaceInput(0, context);
1321 node->ReplaceInput(1, effect);
1322 node->AppendInput(jsgraph()->zone(), control);
1323 NodeProperties::ChangeOp(
1325 simplified()->LoadField(AccessBuilder::ForContextSlot(access.index())));
1326 return Changed(node);
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);
1342 node->ReplaceInput(0, context);
1343 node->ReplaceInput(1, value);
1344 node->ReplaceInput(2, effect);
1345 NodeProperties::ChangeOp(
1347 simplified()->StoreField(AccessBuilder::ForContextSlot(access.index())));
1348 return Changed(node);
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);
1357 int32_t cell_index = OpParameter<int32_t>(node->op());
1358 Node* module = NodeProperties::GetValueInput(node, 0);
1359 Type module_type = NodeProperties::GetType(module);
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);
1367 FieldAccess field_access;
1369 if (ModuleDescriptor::GetCellIndexKind(cell_index) ==
1370 ModuleDescriptor::kExport) {
1371 field_access = AccessBuilder::ForModuleRegularExports();
1372 index = cell_index - 1;
1374 DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
1375 ModuleDescriptor::kImport);
1376 field_access = AccessBuilder::ForModuleRegularImports();
1377 index = -cell_index - 1;
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,
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);
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);
1397 ReplaceWithValue(node, value, effect, control);
1398 return Changed(value);
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);
1407 ModuleDescriptor::GetCellIndexKind(OpParameter<int32_t>(node->op())),
1408 ModuleDescriptor::kExport);
1410 Node* cell = BuildGetModuleCell(node);
1411 if (cell->op()->EffectOutputCount() > 0) effect = cell;
1413 graph()->NewNode(simplified()->StoreField(AccessBuilder::ForCellValue()),
1414 cell, value, effect, control);
1416 ReplaceWithValue(node, effect, effect, control);
1417 return Changed(value);
1422 void ReduceBuiltin(JSGraph* jsgraph, Node* node,
int builtin_index,
int arity,
1423 CallDescriptor::Flags flags) {
1442 const bool is_construct = (node->opcode() == IrOpcode::kJSConstruct);
1444 DCHECK(Builtins::HasCppImplementation(builtin_index));
1446 Node* target = NodeProperties::GetValueInput(node, 0);
1447 Node* new_target = is_construct
1448 ? NodeProperties::GetValueInput(node, arity + 1)
1449 : jsgraph->UndefinedConstant();
1453 const bool has_builtin_exit_frame = Builtins::IsCpp(builtin_index);
1455 Node* stub = jsgraph->CEntryStubConstant(1, kDontSaveFPRegs, kArgvOnStack,
1456 has_builtin_exit_frame);
1457 node->ReplaceInput(0, stub);
1459 Zone* zone = jsgraph->zone();
1463 Node* receiver = jsgraph->UndefinedConstant();
1464 node->RemoveInput(arity + 1);
1465 node->InsertInput(zone, 1, receiver);
1468 const int argc = arity + BuiltinArguments::kNumExtraArgsWithReceiver;
1469 Node* argc_node = jsgraph->Constant(argc);
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);
1478 Address entry = Builtins::CppEntryOf(builtin_index);
1479 ExternalReference entry_ref = ExternalReference::Create(entry);
1480 Node* entry_node = jsgraph->ExternalConstant(entry_ref);
1482 node->InsertInput(zone, cursor++, entry_node);
1483 node->InsertInput(zone, cursor++, argc_node);
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);
1491 NodeProperties::ChangeOp(node, jsgraph->common()->Call(call_descriptor));
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);
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);
1514 if (target_type.IsHeapConstant() &&
1515 target_type.AsHeapConstant()->Ref().IsJSFunction()) {
1517 JSFunctionRef
function = target_type.AsHeapConstant()->Ref().AsJSFunction();
1518 if (!
function.map().is_constructor())
return NoChange();
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);
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);
1548 if (target_type.IsHeapConstant() &&
1549 target_type.AsHeapConstant()->Ref().IsJSFunction()) {
1550 JSFunctionRef
function = target_type.AsHeapConstant()->Ref().AsJSFunction();
1551 SharedFunctionInfoRef shared =
function.shared();
1554 if (!
function.map().is_constructor())
return NoChange();
1556 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1559 bool use_builtin_construct_stub = shared.construct_as_builtin();
1561 CodeRef code(broker(),
1562 use_builtin_construct_stub
1563 ? BUILTIN_CODE(isolate(), JSBuiltinsConstructStub)
1564 : BUILTIN_CODE(isolate(), JSConstructStubGeneric));
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(
1574 common()->Call(Linkage::GetStubCallDescriptor(
1575 graph()->zone(), ConstructStubDescriptor{}, 1 + arity, flags)));
1577 return Changed(node);
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);
1593 if (target_type.Is(Type::Function())) {
1595 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
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);
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);
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;
1631 if (target_type.IsHeapConstant() &&
1632 target_type.AsHeapConstant()->Ref().IsJSFunction()) {
1633 JSFunctionRef
function = target_type.AsHeapConstant()->Ref().AsJSFunction();
1634 SharedFunctionInfoRef shared =
function.shared();
1636 if (shared.HasBreakInfo()) {
1643 if (IsClassConstructor(shared.kind()))
return NoChange();
1647 if (is_sloppy(shared.language_mode()) && !shared.native() &&
1648 !receiver_type.Is(Type::Receiver())) {
1649 if (!
function.native_context().equals(broker()->native_context())) {
1652 Node* global_proxy =
1653 jsgraph()->Constant(
function.native_context().global_proxy_object());
1655 graph()->NewNode(simplified()->ConvertReceiver(convert_mode),
1656 receiver, global_proxy, effect, control);
1657 NodeProperties::ReplaceValueInput(node, receiver, 1);
1661 Node* context = effect = graph()->NewNode(
1662 simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
1664 NodeProperties::ReplaceContextInput(node, context);
1667 NodeProperties::ReplaceEffectInput(node, effect);
1670 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1671 Node* new_target = jsgraph()->UndefinedConstant();
1672 Node* argument_count = jsgraph()->Constant(arity);
1674 if (NeedsArgumentAdaptorFrame(shared, arity)) {
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);
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())) {
1690 ReduceBuiltin(jsgraph(), node, shared.builtin_id(), arity, flags);
1691 }
else if (shared.HasBuiltinId() &&
1692 Builtins::KindOf(shared.builtin_id()) == Builtins::TFJ) {
1694 Callable callable = Builtins::CallableFor(
1695 isolate(), static_cast<Builtins::Name>(shared.builtin_id()));
1696 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
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);
1703 node->InsertInput(graph()->zone(), 2, new_target);
1704 node->InsertInput(graph()->zone(), 3, argument_count);
1705 NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
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)));
1715 return Changed(node);
1719 if (target_type.Is(Type::Function())) {
1721 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
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);
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);
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);
1757 Node* receiver_map = effect =
1758 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1759 receiver, effect, control);
1762 case ForInMode::kUseEnumCacheKeys:
1763 case ForInMode::kUseEnumCacheKeysAndIndices: {
1765 Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
1766 receiver_map, cache_type);
1768 graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongMap),
1769 check, effect, control);
1773 ReplaceWithValue(node, node, node, control);
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(
1783 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()));
1784 NodeProperties::SetType(node, Type::InternalizedString());
1787 case ForInMode::kGeneric: {
1789 Node* key = effect = graph()->NewNode(
1790 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
1791 cache_array, index, effect, control);
1794 Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
1795 receiver_map, cache_type);
1797 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1799 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1809 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
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);
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);
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);
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));
1851 return Changed(node);
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;
1865 case ForInMode::kUseEnumCacheKeys:
1866 case ForInMode::kUseEnumCacheKeysAndIndices: {
1868 effect = graph()->NewNode(
1869 simplified()->CheckMaps(CheckMapsFlag::kNone,
1870 ZoneHandleSet<Map>(factory()->meta_map())),
1871 enumerator, effect, control);
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);
1885 Node* bit_field3 = effect = graph()->NewNode(
1886 simplified()->LoadField(AccessBuilder::ForMapBitField3()), enumerator,
1888 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
1890 graph()->NewNode(simplified()->NumberBitwiseAnd(), bit_field3,
1891 jsgraph()->Constant(Map::EnumLengthBits::kMask));
1894 case ForInMode::kGeneric: {
1896 Node* check = effect = graph()->NewNode(
1897 simplified()->CompareMaps(ZoneHandleSet<Map>(factory()->meta_map())),
1898 enumerator, effect, control);
1900 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1902 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1903 Node* etrue = effect;
1904 Node* cache_array_true;
1905 Node* cache_length_true;
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);
1920 Node* bit_field3 = etrue = graph()->NewNode(
1921 simplified()->LoadField(AccessBuilder::ForMapBitField3()),
1922 enumerator, etrue, if_true);
1923 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
1925 graph()->NewNode(simplified()->NumberBitwiseAnd(), bit_field3,
1926 jsgraph()->Constant(Map::EnumLengthBits::kMask));
1929 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1930 Node* efalse = effect;
1931 Node* cache_array_false;
1932 Node* cache_length_false;
1935 cache_array_false = enumerator;
1936 cache_length_false = efalse = graph()->NewNode(
1937 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
1938 cache_array_false, efalse, if_false);
1942 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1943 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1945 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1946 cache_array_true, cache_array_false, control);
1948 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1949 cache_length_true, cache_length_false, control);
1955 for (Edge edge : node->use_edges()) {
1956 Node*
const user = edge.from();
1957 if (NodeProperties::IsEffectEdge(edge)) {
1958 edge.UpdateTo(effect);
1960 }
else if (NodeProperties::IsControlEdge(edge)) {
1961 edge.UpdateTo(control);
1964 DCHECK(NodeProperties::IsValueEdge(edge));
1965 switch (ProjectionIndexOf(user->op())) {
1967 Replace(user, cache_type);
1970 Replace(user, cache_array);
1973 Replace(user, cache_length);
1981 return Replace(effect);
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);
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);
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());
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();
2024 Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
2025 generator, effect, control);
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);
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);
2043 ReplaceWithValue(node, effect, effect, control);
2044 return Changed(effect);
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);
2053 FieldAccess continuation_field =
2054 AccessBuilder::ForJSGeneratorObjectContinuation();
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);
2062 ReplaceWithValue(node, continuation, effect, control);
2063 return Changed(continuation);
2066 Reduction JSTypedLowering::ReduceJSGeneratorRestoreContext(Node* node) {
2067 DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContext, node->opcode());
2069 const Operator* new_op =
2070 simplified()->LoadField(AccessBuilder::ForJSGeneratorObjectContext());
2073 DCHECK(OperatorProperties::HasContextInput(node->op()));
2074 DCHECK(!OperatorProperties::HasContextInput(new_op));
2075 node->RemoveInput(NodeProperties::FirstContextIndex(node));
2077 NodeProperties::ChangeOp(node, new_op);
2078 return Changed(node);
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());
2088 FieldAccess array_field =
2089 AccessBuilder::ForJSGeneratorObjectParametersAndRegisters();
2090 FieldAccess element_field = AccessBuilder::ForFixedArraySlot(index);
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);
2100 ReplaceWithValue(node, element, effect, control);
2101 return Changed(element);
2104 Reduction JSTypedLowering::ReduceJSGeneratorRestoreInputOrDebugPos(Node* node) {
2105 DCHECK_EQ(IrOpcode::kJSGeneratorRestoreInputOrDebugPos, node->opcode());
2107 FieldAccess input_or_debug_pos_field =
2108 AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
2109 const Operator* new_op = simplified()->LoadField(input_or_debug_pos_field);
2112 DCHECK(OperatorProperties::HasContextInput(node->op()));
2113 DCHECK(!OperatorProperties::HasContextInput(new_op));
2114 node->RemoveInput(NodeProperties::FirstContextIndex(node));
2116 NodeProperties::ChangeOp(node, new_op);
2117 return Changed(node);
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);
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);
2145 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
2147 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
2150 controls[count] = graph()->NewNode(common()->IfTrue(), control);
2151 effects[count] = effect;
2152 values[count] = jsgraph()->FalseConstant();
2155 control = graph()->NewNode(common()->IfFalse(), control);
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,
2165 check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type,
2166 jsgraph()->Constant(JS_ARRAY_TYPE));
2167 control = graph()->NewNode(common()->Branch(), check, control);
2170 controls[count] = graph()->NewNode(common()->IfTrue(), control);
2171 effects[count] = effect;
2172 values[count] = jsgraph()->TrueConstant();
2175 control = graph()->NewNode(common()->IfFalse(), control);
2178 check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type,
2179 jsgraph()->Constant(JS_PROXY_TYPE));
2181 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
2184 controls[count] = graph()->NewNode(common()->IfFalse(), control);
2185 effects[count] = effect;
2186 values[count] = jsgraph()->FalseConstant();
2189 control = graph()->NewNode(common()->IfTrue(), control);
2192 value = effect = control =
2193 graph()->NewNode(javascript()->CallRuntime(Runtime::kArrayIsArray), value,
2194 context, frame_state, effect, control);
2195 NodeProperties::SetType(value, Type::Boolean());
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);
2208 controls[count] = control;
2209 effects[count] = effect;
2210 values[count] = value;
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),
2219 ReplaceWithValue(node, value, effect, control);
2220 return Replace(value);
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);
2230 if (value_type.Is(type_cache_.kSafeInteger) &&
2231 (radix_type.Is(type_cache_.kTenOrUndefined) ||
2232 radix_type.Is(type_cache_.kZeroOrUndefined))) {
2236 ReplaceWithValue(node, value);
2237 return Replace(value);
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);
2249 if (resolution_type.Is(Type::Primitive())) {
2251 node->RemoveInput(3);
2252 NodeProperties::ChangeOp(node, javascript()->FulfillPromise());
2253 return Changed(node);
2258 Reduction JSTypedLowering::Reduce(Node* node) {
2259 DisallowHeapAccess no_heap_access;
2261 switch (node->opcode()) {
2262 case IrOpcode::kJSEqual:
2263 return ReduceJSEqual(node);
2264 case IrOpcode::kJSStrictEqual:
2265 return ReduceJSStrictEqual(node);
2266 case IrOpcode::kJSLessThan:
2267 case IrOpcode::kJSGreaterThan:
2268 case IrOpcode::kJSLessThanOrEqual:
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);
2362 Factory* JSTypedLowering::factory()
const {
return jsgraph()->factory(); }
2365 Graph* JSTypedLowering::graph()
const {
return jsgraph()->graph(); }
2368 Isolate* JSTypedLowering::isolate()
const {
return jsgraph()->isolate(); }
2371 JSOperatorBuilder* JSTypedLowering::javascript()
const {
2372 return jsgraph()->javascript();
2376 CommonOperatorBuilder* JSTypedLowering::common()
const {
2377 return jsgraph()->common();
2380 SimplifiedOperatorBuilder* JSTypedLowering::simplified()
const {
2381 return jsgraph()->simplified();