5 #include "src/compiler/js-call-reducer.h" 7 #include "src/api-inl.h" 8 #include "src/builtins/builtins-promise-gen.h" 9 #include "src/builtins/builtins-utils.h" 10 #include "src/code-factory.h" 11 #include "src/code-stubs.h" 12 #include "src/compiler/access-builder.h" 13 #include "src/compiler/access-info.h" 14 #include "src/compiler/allocation-builder.h" 15 #include "src/compiler/compilation-dependencies.h" 16 #include "src/compiler/js-graph.h" 17 #include "src/compiler/linkage.h" 18 #include "src/compiler/node-matchers.h" 19 #include "src/compiler/property-access-builder.h" 20 #include "src/compiler/simplified-operator.h" 21 #include "src/compiler/type-cache.h" 22 #include "src/feedback-vector-inl.h" 23 #include "src/ic/call-optimization.h" 24 #include "src/objects-inl.h" 25 #include "src/objects/arguments-inl.h" 26 #include "src/objects/js-array-buffer-inl.h" 27 #include "src/objects/js-array-inl.h" 28 #include "src/objects/js-objects.h" 29 #include "src/vector-slot-pair.h" 35 Reduction JSCallReducer::ReduceMathUnary(Node* node,
const Operator* op) {
36 CallParameters
const& p = CallParametersOf(node->op());
37 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
40 if (node->op()->ValueInputCount() < 3) {
41 Node* value = jsgraph()->NaNConstant();
42 ReplaceWithValue(node, value);
43 return Replace(value);
46 Node* effect = NodeProperties::GetEffectInput(node);
47 Node* control = NodeProperties::GetControlInput(node);
48 Node* input = NodeProperties::GetValueInput(node, 2);
51 graph()->NewNode(simplified()->SpeculativeToNumber(
52 NumberOperationHint::kNumberOrOddball, p.feedback()),
53 input, effect, control);
54 Node* value = graph()->NewNode(op, input);
55 ReplaceWithValue(node, value, effect);
56 return Replace(value);
59 Reduction JSCallReducer::ReduceMathBinary(Node* node,
const Operator* op) {
60 CallParameters
const& p = CallParametersOf(node->op());
61 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
64 if (node->op()->ValueInputCount() < 3) {
65 Node* value = jsgraph()->NaNConstant();
66 ReplaceWithValue(node, value);
67 return Replace(value);
69 Node* effect = NodeProperties::GetEffectInput(node);
70 Node* control = NodeProperties::GetControlInput(node);
72 Node* left = NodeProperties::GetValueInput(node, 2);
73 Node* right = node->op()->ValueInputCount() > 3
74 ? NodeProperties::GetValueInput(node, 3)
75 : jsgraph()->NaNConstant();
77 graph()->NewNode(simplified()->SpeculativeToNumber(
78 NumberOperationHint::kNumberOrOddball, p.feedback()),
79 left, effect, control);
81 graph()->NewNode(simplified()->SpeculativeToNumber(
82 NumberOperationHint::kNumberOrOddball, p.feedback()),
83 right, effect, control);
84 Node* value = graph()->NewNode(op, left, right);
85 ReplaceWithValue(node, value, effect);
86 return Replace(value);
90 Reduction JSCallReducer::ReduceMathImul(Node* node) {
91 CallParameters
const& p = CallParametersOf(node->op());
92 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
95 if (node->op()->ValueInputCount() < 3) {
96 Node* value = jsgraph()->ZeroConstant();
97 ReplaceWithValue(node, value);
98 return Replace(value);
100 Node* left = NodeProperties::GetValueInput(node, 2);
101 Node* right = node->op()->ValueInputCount() > 3
102 ? NodeProperties::GetValueInput(node, 3)
103 : jsgraph()->ZeroConstant();
104 Node* effect = NodeProperties::GetEffectInput(node);
105 Node* control = NodeProperties::GetControlInput(node);
108 graph()->NewNode(simplified()->SpeculativeToNumber(
109 NumberOperationHint::kNumberOrOddball, p.feedback()),
110 left, effect, control);
112 graph()->NewNode(simplified()->SpeculativeToNumber(
113 NumberOperationHint::kNumberOrOddball, p.feedback()),
114 right, effect, control);
115 left = graph()->NewNode(simplified()->NumberToUint32(), left);
116 right = graph()->NewNode(simplified()->NumberToUint32(), right);
117 Node* value = graph()->NewNode(simplified()->NumberImul(), left, right);
118 ReplaceWithValue(node, value, effect);
119 return Replace(value);
123 Reduction JSCallReducer::ReduceMathClz32(Node* node) {
124 CallParameters
const& p = CallParametersOf(node->op());
125 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
128 if (node->op()->ValueInputCount() < 3) {
129 Node* value = jsgraph()->Constant(32);
130 ReplaceWithValue(node, value);
131 return Replace(value);
133 Node* input = NodeProperties::GetValueInput(node, 2);
134 Node* effect = NodeProperties::GetEffectInput(node);
135 Node* control = NodeProperties::GetControlInput(node);
138 graph()->NewNode(simplified()->SpeculativeToNumber(
139 NumberOperationHint::kNumberOrOddball, p.feedback()),
140 input, effect, control);
141 input = graph()->NewNode(simplified()->NumberToUint32(), input);
142 Node* value = graph()->NewNode(simplified()->NumberClz32(), input);
143 ReplaceWithValue(node, value, effect);
144 return Replace(value);
149 Reduction JSCallReducer::ReduceMathMinMax(Node* node,
const Operator* op,
151 CallParameters
const& p = CallParametersOf(node->op());
152 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
155 if (node->op()->ValueInputCount() <= 2) {
156 ReplaceWithValue(node, empty_value);
157 return Replace(empty_value);
159 Node* effect = NodeProperties::GetEffectInput(node);
160 Node* control = NodeProperties::GetControlInput(node);
162 Node* value = effect =
163 graph()->NewNode(simplified()->SpeculativeToNumber(
164 NumberOperationHint::kNumberOrOddball, p.feedback()),
165 NodeProperties::GetValueInput(node, 2), effect, control);
166 for (
int i = 3;
i < node->op()->ValueInputCount();
i++) {
167 Node* input = effect = graph()->NewNode(
168 simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
170 NodeProperties::GetValueInput(node,
i), effect, control);
171 value = graph()->NewNode(op, value, input);
174 ReplaceWithValue(node, value, effect);
175 return Replace(value);
178 Reduction JSCallReducer::Reduce(Node* node) {
179 switch (node->opcode()) {
180 case IrOpcode::kJSConstruct:
181 return ReduceJSConstruct(node);
182 case IrOpcode::kJSConstructWithArrayLike:
183 return ReduceJSConstructWithArrayLike(node);
184 case IrOpcode::kJSConstructWithSpread:
185 return ReduceJSConstructWithSpread(node);
186 case IrOpcode::kJSCall:
187 return ReduceJSCall(node);
188 case IrOpcode::kJSCallWithArrayLike:
189 return ReduceJSCallWithArrayLike(node);
190 case IrOpcode::kJSCallWithSpread:
191 return ReduceJSCallWithSpread(node);
198 void JSCallReducer::Finalize() {
202 std::set<Node*>
const waitlist = std::move(waitlist_);
203 for (Node* node : waitlist) {
204 if (!node->IsDead()) {
205 Reduction
const reduction = Reduce(node);
206 if (reduction.Changed()) {
207 Node* replacement = reduction.replacement();
208 if (replacement != node) {
209 Replace(node, replacement);
217 Reduction JSCallReducer::ReduceArrayConstructor(Node* node) {
218 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
219 Node* target = NodeProperties::GetValueInput(node, 0);
220 CallParameters
const& p = CallParametersOf(node->op());
223 DCHECK_LE(2u, p.arity());
224 size_t const arity = p.arity() - 2;
225 NodeProperties::ReplaceValueInput(node, target, 0);
226 NodeProperties::ReplaceValueInput(node, target, 1);
227 NodeProperties::ChangeOp(
228 node, javascript()->CreateArray(arity, MaybeHandle<AllocationSite>()));
229 return Changed(node);
233 Reduction JSCallReducer::ReduceBooleanConstructor(Node* node) {
234 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
235 CallParameters
const& p = CallParametersOf(node->op());
238 DCHECK_LE(2u, p.arity());
239 Node* value = (p.arity() == 2) ? jsgraph()->UndefinedConstant()
240 : NodeProperties::GetValueInput(node, 2);
241 value = graph()->NewNode(simplified()->ToBoolean(), value);
242 ReplaceWithValue(node, value);
243 return Replace(value);
247 Reduction JSCallReducer::ReduceObjectConstructor(Node* node) {
248 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
249 CallParameters
const& p = CallParametersOf(node->op());
250 if (p.arity() < 3)
return NoChange();
251 Node* value = (p.arity() >= 3) ? NodeProperties::GetValueInput(node, 2)
252 : jsgraph()->UndefinedConstant();
253 Node* effect = NodeProperties::GetEffectInput(node);
256 if (NodeProperties::CanBePrimitive(broker(), value, effect)) {
257 if (!NodeProperties::CanBeNullOrUndefined(broker(), value, effect)) {
260 NodeProperties::ReplaceValueInputs(node, value);
261 NodeProperties::ChangeOp(node, javascript()->ToObject());
262 return Changed(node);
265 ReplaceWithValue(node, value);
266 return Replace(value);
272 Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
273 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
274 CallParameters
const& p = CallParametersOf(node->op());
275 size_t arity = p.arity();
276 DCHECK_LE(2u, arity);
277 ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny;
280 convert_mode = ConvertReceiverMode::kNullOrUndefined;
281 node->ReplaceInput(0, node->InputAt(1));
282 node->ReplaceInput(1, jsgraph()->UndefinedConstant());
283 }
else if (arity == 3) {
285 node->RemoveInput(0);
288 Node* target = NodeProperties::GetValueInput(node, 1);
289 Node* this_argument = NodeProperties::GetValueInput(node, 2);
290 Node* arguments_list = NodeProperties::GetValueInput(node, 3);
291 Node* context = NodeProperties::GetContextInput(node);
292 Node* frame_state = NodeProperties::GetFrameStateInput(node);
293 Node* effect = NodeProperties::GetEffectInput(node);
294 Node* control = NodeProperties::GetControlInput(node);
298 if (!NodeProperties::CanBeNullOrUndefined(broker(), arguments_list,
301 node->ReplaceInput(0, target);
302 node->ReplaceInput(1, this_argument);
303 node->ReplaceInput(2, arguments_list);
304 while (arity-- > 3) node->RemoveInput(3);
307 NodeProperties::ChangeOp(node,
308 javascript()->CallWithArrayLike(p.frequency()));
309 Reduction
const reduction = ReduceJSCallWithArrayLike(node);
310 return reduction.Changed() ? reduction : Changed(node);
314 graph()->NewNode(simplified()->ReferenceEqual(), arguments_list,
315 jsgraph()->NullConstant());
316 control = graph()->NewNode(common()->Branch(BranchHint::kFalse),
317 check_null, control);
318 Node* if_null = graph()->NewNode(common()->IfTrue(), control);
319 control = graph()->NewNode(common()->IfFalse(), control);
322 Node* check_undefined =
323 graph()->NewNode(simplified()->ReferenceEqual(), arguments_list,
324 jsgraph()->UndefinedConstant());
325 control = graph()->NewNode(common()->Branch(BranchHint::kFalse),
326 check_undefined, control);
327 Node* if_undefined = graph()->NewNode(common()->IfTrue(), control);
328 control = graph()->NewNode(common()->IfFalse(), control);
332 Node* effect0 = effect;
333 Node* control0 = control;
334 Node* value0 = effect0 = control0 = graph()->NewNode(
335 javascript()->CallWithArrayLike(p.frequency()), target, this_argument,
336 arguments_list, context, frame_state, effect0, control0);
339 Node* effect1 = effect;
341 graph()->NewNode(common()->Merge(2), if_null, if_undefined);
342 Node* value1 = effect1 = control1 =
343 graph()->NewNode(javascript()->Call(2), target, this_argument,
344 context, frame_state, effect1, control1);
347 Node* if_exception =
nullptr;
348 if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
350 Node* if_exception0 =
351 graph()->NewNode(common()->IfException(), control0, effect0);
352 control0 = graph()->NewNode(common()->IfSuccess(), control0);
353 Node* if_exception1 =
354 graph()->NewNode(common()->IfException(), control1, effect1);
355 control1 = graph()->NewNode(common()->IfSuccess(), control1);
359 graph()->NewNode(common()->Merge(2), if_exception0, if_exception1);
360 Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception0,
361 if_exception1, merge);
363 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
364 if_exception0, if_exception1, merge);
365 ReplaceWithValue(if_exception, phi, ephi, merge);
369 control = graph()->NewNode(common()->Merge(2), control0, control1);
371 graph()->NewNode(common()->EffectPhi(2), effect0, effect1, control);
373 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
374 value0, value1, control);
375 ReplaceWithValue(node, value, effect, control);
376 return Replace(value);
380 NodeProperties::ChangeOp(
382 javascript()->Call(arity, p.frequency(), VectorSlotPair(), convert_mode));
384 Reduction
const reduction = ReduceJSCall(node);
385 return reduction.Changed() ? reduction : Changed(node);
389 Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
390 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
397 Node* receiver = NodeProperties::GetValueInput(node, 1);
398 Node* bound_this = (node->op()->ValueInputCount() < 3)
399 ? jsgraph()->UndefinedConstant()
400 : NodeProperties::GetValueInput(node, 2);
401 Node* context = NodeProperties::GetContextInput(node);
402 Node* effect = NodeProperties::GetEffectInput(node);
403 Node* control = NodeProperties::GetControlInput(node);
409 ZoneHandleSet<Map> receiver_maps;
410 NodeProperties::InferReceiverMapsResult result =
411 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
413 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
414 DCHECK_NE(0, receiver_maps.size());
415 MapRef first_receiver_map(broker(), receiver_maps[0]);
416 bool const is_constructor = first_receiver_map.is_constructor();
417 first_receiver_map.SerializePrototype();
418 ObjectRef
const prototype = first_receiver_map.prototype();
419 for (Handle<Map>
const map : receiver_maps) {
420 MapRef receiver_map(broker(), map);
423 STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE);
424 receiver_map.SerializePrototype();
425 if (!receiver_map.prototype().equals(prototype) ||
426 receiver_map.is_constructor() != is_constructor ||
427 receiver_map.instance_type() < FIRST_FUNCTION_TYPE) {
433 if (receiver_map.is_dictionary_map())
return NoChange();
440 Handle<DescriptorArray> descriptors(
441 receiver_map.object()->instance_descriptors(), isolate());
442 if (descriptors->number_of_descriptors() < 2)
return NoChange();
443 if (descriptors->GetKey(JSFunction::kLengthDescriptorIndex) !=
444 ReadOnlyRoots(isolate()).length_string()) {
447 if (!descriptors->GetStrongValue(JSFunction::kLengthDescriptorIndex)
448 ->IsAccessorInfo()) {
451 if (descriptors->GetKey(JSFunction::kNameDescriptorIndex) !=
452 ReadOnlyRoots(isolate()).name_string()) {
455 if (!descriptors->GetStrongValue(JSFunction::kNameDescriptorIndex)
456 ->IsAccessorInfo()) {
463 MapRef map = is_constructor
464 ? native_context().bound_function_with_constructor_map()
465 : native_context().bound_function_without_constructor_map();
466 if (!map.prototype().equals(prototype))
return NoChange();
469 if (result == NodeProperties::kUnreliableReceiverMaps) {
470 effect = graph()->NewNode(
471 simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
476 int const arity = std::max(0, node->op()->ValueInputCount() - 3);
477 int const input_count = 2 + arity + 3;
478 Node** inputs = graph()->zone()->NewArray<Node*>(input_count);
479 inputs[0] = receiver;
480 inputs[1] = bound_this;
481 for (
int i = 0;
i < arity; ++
i) {
482 inputs[2 +
i] = NodeProperties::GetValueInput(node, 3 +
i);
484 inputs[2 + arity + 0] = context;
485 inputs[2 + arity + 1] = effect;
486 inputs[2 + arity + 2] = control;
487 Node* value = effect =
488 graph()->NewNode(javascript()->CreateBoundFunction(arity, map.object()),
489 input_count, inputs);
490 ReplaceWithValue(node, value, effect, control);
491 return Replace(value);
495 Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
496 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
497 CallParameters
const& p = CallParametersOf(node->op());
498 Node* target = NodeProperties::GetValueInput(node, 0);
499 Node* effect = NodeProperties::GetEffectInput(node);
500 Node* control = NodeProperties::GetControlInput(node);
505 HeapObjectMatcher m(target);
507 JSFunctionRef
function = m.Ref(broker()).AsJSFunction();
508 context = jsgraph()->Constant(
function.context());
510 context = effect = graph()->NewNode(
511 simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
514 NodeProperties::ReplaceContextInput(node, context);
515 NodeProperties::ReplaceEffectInput(node, effect);
520 size_t arity = p.arity();
521 DCHECK_LE(2u, arity);
522 ConvertReceiverMode convert_mode;
525 convert_mode = ConvertReceiverMode::kNullOrUndefined;
526 node->ReplaceInput(0, node->InputAt(1));
527 node->ReplaceInput(1, jsgraph()->UndefinedConstant());
530 convert_mode = ConvertReceiverMode::kAny;
531 node->RemoveInput(0);
534 NodeProperties::ChangeOp(
536 javascript()->Call(arity, p.frequency(), VectorSlotPair(), convert_mode));
538 Reduction
const reduction = ReduceJSCall(node);
539 return reduction.Changed() ? reduction : Changed(node);
543 Reduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) {
544 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
545 Node* receiver = NodeProperties::GetValueInput(node, 1);
546 Node*
object = (node->op()->ValueInputCount() >= 3)
547 ? NodeProperties::GetValueInput(node, 2)
548 : jsgraph()->UndefinedConstant();
549 Node* context = NodeProperties::GetContextInput(node);
550 Node* frame_state = NodeProperties::GetFrameStateInput(node);
551 Node* effect = NodeProperties::GetEffectInput(node);
552 Node* control = NodeProperties::GetControlInput(node);
560 node->ReplaceInput(0, receiver);
561 node->ReplaceInput(1,
object);
562 node->ReplaceInput(2, context);
563 node->ReplaceInput(3, frame_state);
564 node->ReplaceInput(4, effect);
565 node->ReplaceInput(5, control);
566 node->TrimInputCount(6);
567 NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
568 return Changed(node);
571 Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node*
object) {
572 Node* effect = NodeProperties::GetEffectInput(node);
575 ZoneHandleSet<Map> object_maps;
576 NodeProperties::InferReceiverMapsResult result =
577 NodeProperties::InferReceiverMaps(broker(),
object, effect, &object_maps);
578 if (result != NodeProperties::kNoReceiverMaps) {
579 MapRef candidate_map(broker(), object_maps[0]);
580 candidate_map.SerializePrototype();
581 ObjectRef candidate_prototype = candidate_map.prototype();
584 for (
size_t i = 0;
i < object_maps.size(); ++
i) {
585 MapRef object_map(broker(), object_maps[
i]);
586 object_map.SerializePrototype();
587 if (IsSpecialReceiverInstanceType(object_map.instance_type()) ||
588 object_map.has_hidden_prototype() ||
589 !object_map.prototype().equals(candidate_prototype)) {
597 DCHECK(!object_map.IsPrimitiveMap() && object_map.IsJSReceiverMap());
598 if (result == NodeProperties::kUnreliableReceiverMaps &&
599 !object_map.is_stable()) {
603 if (result == NodeProperties::kUnreliableReceiverMaps) {
604 for (
size_t i = 0;
i < object_maps.size(); ++
i) {
605 dependencies()->DependOnStableMap(MapRef(broker(), object_maps[
i]));
608 Node* value = jsgraph()->Constant(candidate_prototype);
609 ReplaceWithValue(node, value);
610 return Replace(value);
617 Reduction JSCallReducer::ReduceObjectGetPrototypeOf(Node* node) {
618 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
619 Node*
object = (node->op()->ValueInputCount() >= 3)
620 ? NodeProperties::GetValueInput(node, 2)
621 : jsgraph()->UndefinedConstant();
622 return ReduceObjectGetPrototype(node,
object);
626 Reduction JSCallReducer::ReduceObjectIs(Node* node) {
627 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
628 CallParameters
const& params = CallParametersOf(node->op());
629 int const argc =
static_cast<int>(params.arity() - 2);
630 Node* lhs = (argc >= 1) ? NodeProperties::GetValueInput(node, 2)
631 : jsgraph()->UndefinedConstant();
632 Node* rhs = (argc >= 2) ? NodeProperties::GetValueInput(node, 3)
633 : jsgraph()->UndefinedConstant();
634 Node* value = graph()->NewNode(simplified()->SameValue(), lhs, rhs);
635 ReplaceWithValue(node, value);
636 return Replace(value);
640 Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) {
641 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
642 Node* receiver = NodeProperties::GetValueInput(node, 1);
643 return ReduceObjectGetPrototype(node, receiver);
647 Reduction JSCallReducer::ReduceObjectPrototypeHasOwnProperty(Node* node) {
648 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
649 CallParameters
const& params = CallParametersOf(node->op());
650 int const argc =
static_cast<int>(params.arity() - 2);
651 Node* receiver = NodeProperties::GetValueInput(node, 1);
652 Node* name = (argc >= 1) ? NodeProperties::GetValueInput(node, 2)
653 : jsgraph()->UndefinedConstant();
654 Node* effect = NodeProperties::GetEffectInput(node);
655 Node* control = NodeProperties::GetControlInput(node);
694 if (name->opcode() == IrOpcode::kJSForInNext) {
695 ForInMode
const mode = ForInModeOf(name->op());
696 if (mode != ForInMode::kGeneric) {
697 Node*
object = NodeProperties::GetValueInput(name, 0);
698 Node* cache_type = NodeProperties::GetValueInput(name, 2);
699 if (object->opcode() == IrOpcode::kJSToObject) {
700 object = NodeProperties::GetValueInput(
object, 0);
702 if (
object == receiver) {
705 if (!NodeProperties::NoObservableSideEffectBetween(effect, name)) {
706 Node* receiver_map = effect =
707 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
708 receiver, effect, control);
709 Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
710 receiver_map, cache_type);
711 effect = graph()->NewNode(
712 simplified()->CheckIf(DeoptimizeReason::kWrongMap), check, effect,
715 Node* value = jsgraph()->TrueConstant();
716 ReplaceWithValue(node, value, effect, control);
717 return Replace(value);
726 Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
727 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
728 Node* receiver = NodeProperties::GetValueInput(node, 1);
729 Node* value = node->op()->ValueInputCount() > 2
730 ? NodeProperties::GetValueInput(node, 2)
731 : jsgraph()->UndefinedConstant();
732 Node* effect = NodeProperties::GetEffectInput(node);
736 ZoneHandleSet<Map> receiver_maps;
737 NodeProperties::InferReceiverMapsResult result =
738 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
740 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
741 for (Handle<Map> map : receiver_maps) {
742 MapRef receiver_map(broker(), map);
743 if (!receiver_map.IsJSReceiverMap())
return NoChange();
750 NodeProperties::ReplaceValueInput(node, value, 0);
751 NodeProperties::ReplaceValueInput(node, receiver, 1);
752 for (
int i = node->op()->ValueInputCount();
i-- > 2;) {
753 node->RemoveInput(
i);
755 NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
756 return Changed(node);
760 Reduction JSCallReducer::ReduceReflectApply(Node* node) {
761 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
762 CallParameters
const& p = CallParametersOf(node->op());
763 int arity =
static_cast<int>(p.arity() - 2);
766 node->RemoveInput(0);
767 node->RemoveInput(0);
769 node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
771 while (arity-- > 3) {
772 node->RemoveInput(arity);
774 NodeProperties::ChangeOp(node,
775 javascript()->CallWithArrayLike(p.frequency()));
776 Reduction
const reduction = ReduceJSCallWithArrayLike(node);
777 return reduction.Changed() ? reduction : Changed(node);
781 Reduction JSCallReducer::ReduceReflectConstruct(Node* node) {
782 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
783 CallParameters
const& p = CallParametersOf(node->op());
784 int arity =
static_cast<int>(p.arity() - 2);
787 node->RemoveInput(0);
788 node->RemoveInput(0);
790 node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
793 node->InsertInput(graph()->zone(), arity++, node->InputAt(0));
795 while (arity-- > 3) {
796 node->RemoveInput(arity);
798 NodeProperties::ChangeOp(node,
799 javascript()->ConstructWithArrayLike(p.frequency()));
800 Reduction
const reduction = ReduceJSConstructWithArrayLike(node);
801 return reduction.Changed() ? reduction : Changed(node);
805 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) {
806 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
807 Node* target = (node->op()->ValueInputCount() >= 3)
808 ? NodeProperties::GetValueInput(node, 2)
809 : jsgraph()->UndefinedConstant();
810 return ReduceObjectGetPrototype(node, target);
814 Reduction JSCallReducer::ReduceObjectCreate(Node* node) {
815 int arg_count = node->op()->ValueInputCount();
816 Node* properties = arg_count >= 4 ? NodeProperties::GetValueInput(node, 3)
817 : jsgraph()->UndefinedConstant();
818 if (properties != jsgraph()->UndefinedConstant())
return NoChange();
820 Node* effect = NodeProperties::GetEffectInput(node);
821 Node* control = NodeProperties::GetControlInput(node);
822 Node* context = NodeProperties::GetContextInput(node);
823 Node* frame_state = NodeProperties::GetFrameStateInput(node);
824 Node* prototype = arg_count >= 3 ? NodeProperties::GetValueInput(node, 2)
825 : jsgraph()->UndefinedConstant();
826 node->ReplaceInput(0, prototype);
827 node->ReplaceInput(1, context);
828 node->ReplaceInput(2, frame_state);
829 node->ReplaceInput(3, effect);
830 node->ReplaceInput(4, control);
831 node->TrimInputCount(5);
832 NodeProperties::ChangeOp(node, javascript()->CreateObject());
833 return Changed(node);
837 Reduction JSCallReducer::ReduceReflectGet(Node* node) {
838 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
839 CallParameters
const& p = CallParametersOf(node->op());
840 int arity =
static_cast<int>(p.arity() - 2);
841 if (arity != 2)
return NoChange();
842 Node* target = NodeProperties::GetValueInput(node, 2);
843 Node* key = NodeProperties::GetValueInput(node, 3);
844 Node* context = NodeProperties::GetContextInput(node);
845 Node* frame_state = NodeProperties::GetFrameStateInput(node);
846 Node* effect = NodeProperties::GetEffectInput(node);
847 Node* control = NodeProperties::GetControlInput(node);
850 Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
852 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
855 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
856 Node* efalse = effect;
858 if_false = efalse = graph()->NewNode(
859 javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
861 static_cast<int>(MessageTemplate::kCalledOnNonObject)),
862 jsgraph()->HeapConstant(factory()->ReflectGet_string()), context,
863 frame_state, efalse, if_false);
867 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
868 Node* etrue = effect;
872 Builtins::CallableFor(isolate(), Builtins::kGetProperty);
873 auto call_descriptor = Linkage::GetStubCallDescriptor(
874 graph()->zone(), callable.descriptor(),
875 callable.descriptor().GetStackParameterCount(),
876 CallDescriptor::kNeedsFrameState, Operator::kNoProperties);
877 Node* stub_code = jsgraph()->HeapConstant(callable.code());
878 vtrue = etrue = if_true =
879 graph()->NewNode(common()->Call(call_descriptor), stub_code, target,
880 key, context, frame_state, etrue, if_true);
884 Node* on_exception =
nullptr;
885 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
887 Node* extrue = graph()->NewNode(common()->IfException(), etrue, if_true);
888 if_true = graph()->NewNode(common()->IfSuccess(), if_true);
889 Node* exfalse = graph()->NewNode(common()->IfException(), efalse, if_false);
890 if_false = graph()->NewNode(common()->IfSuccess(), if_false);
893 Node* merge = graph()->NewNode(common()->Merge(2), extrue, exfalse);
895 graph()->NewNode(common()->EffectPhi(2), extrue, exfalse, merge);
897 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
898 extrue, exfalse, merge);
899 ReplaceWithValue(on_exception, phi, ephi, merge);
903 if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
904 NodeProperties::MergeControlToEnd(graph(), common(), if_false);
907 ReplaceWithValue(node, vtrue, etrue, if_true);
908 return Changed(vtrue);
912 Reduction JSCallReducer::ReduceReflectHas(Node* node) {
913 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
914 CallParameters
const& p = CallParametersOf(node->op());
915 int arity =
static_cast<int>(p.arity() - 2);
917 Node* target = (arity >= 1) ? NodeProperties::GetValueInput(node, 2)
918 : jsgraph()->UndefinedConstant();
919 Node* key = (arity >= 2) ? NodeProperties::GetValueInput(node, 3)
920 : jsgraph()->UndefinedConstant();
921 Node* context = NodeProperties::GetContextInput(node);
922 Node* frame_state = NodeProperties::GetFrameStateInput(node);
923 Node* effect = NodeProperties::GetEffectInput(node);
924 Node* control = NodeProperties::GetControlInput(node);
927 Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
929 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
932 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
933 Node* efalse = effect;
935 if_false = efalse = graph()->NewNode(
936 javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
938 static_cast<int>(MessageTemplate::kCalledOnNonObject)),
939 jsgraph()->HeapConstant(factory()->ReflectHas_string()), context,
940 frame_state, efalse, if_false);
944 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
945 Node* etrue = effect;
948 vtrue = etrue = if_true =
949 graph()->NewNode(javascript()->HasProperty(), target, key, context,
950 frame_state, etrue, if_true);
954 Node* on_exception =
nullptr;
955 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
957 Node* extrue = graph()->NewNode(common()->IfException(), etrue, if_true);
958 if_true = graph()->NewNode(common()->IfSuccess(), if_true);
959 Node* exfalse = graph()->NewNode(common()->IfException(), efalse, if_false);
960 if_false = graph()->NewNode(common()->IfSuccess(), if_false);
963 Node* merge = graph()->NewNode(common()->Merge(2), extrue, exfalse);
965 graph()->NewNode(common()->EffectPhi(2), extrue, exfalse, merge);
967 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
968 extrue, exfalse, merge);
969 ReplaceWithValue(on_exception, phi, ephi, merge);
973 if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
974 NodeProperties::MergeControlToEnd(graph(), common(), if_false);
977 ReplaceWithValue(node, vtrue, etrue, if_true);
978 return Changed(vtrue);
981 Node* JSCallReducer::WireInLoopStart(Node* k, Node** control, Node** effect) {
982 Node* loop = *control =
983 graph()->NewNode(common()->Loop(2), *control, *control);
984 Node* eloop = *effect =
985 graph()->NewNode(common()->EffectPhi(2), *effect, *effect, loop);
986 Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
987 NodeProperties::MergeControlToEnd(graph(), common(), terminate);
988 return graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), k,
992 void JSCallReducer::WireInLoopEnd(Node* loop, Node* eloop, Node* vloop, Node* k,
993 Node* control, Node* effect) {
994 loop->ReplaceInput(1, control);
995 vloop->ReplaceInput(1, k);
996 eloop->ReplaceInput(1, effect);
1001 bool CanInlineArrayIteratingBuiltin(Isolate* isolate, MapRef& receiver_map) {
1002 receiver_map.SerializePrototype();
1003 if (!receiver_map.prototype().IsJSArray())
return false;
1004 JSArrayRef receiver_prototype = receiver_map.prototype().AsJSArray();
1005 return receiver_map.instance_type() == JS_ARRAY_TYPE &&
1006 IsFastElementsKind(receiver_map.elements_kind()) &&
1007 isolate->IsNoElementsProtectorIntact() &&
1008 isolate->IsAnyInitialArrayPrototype(receiver_prototype.object());
1011 bool CanInlineArrayIteratingBuiltin(JSHeapBroker* broker,
1012 ZoneHandleSet<Map> receiver_maps,
1013 ElementsKind* kind_return) {
1014 DCHECK_NE(0, receiver_maps.size());
1015 *kind_return = MapRef(broker, receiver_maps[0]).elements_kind();
1016 for (
auto receiver_map : receiver_maps) {
1017 MapRef map(broker, receiver_map);
1018 if (!CanInlineArrayIteratingBuiltin(broker->isolate(), map)) {
1021 if (!UnionElementsKindUptoSize(kind_return, map.elements_kind())) {
1030 Reduction JSCallReducer::ReduceArrayForEach(
1031 Node* node,
const SharedFunctionInfoRef& shared) {
1032 if (!FLAG_turbo_inline_array_builtins)
return NoChange();
1033 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
1034 CallParameters
const& p = CallParametersOf(node->op());
1035 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
1039 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
1040 Node* effect = NodeProperties::GetEffectInput(node);
1041 Node* control = NodeProperties::GetControlInput(node);
1042 Node* context = NodeProperties::GetContextInput(node);
1045 Node* receiver = NodeProperties::GetValueInput(node, 1);
1046 Node* fncallback = node->op()->ValueInputCount() > 2
1047 ? NodeProperties::GetValueInput(node, 2)
1048 : jsgraph()->UndefinedConstant();
1049 Node* this_arg = node->op()->ValueInputCount() > 3
1050 ? NodeProperties::GetValueInput(node, 3)
1051 : jsgraph()->UndefinedConstant();
1052 ZoneHandleSet<Map> receiver_maps;
1053 NodeProperties::InferReceiverMapsResult result =
1054 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
1056 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
1059 if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
1065 dependencies()->DependOnProtector(
1066 PropertyCellRef(broker(), factory()->no_elements_protector()));
1069 if (result == NodeProperties::kUnreliableReceiverMaps) {
1071 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
1072 receiver_maps, p.feedback()),
1073 receiver, effect, control);
1076 Node* k = jsgraph()->ZeroConstant();
1078 Node* original_length = effect = graph()->NewNode(
1079 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
1082 std::vector<Node*> checkpoint_params(
1083 {receiver, fncallback, this_arg, k, original_length});
1084 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1088 Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1089 jsgraph(), shared, Builtins::kArrayForEachLoopLazyDeoptContinuation,
1090 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1091 outer_frame_state, ContinuationFrameStateMode::LAZY);
1092 Node* check_fail =
nullptr;
1093 Node* check_throw =
nullptr;
1094 WireInCallbackIsCallableCheck(fncallback, context, check_frame_state, effect,
1095 &control, &check_fail, &check_throw);
1098 Node* vloop = k = WireInLoopStart(k, &control, &effect);
1099 Node *loop = control, *eloop = effect;
1100 checkpoint_params[3] = k;
1102 Node* continue_test =
1103 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
1104 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1105 continue_test, control);
1107 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
1108 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
1111 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1112 jsgraph(), shared, Builtins::kArrayForEachLoopEagerDeoptContinuation,
1113 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1114 outer_frame_state, ContinuationFrameStateMode::EAGER);
1117 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
1121 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
1122 receiver_maps, p.feedback()),
1123 receiver, effect, control);
1126 SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
1129 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
1130 checkpoint_params[3] = next_k;
1132 Node* hole_true =
nullptr;
1133 Node* hole_false =
nullptr;
1134 Node* effect_true = effect;
1136 if (IsHoleyElementsKind(kind)) {
1140 if (IsDoubleElementsKind(kind)) {
1141 check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
1143 check = graph()->NewNode(simplified()->ReferenceEqual(), element,
1144 jsgraph()->TheHoleConstant());
1147 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
1148 hole_true = graph()->NewNode(common()->IfTrue(), branch);
1149 hole_false = graph()->NewNode(common()->IfFalse(), branch);
1150 control = hole_false;
1155 element = effect = graph()->NewNode(
1156 common()->TypeGuard(Type::NonInternal()), element, effect, control);
1159 frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1160 jsgraph(), shared, Builtins::kArrayForEachLoopLazyDeoptContinuation,
1161 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1162 outer_frame_state, ContinuationFrameStateMode::LAZY);
1164 control = effect = graph()->NewNode(
1165 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
1166 receiver, context, frame_state, effect, control);
1169 Node* on_exception =
nullptr;
1170 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
1171 RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
1172 &check_fail, &control);
1175 if (IsHoleyElementsKind(kind)) {
1176 Node* after_call_control = control;
1177 Node* after_call_effect = effect;
1178 control = hole_true;
1179 effect = effect_true;
1181 control = graph()->NewNode(common()->Merge(2), control, after_call_control);
1182 effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
1186 WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
1193 control = graph()->NewNode(common()->LoopExit(), control, loop);
1194 effect = graph()->NewNode(common()->LoopExitEffect(), effect, control);
1201 graph()->NewNode(common()->Throw(), check_throw, check_fail);
1202 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
1204 ReplaceWithValue(node, jsgraph()->UndefinedConstant(), effect, control);
1205 return Replace(jsgraph()->UndefinedConstant());
1208 Reduction JSCallReducer::ReduceArrayReduce(
1209 Node* node, ArrayReduceDirection direction,
1210 const SharedFunctionInfoRef& shared) {
1211 if (!FLAG_turbo_inline_array_builtins)
return NoChange();
1212 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
1213 CallParameters
const& p = CallParametersOf(node->op());
1214 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
1217 bool left = direction == ArrayReduceDirection::kLeft;
1219 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
1220 Node* effect = NodeProperties::GetEffectInput(node);
1221 Node* control = NodeProperties::GetControlInput(node);
1222 Node* context = NodeProperties::GetContextInput(node);
1225 Node* receiver = NodeProperties::GetValueInput(node, 1);
1226 Node* fncallback = node->op()->ValueInputCount() > 2
1227 ? NodeProperties::GetValueInput(node, 2)
1228 : jsgraph()->UndefinedConstant();
1230 ZoneHandleSet<Map> receiver_maps;
1231 NodeProperties::InferReceiverMapsResult result =
1232 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
1234 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
1237 if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
1241 std::function<Node*(Node*)> hole_check = [
this, kind](Node* element) {
1242 if (IsDoubleElementsKind(kind)) {
1243 return graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
1245 return graph()->NewNode(simplified()->ReferenceEqual(), element,
1246 jsgraph()->TheHoleConstant());
1252 dependencies()->DependOnProtector(
1253 PropertyCellRef(broker(), factory()->no_elements_protector()));
1256 if (result == NodeProperties::kUnreliableReceiverMaps) {
1258 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
1259 receiver_maps, p.feedback()),
1260 receiver, effect, control);
1263 Node* original_length = effect = graph()->NewNode(
1264 simplified()->LoadField(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS)),
1265 receiver, effect, control);
1267 Node* initial_index =
1268 left ? jsgraph()->ZeroConstant()
1269 : graph()->NewNode(simplified()->NumberSubtract(), original_length,
1270 jsgraph()->OneConstant());
1271 const Operator* next_op =
1272 left ? simplified()->NumberAdd() : simplified()->NumberSubtract();
1273 Node* k = initial_index;
1275 Node* check_frame_state;
1277 Builtins::Name builtin_lazy =
1278 left ? Builtins::kArrayReduceLoopLazyDeoptContinuation
1279 : Builtins::kArrayReduceRightLoopLazyDeoptContinuation;
1280 const std::vector<Node*> checkpoint_params(
1281 {receiver, fncallback, k, original_length,
1282 jsgraph()->UndefinedConstant()});
1283 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1284 check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1285 jsgraph(), shared, builtin_lazy, node->InputAt(0), context,
1286 checkpoint_params.data(), stack_parameters - 1, outer_frame_state,
1287 ContinuationFrameStateMode::LAZY);
1289 Node* check_fail =
nullptr;
1290 Node* check_throw =
nullptr;
1294 WireInCallbackIsCallableCheck(fncallback, context, check_frame_state, effect,
1295 &control, &check_fail, &check_throw);
1298 Node* cur = jsgraph()->TheHoleConstant();
1300 if (node->op()->ValueInputCount() > 3) {
1301 cur = NodeProperties::GetValueInput(node, 3);
1305 Builtins::Name builtin_eager =
1306 left ? Builtins::kArrayReducePreLoopEagerDeoptContinuation
1307 : Builtins::kArrayReduceRightPreLoopEagerDeoptContinuation;
1308 const std::vector<Node*> checkpoint_params(
1309 {receiver, fncallback, original_length});
1310 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1311 Node* find_first_element_frame_state =
1312 CreateJavaScriptBuiltinContinuationFrameState(
1313 jsgraph(), shared, builtin_eager, node->InputAt(0), context,
1314 checkpoint_params.data(), stack_parameters, outer_frame_state,
1315 ContinuationFrameStateMode::EAGER);
1317 Node* vloop = k = WireInLoopStart(k, &control, &effect);
1318 Node* loop = control;
1319 Node* eloop = effect;
1320 effect = graph()->NewNode(common()->Checkpoint(),
1321 find_first_element_frame_state, effect, control);
1322 Node* continue_test =
1323 left ? graph()->NewNode(simplified()->NumberLessThan(), k,
1325 : graph()->NewNode(simplified()->NumberLessThanOrEqual(),
1326 jsgraph()->ZeroConstant(), k);
1327 effect = graph()->NewNode(
1328 simplified()->CheckIf(DeoptimizeReason::kNoInitialElement),
1329 continue_test, effect, control);
1331 cur = SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
1332 Node* next_k = graph()->NewNode(next_op, k, jsgraph()->OneConstant());
1334 Node* hole_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1335 hole_check(cur), control);
1336 Node* found_el = graph()->NewNode(common()->IfFalse(), hole_branch);
1338 Node* is_hole = graph()->NewNode(common()->IfTrue(), hole_branch);
1340 WireInLoopEnd(loop, eloop, vloop, next_k, is_hole, effect);
1342 cur = effect = graph()->NewNode(common()->TypeGuard(Type::NonInternal()),
1343 cur, effect, control);
1348 Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
1349 Node* eloop = effect =
1350 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
1351 Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
1352 NodeProperties::MergeControlToEnd(graph(), common(), terminate);
1353 Node* kloop = k = graph()->NewNode(
1354 common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop);
1355 Node* curloop = cur = graph()->NewNode(
1356 common()->Phi(MachineRepresentation::kTagged, 2), cur, cur, loop);
1361 Node* continue_test =
1363 ? graph()->NewNode(simplified()->NumberLessThan(), k, original_length)
1364 : graph()->NewNode(simplified()->NumberLessThanOrEqual(),
1365 jsgraph()->ZeroConstant(), k);
1367 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1368 continue_test, control);
1370 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
1371 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
1375 Builtins::Name builtin_eager =
1376 left ? Builtins::kArrayReduceLoopEagerDeoptContinuation
1377 : Builtins::kArrayReduceRightLoopEagerDeoptContinuation;
1378 const std::vector<Node*> checkpoint_params(
1379 {receiver, fncallback, k, original_length, curloop});
1380 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1381 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1382 jsgraph(), shared, builtin_eager, node->InputAt(0), context,
1383 checkpoint_params.data(), stack_parameters, outer_frame_state,
1384 ContinuationFrameStateMode::EAGER);
1386 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
1390 effect = graph()->NewNode(
1391 simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
1395 SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
1397 Node* next_k = graph()->NewNode(next_op, k, jsgraph()->OneConstant());
1399 Node* hole_true =
nullptr;
1400 Node* hole_false =
nullptr;
1401 Node* effect_true = effect;
1403 if (IsHoleyElementsKind(kind)) {
1406 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1407 hole_check(element), control);
1408 hole_true = graph()->NewNode(common()->IfTrue(), branch);
1409 hole_false = graph()->NewNode(common()->IfFalse(), branch);
1410 control = hole_false;
1415 element = effect = graph()->NewNode(
1416 common()->TypeGuard(Type::NonInternal()), element, effect, control);
1421 Builtins::Name builtin_lazy =
1422 left ? Builtins::kArrayReduceLoopLazyDeoptContinuation
1423 : Builtins::kArrayReduceRightLoopLazyDeoptContinuation;
1424 const std::vector<Node*> checkpoint_params(
1425 {receiver, fncallback, next_k, original_length, curloop});
1426 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1427 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1428 jsgraph(), shared, builtin_lazy, node->InputAt(0), context,
1429 checkpoint_params.data(), stack_parameters - 1, outer_frame_state,
1430 ContinuationFrameStateMode::LAZY);
1432 next_cur = control = effect =
1433 graph()->NewNode(javascript()->Call(6, p.frequency()), fncallback,
1434 jsgraph()->UndefinedConstant(), cur, element, k,
1435 receiver, context, frame_state, effect, control);
1439 Node* on_exception =
nullptr;
1440 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
1441 RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
1442 &check_fail, &control);
1445 if (IsHoleyElementsKind(kind)) {
1446 Node* after_call_control = control;
1447 Node* after_call_effect = effect;
1448 control = hole_true;
1449 effect = effect_true;
1451 control = graph()->NewNode(common()->Merge(2), control, after_call_control);
1452 effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
1455 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), cur,
1462 loop->ReplaceInput(1, control);
1463 kloop->ReplaceInput(1, k);
1464 curloop->ReplaceInput(1, cur);
1465 eloop->ReplaceInput(1, effect);
1475 graph()->NewNode(common()->Throw(), check_throw, check_fail);
1476 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
1478 ReplaceWithValue(node, curloop, effect, control);
1479 return Replace(curloop);
1482 Reduction JSCallReducer::ReduceArrayMap(Node* node,
1483 const SharedFunctionInfoRef& shared) {
1484 if (!FLAG_turbo_inline_array_builtins)
return NoChange();
1485 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
1486 CallParameters
const& p = CallParametersOf(node->op());
1487 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
1491 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
1492 Node* effect = NodeProperties::GetEffectInput(node);
1493 Node* control = NodeProperties::GetControlInput(node);
1494 Node* context = NodeProperties::GetContextInput(node);
1497 Node* receiver = NodeProperties::GetValueInput(node, 1);
1498 Node* fncallback = node->op()->ValueInputCount() > 2
1499 ? NodeProperties::GetValueInput(node, 2)
1500 : jsgraph()->UndefinedConstant();
1501 Node* this_arg = node->op()->ValueInputCount() > 3
1502 ? NodeProperties::GetValueInput(node, 3)
1503 : jsgraph()->UndefinedConstant();
1504 ZoneHandleSet<Map> receiver_maps;
1505 NodeProperties::InferReceiverMapsResult result =
1506 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
1508 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
1511 if (!isolate()->IsArraySpeciesLookupChainIntact())
return NoChange();
1514 if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
1518 if (IsHoleyElementsKind(kind)) {
1519 dependencies()->DependOnProtector(
1520 PropertyCellRef(broker(), factory()->no_elements_protector()));
1523 dependencies()->DependOnProtector(
1524 PropertyCellRef(broker(), factory()->array_species_protector()));
1526 Node* array_constructor = jsgraph()->Constant(
1527 native_context().GetInitialJSArrayMap(kind).GetConstructor());
1529 Node* k = jsgraph()->ZeroConstant();
1532 if (result == NodeProperties::kUnreliableReceiverMaps) {
1534 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
1535 receiver_maps, p.feedback()),
1536 receiver, effect, control);
1539 Node* original_length = effect = graph()->NewNode(
1540 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
1545 Node* a = control = effect = graph()->NewNode(
1546 javascript()->CreateArray(1, MaybeHandle<AllocationSite>()),
1547 array_constructor, array_constructor, original_length, context,
1548 outer_frame_state, effect, control);
1550 std::vector<Node*> checkpoint_params(
1551 {receiver, fncallback, this_arg, a, k, original_length});
1552 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1556 Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1557 jsgraph(), shared, Builtins::kArrayMapLoopLazyDeoptContinuation,
1558 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1559 outer_frame_state, ContinuationFrameStateMode::LAZY);
1560 Node* check_fail =
nullptr;
1561 Node* check_throw =
nullptr;
1562 WireInCallbackIsCallableCheck(fncallback, context, check_frame_state, effect,
1563 &control, &check_fail, &check_throw);
1566 Node* vloop = k = WireInLoopStart(k, &control, &effect);
1567 Node *loop = control, *eloop = effect;
1568 checkpoint_params[4] = k;
1570 Node* continue_test =
1571 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
1572 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1573 continue_test, control);
1575 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
1576 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
1579 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1580 jsgraph(), shared, Builtins::kArrayMapLoopEagerDeoptContinuation,
1581 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1582 outer_frame_state, ContinuationFrameStateMode::EAGER);
1585 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
1589 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
1590 receiver_maps, p.feedback()),
1591 receiver, effect, control);
1594 SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
1597 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
1599 Node* hole_true =
nullptr;
1600 Node* hole_false =
nullptr;
1601 Node* effect_true = effect;
1603 if (IsHoleyElementsKind(kind)) {
1607 if (IsDoubleElementsKind(kind)) {
1608 check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
1610 check = graph()->NewNode(simplified()->ReferenceEqual(), element,
1611 jsgraph()->TheHoleConstant());
1614 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
1615 hole_true = graph()->NewNode(common()->IfTrue(), branch);
1616 hole_false = graph()->NewNode(common()->IfFalse(), branch);
1617 control = hole_false;
1622 element = effect = graph()->NewNode(
1623 common()->TypeGuard(Type::NonInternal()), element, effect, control);
1628 frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1629 jsgraph(), shared, Builtins::kArrayMapLoopLazyDeoptContinuation,
1630 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1631 outer_frame_state, ContinuationFrameStateMode::LAZY);
1633 Node* callback_value = control = effect = graph()->NewNode(
1634 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
1635 receiver, context, frame_state, effect, control);
1638 Node* on_exception =
nullptr;
1639 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
1640 RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
1641 &check_fail, &control);
1647 MapRef holey_double_map =
1648 native_context().GetInitialJSArrayMap(HOLEY_DOUBLE_ELEMENTS);
1649 MapRef holey_map = native_context().GetInitialJSArrayMap(HOLEY_ELEMENTS);
1650 effect = graph()->NewNode(simplified()->TransitionAndStoreElement(
1651 holey_double_map.object(), holey_map.object()),
1652 a, k, callback_value, effect, control);
1654 if (IsHoleyElementsKind(kind)) {
1655 Node* after_call_and_store_control = control;
1656 Node* after_call_and_store_effect = effect;
1657 control = hole_true;
1658 effect = effect_true;
1660 control = graph()->NewNode(common()->Merge(2), control,
1661 after_call_and_store_control);
1662 effect = graph()->NewNode(common()->EffectPhi(2), effect,
1663 after_call_and_store_effect, control);
1666 WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
1676 graph()->NewNode(common()->Throw(), check_throw, check_fail);
1677 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
1679 ReplaceWithValue(node, a, effect, control);
1683 Reduction JSCallReducer::ReduceArrayFilter(
1684 Node* node,
const SharedFunctionInfoRef& shared) {
1685 if (!FLAG_turbo_inline_array_builtins)
return NoChange();
1686 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
1687 CallParameters
const& p = CallParametersOf(node->op());
1688 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
1692 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
1693 Node* effect = NodeProperties::GetEffectInput(node);
1694 Node* control = NodeProperties::GetControlInput(node);
1695 Node* context = NodeProperties::GetContextInput(node);
1697 Node* receiver = NodeProperties::GetValueInput(node, 1);
1698 Node* fncallback = node->op()->ValueInputCount() > 2
1699 ? NodeProperties::GetValueInput(node, 2)
1700 : jsgraph()->UndefinedConstant();
1701 Node* this_arg = node->op()->ValueInputCount() > 3
1702 ? NodeProperties::GetValueInput(node, 3)
1703 : jsgraph()->UndefinedConstant();
1704 ZoneHandleSet<Map> receiver_maps;
1705 NodeProperties::InferReceiverMapsResult result =
1706 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
1708 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
1711 if (!isolate()->IsArraySpeciesLookupChainIntact())
return NoChange();
1714 if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
1719 const ElementsKind packed_kind = GetPackedElementsKind(kind);
1721 if (IsHoleyElementsKind(kind)) {
1722 dependencies()->DependOnProtector(
1723 PropertyCellRef(broker(), factory()->no_elements_protector()));
1726 dependencies()->DependOnProtector(
1727 PropertyCellRef(broker(), factory()->array_species_protector()));
1729 MapRef initial_map = native_context().GetInitialJSArrayMap(packed_kind);
1731 Node* k = jsgraph()->ZeroConstant();
1732 Node* to = jsgraph()->ZeroConstant();
1735 if (result == NodeProperties::kUnreliableReceiverMaps) {
1737 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
1738 receiver_maps, p.feedback()),
1739 receiver, effect, control);
1744 AllocationBuilder ab(jsgraph(), effect, control);
1745 ab.Allocate(initial_map.instance_size(), NOT_TENURED, Type::Array());
1746 ab.Store(AccessBuilder::ForMap(), initial_map);
1747 Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
1748 ab.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
1749 ab.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
1750 ab.Store(AccessBuilder::ForJSArrayLength(packed_kind),
1751 jsgraph()->ZeroConstant());
1752 for (
int i = 0;
i < initial_map.GetInObjectProperties(); ++
i) {
1753 ab.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map,
i),
1754 jsgraph()->UndefinedConstant());
1756 a = effect = ab.Finish();
1759 Node* original_length = effect = graph()->NewNode(
1760 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
1765 Node* check_fail =
nullptr;
1766 Node* check_throw =
nullptr;
1774 std::vector<Node*> checkpoint_params(
1775 {receiver, fncallback, this_arg, a, k, original_length, to, to});
1776 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1778 Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1779 jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
1780 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1781 outer_frame_state, ContinuationFrameStateMode::LAZY);
1782 WireInCallbackIsCallableCheck(fncallback, context, check_frame_state,
1783 effect, &control, &check_fail, &check_throw);
1787 Node* vloop = k = WireInLoopStart(k, &control, &effect);
1788 Node *loop = control, *eloop = effect;
1789 Node* v_to_loop = to = graph()->NewNode(
1790 common()->Phi(MachineRepresentation::kTaggedSigned, 2), to, to, loop);
1792 Node* continue_test =
1793 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
1794 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1795 continue_test, control);
1797 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
1798 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
1802 std::vector<Node*> checkpoint_params(
1803 {receiver, fncallback, this_arg, a, k, original_length, to});
1804 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1806 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1807 jsgraph(), shared, Builtins::kArrayFilterLoopEagerDeoptContinuation,
1808 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1809 outer_frame_state, ContinuationFrameStateMode::EAGER);
1812 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
1817 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
1818 receiver_maps, p.feedback()),
1819 receiver, effect, control);
1822 SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
1825 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
1827 Node* hole_true =
nullptr;
1828 Node* hole_false =
nullptr;
1829 Node* effect_true = effect;
1830 Node* hole_true_vto = to;
1832 if (IsHoleyElementsKind(kind)) {
1836 if (IsDoubleElementsKind(kind)) {
1837 check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
1839 check = graph()->NewNode(simplified()->ReferenceEqual(), element,
1840 jsgraph()->TheHoleConstant());
1843 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
1844 hole_true = graph()->NewNode(common()->IfTrue(), branch);
1845 hole_false = graph()->NewNode(common()->IfFalse(), branch);
1846 control = hole_false;
1851 element = effect = graph()->NewNode(
1852 common()->TypeGuard(Type::NonInternal()), element, effect, control);
1855 Node* callback_value =
nullptr;
1859 std::vector<Node*> checkpoint_params(
1860 {receiver, fncallback, this_arg, a, k, original_length, element, to});
1861 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1863 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1864 jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
1865 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1866 outer_frame_state, ContinuationFrameStateMode::LAZY);
1868 callback_value = control = effect = graph()->NewNode(
1869 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
1870 receiver, context, frame_state, effect, control);
1874 Node* on_exception =
nullptr;
1875 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
1876 RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
1877 &check_fail, &control);
1888 std::vector<Node*> checkpoint_params({receiver, fncallback, this_arg, a, k,
1889 original_length, element, to,
1891 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
1892 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
1893 jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
1894 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
1895 outer_frame_state, ContinuationFrameStateMode::EAGER);
1898 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
1904 to = DoFilterPostCallbackWork(packed_kind, &control, &effect, a, to, element,
1907 if (IsHoleyElementsKind(kind)) {
1908 Node* after_call_control = control;
1909 Node* after_call_effect = effect;
1910 control = hole_true;
1911 effect = effect_true;
1913 control = graph()->NewNode(common()->Merge(2), control, after_call_control);
1914 effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
1917 graph()->NewNode(common()->Phi(MachineRepresentation::kTaggedSigned, 2),
1918 hole_true_vto, to, control);
1921 WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
1922 v_to_loop->ReplaceInput(1, to);
1932 graph()->NewNode(common()->Throw(), check_throw, check_fail);
1933 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
1935 ReplaceWithValue(node, a, effect, control);
1939 Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
1940 const SharedFunctionInfoRef& shared) {
1941 if (!FLAG_turbo_inline_array_builtins)
return NoChange();
1942 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
1943 CallParameters
const& p = CallParametersOf(node->op());
1944 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
1948 Builtins::Name eager_continuation_builtin;
1949 Builtins::Name lazy_continuation_builtin;
1950 Builtins::Name after_callback_lazy_continuation_builtin;
1951 if (variant == ArrayFindVariant::kFind) {
1952 eager_continuation_builtin = Builtins::kArrayFindLoopEagerDeoptContinuation;
1953 lazy_continuation_builtin = Builtins::kArrayFindLoopLazyDeoptContinuation;
1954 after_callback_lazy_continuation_builtin =
1955 Builtins::kArrayFindLoopAfterCallbackLazyDeoptContinuation;
1957 DCHECK_EQ(ArrayFindVariant::kFindIndex, variant);
1958 eager_continuation_builtin =
1959 Builtins::kArrayFindIndexLoopEagerDeoptContinuation;
1960 lazy_continuation_builtin =
1961 Builtins::kArrayFindIndexLoopLazyDeoptContinuation;
1962 after_callback_lazy_continuation_builtin =
1963 Builtins::kArrayFindIndexLoopAfterCallbackLazyDeoptContinuation;
1966 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
1967 Node* effect = NodeProperties::GetEffectInput(node);
1968 Node* control = NodeProperties::GetControlInput(node);
1969 Node* context = NodeProperties::GetContextInput(node);
1972 Node* receiver = NodeProperties::GetValueInput(node, 1);
1973 Node* fncallback = node->op()->ValueInputCount() > 2
1974 ? NodeProperties::GetValueInput(node, 2)
1975 : jsgraph()->UndefinedConstant();
1976 Node* this_arg = node->op()->ValueInputCount() > 3
1977 ? NodeProperties::GetValueInput(node, 3)
1978 : jsgraph()->UndefinedConstant();
1979 ZoneHandleSet<Map> receiver_maps;
1980 NodeProperties::InferReceiverMapsResult result =
1981 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
1983 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
1986 if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
1992 dependencies()->DependOnProtector(
1993 PropertyCellRef(broker(), factory()->no_elements_protector()));
1996 if (result == NodeProperties::kUnreliableReceiverMaps) {
1998 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
1999 receiver_maps, p.feedback()),
2000 receiver, effect, control);
2003 Node* k = jsgraph()->ZeroConstant();
2005 Node* original_length = effect = graph()->NewNode(
2006 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
2009 std::vector<Node*> checkpoint_params(
2010 {receiver, fncallback, this_arg, k, original_length});
2011 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
2015 Node* check_fail =
nullptr;
2016 Node* check_throw =
nullptr;
2018 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2019 jsgraph(), shared, lazy_continuation_builtin, node->InputAt(0), context,
2020 &checkpoint_params[0], stack_parameters, outer_frame_state,
2021 ContinuationFrameStateMode::LAZY);
2022 WireInCallbackIsCallableCheck(fncallback, context, frame_state, effect,
2023 &control, &check_fail, &check_throw);
2027 Node* vloop = k = WireInLoopStart(k, &control, &effect);
2028 Node *loop = control, *eloop = effect;
2029 checkpoint_params[3] = k;
2032 Node* if_false =
nullptr;
2034 Node* continue_test =
2035 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
2036 Node* continue_branch = graph()->NewNode(
2037 common()->Branch(BranchHint::kTrue), continue_test, control);
2038 control = graph()->NewNode(common()->IfTrue(), continue_branch);
2039 if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
2044 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2045 jsgraph(), shared, eager_continuation_builtin, node->InputAt(0),
2046 context, &checkpoint_params[0], stack_parameters, outer_frame_state,
2047 ContinuationFrameStateMode::EAGER);
2050 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
2053 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
2054 receiver_maps, p.feedback()),
2055 receiver, effect, control);
2060 SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
2063 Node* next_k = checkpoint_params[3] =
2064 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
2067 if (kind == HOLEY_DOUBLE_ELEMENTS) {
2069 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
2071 graph()->NewNode(simplified()->CheckFloat64Hole(mode, p.feedback()),
2072 element, effect, control);
2073 }
else if (IsHoleyElementsKind(kind)) {
2075 graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), element);
2078 Node* if_found_return_value =
2079 (variant == ArrayFindVariant::kFind) ? element : k;
2082 Node* callback_value =
nullptr;
2084 std::vector<Node*> call_checkpoint_params({receiver, fncallback, this_arg,
2085 next_k, original_length,
2086 if_found_return_value});
2087 const int call_stack_parameters =
2088 static_cast<int>(call_checkpoint_params.size());
2090 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2091 jsgraph(), shared, after_callback_lazy_continuation_builtin,
2092 node->InputAt(0), context, &call_checkpoint_params[0],
2093 call_stack_parameters, outer_frame_state,
2094 ContinuationFrameStateMode::LAZY);
2096 callback_value = control = effect = graph()->NewNode(
2097 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
2098 receiver, context, frame_state, effect, control);
2102 Node* on_exception =
nullptr;
2103 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
2104 RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
2105 &check_fail, &control);
2109 Node* boolean_result =
2110 graph()->NewNode(simplified()->ToBoolean(), callback_value);
2111 Node* efound_branch = effect;
2112 Node* found_branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2113 boolean_result, control);
2114 Node* if_found = graph()->NewNode(common()->IfTrue(), found_branch);
2115 Node* if_notfound = graph()->NewNode(common()->IfFalse(), found_branch);
2116 control = if_notfound;
2119 WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
2121 control = graph()->NewNode(common()->Merge(2), if_found, if_false);
2123 graph()->NewNode(common()->EffectPhi(2), efound_branch, eloop, control);
2125 Node* if_not_found_value = (variant == ArrayFindVariant::kFind)
2126 ? jsgraph()->UndefinedConstant()
2127 : jsgraph()->MinusOneConstant();
2129 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2130 if_found_return_value, if_not_found_value, control);
2134 control = graph()->NewNode(common()->LoopExit(), control, loop);
2135 effect = graph()->NewNode(common()->LoopExitEffect(), effect, control);
2136 value = graph()->NewNode(common()->LoopExitValue(), value, control);
2143 graph()->NewNode(common()->Throw(), check_throw, check_fail);
2144 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
2146 ReplaceWithValue(node, value, effect, control);
2147 return Replace(value);
2150 Node* JSCallReducer::DoFilterPostCallbackWork(ElementsKind kind, Node** control,
2151 Node** effect, Node* a, Node* to,
2153 Node* callback_value) {
2154 Node* boolean_result =
2155 graph()->NewNode(simplified()->ToBoolean(), callback_value);
2156 Node* boolean_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2157 boolean_result, *control);
2159 Node* if_true = graph()->NewNode(common()->IfTrue(), boolean_branch);
2160 Node* etrue = *effect;
2164 Node* elements = etrue = graph()->NewNode(
2165 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), a, etrue,
2168 DCHECK(TypeCache::Get().kFixedDoubleArrayLengthType.Is(
2169 TypeCache::Get().kFixedArrayLengthType));
2170 Node* checked_to = etrue = graph()->NewNode(
2171 common()->TypeGuard(TypeCache::Get().kFixedArrayLengthType), to, etrue,
2173 Node* elements_length = etrue = graph()->NewNode(
2174 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), elements,
2177 GrowFastElementsMode mode =
2178 IsDoubleElementsKind(kind) ? GrowFastElementsMode::kDoubleElements
2179 : GrowFastElementsMode::kSmiOrObjectElements;
2180 elements = etrue = graph()->NewNode(
2181 simplified()->MaybeGrowFastElements(mode, VectorSlotPair()), a,
2182 elements, checked_to, elements_length, etrue, if_true);
2185 Node* new_length_a = graph()->NewNode(simplified()->NumberAdd(), checked_to,
2186 jsgraph()->OneConstant());
2188 etrue = graph()->NewNode(
2189 simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)), a,
2190 new_length_a, etrue, if_true);
2193 etrue = graph()->NewNode(
2194 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(kind)),
2195 elements, checked_to, element, etrue, if_true);
2197 vtrue = new_length_a;
2200 Node* if_false = graph()->NewNode(common()->IfFalse(), boolean_branch);
2201 Node* efalse = *effect;
2204 *control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2205 *effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, *control);
2206 to = graph()->NewNode(common()->Phi(MachineRepresentation::kTaggedSigned, 2),
2207 vtrue, vfalse, *control);
2211 void JSCallReducer::WireInCallbackIsCallableCheck(
2212 Node* fncallback, Node* context, Node* check_frame_state, Node* effect,
2213 Node** control, Node** check_fail, Node** check_throw) {
2214 Node* check = graph()->NewNode(simplified()->ObjectIsCallable(), fncallback);
2215 Node* check_branch =
2216 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, *control);
2217 *check_fail = graph()->NewNode(common()->IfFalse(), check_branch);
2218 *check_throw = *check_fail = graph()->NewNode(
2219 javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
2220 jsgraph()->Constant(
2221 static_cast<int>(MessageTemplate::kCalledNonCallable)),
2222 fncallback, context, check_frame_state, effect, *check_fail);
2223 *control = graph()->NewNode(common()->IfTrue(), check_branch);
2226 void JSCallReducer::RewirePostCallbackExceptionEdges(Node* check_throw,
2232 Node* if_exception0 =
2233 graph()->NewNode(common()->IfException(), check_throw, *check_fail);
2234 *check_fail = graph()->NewNode(common()->IfSuccess(), *check_fail);
2235 Node* if_exception1 =
2236 graph()->NewNode(common()->IfException(), effect, *control);
2237 *control = graph()->NewNode(common()->IfSuccess(), *control);
2241 graph()->NewNode(common()->Merge(2), if_exception0, if_exception1);
2242 Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception0,
2243 if_exception1, merge);
2244 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2245 if_exception0, if_exception1, merge);
2246 ReplaceWithValue(on_exception, phi, ephi, merge);
2249 Node* JSCallReducer::SafeLoadElement(ElementsKind kind, Node* receiver,
2250 Node* control, Node** effect, Node** k,
2251 const VectorSlotPair& feedback) {
2254 Node* length = *effect = graph()->NewNode(
2255 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
2257 *k = *effect = graph()->NewNode(simplified()->CheckBounds(feedback), *k,
2258 length, *effect, control);
2263 Node* elements = *effect = graph()->NewNode(
2264 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
2267 Node* element = *effect = graph()->NewNode(
2268 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(
2269 kind, LoadSensitivity::kCritical)),
2270 elements, *k, *effect, control);
2274 Reduction JSCallReducer::ReduceArrayEvery(Node* node,
2275 const SharedFunctionInfoRef& shared) {
2276 if (!FLAG_turbo_inline_array_builtins)
return NoChange();
2277 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
2278 CallParameters
const& p = CallParametersOf(node->op());
2279 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
2283 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
2284 Node* effect = NodeProperties::GetEffectInput(node);
2285 Node* control = NodeProperties::GetControlInput(node);
2286 Node* context = NodeProperties::GetContextInput(node);
2288 Node* receiver = NodeProperties::GetValueInput(node, 1);
2289 Node* fncallback = node->op()->ValueInputCount() > 2
2290 ? NodeProperties::GetValueInput(node, 2)
2291 : jsgraph()->UndefinedConstant();
2292 Node* this_arg = node->op()->ValueInputCount() > 3
2293 ? NodeProperties::GetValueInput(node, 3)
2294 : jsgraph()->UndefinedConstant();
2295 ZoneHandleSet<Map> receiver_maps;
2296 NodeProperties::InferReceiverMapsResult result =
2297 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
2299 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
2302 if (!isolate()->IsArraySpeciesLookupChainIntact())
return NoChange();
2305 if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
2309 if (IsHoleyElementsKind(kind)) {
2310 dependencies()->DependOnProtector(
2311 PropertyCellRef(broker(), factory()->no_elements_protector()));
2314 dependencies()->DependOnProtector(
2315 PropertyCellRef(broker(), factory()->array_species_protector()));
2318 if (result == NodeProperties::kUnreliableReceiverMaps) {
2320 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
2321 receiver_maps, p.feedback()),
2322 receiver, effect, control);
2325 Node* k = jsgraph()->ZeroConstant();
2328 effect = graph()->NewNode(
2329 simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
2332 Node* original_length = effect = graph()->NewNode(
2333 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
2338 Node* check_fail =
nullptr;
2339 Node* check_throw =
nullptr;
2344 std::vector<Node*> checkpoint_params(
2345 {receiver, fncallback, this_arg, k, original_length});
2346 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
2348 Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2349 jsgraph(), shared, Builtins::kArrayEveryLoopLazyDeoptContinuation,
2350 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
2351 outer_frame_state, ContinuationFrameStateMode::LAZY);
2352 WireInCallbackIsCallableCheck(fncallback, context, check_frame_state,
2353 effect, &control, &check_fail, &check_throw);
2357 Node* vloop = k = WireInLoopStart(k, &control, &effect);
2358 Node *loop = control, *eloop = effect;
2360 Node* continue_test =
2361 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
2362 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2363 continue_test, control);
2365 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
2366 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
2370 std::vector<Node*> checkpoint_params(
2371 {receiver, fncallback, this_arg, k, original_length});
2372 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
2374 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2375 jsgraph(), shared, Builtins::kArrayEveryLoopEagerDeoptContinuation,
2376 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
2377 outer_frame_state, ContinuationFrameStateMode::EAGER);
2380 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
2385 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
2386 receiver_maps, p.feedback()),
2387 receiver, effect, control);
2390 SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
2393 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
2395 Node* hole_true =
nullptr;
2396 Node* hole_false =
nullptr;
2397 Node* effect_true = effect;
2399 if (IsHoleyElementsKind(kind)) {
2403 if (IsDoubleElementsKind(kind)) {
2404 check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
2406 check = graph()->NewNode(simplified()->ReferenceEqual(), element,
2407 jsgraph()->TheHoleConstant());
2410 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
2411 hole_true = graph()->NewNode(common()->IfTrue(), branch);
2412 hole_false = graph()->NewNode(common()->IfFalse(), branch);
2413 control = hole_false;
2418 element = effect = graph()->NewNode(
2419 common()->TypeGuard(Type::NonInternal()), element, effect, control);
2422 Node* callback_value =
nullptr;
2426 std::vector<Node*> checkpoint_params(
2427 {receiver, fncallback, this_arg, k, original_length});
2428 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
2430 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2431 jsgraph(), shared, Builtins::kArrayEveryLoopLazyDeoptContinuation,
2432 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
2433 outer_frame_state, ContinuationFrameStateMode::LAZY);
2435 callback_value = control = effect = graph()->NewNode(
2436 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
2437 receiver, context, frame_state, effect, control);
2441 Node* on_exception =
nullptr;
2442 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
2443 RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
2444 &check_fail, &control);
2448 Node* if_false_callback;
2449 Node* efalse_callback;
2451 Node* boolean_result =
2452 graph()->NewNode(simplified()->ToBoolean(), callback_value);
2453 Node* boolean_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2454 boolean_result, control);
2455 if_false_callback = graph()->NewNode(common()->IfFalse(), boolean_branch);
2456 efalse_callback = effect;
2459 control = graph()->NewNode(common()->IfTrue(), boolean_branch);
2462 if (IsHoleyElementsKind(kind)) {
2463 Node* after_call_control = control;
2464 Node* after_call_effect = effect;
2465 control = hole_true;
2466 effect = effect_true;
2468 control = graph()->NewNode(common()->Merge(2), control, after_call_control);
2469 effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
2473 WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
2475 control = graph()->NewNode(common()->Merge(2), if_false, if_false_callback);
2477 graph()->NewNode(common()->EffectPhi(2), eloop, efalse_callback, control);
2478 Node* value = graph()->NewNode(
2479 common()->Phi(MachineRepresentation::kTagged, 2),
2480 jsgraph()->TrueConstant(), jsgraph()->FalseConstant(), control);
2484 control = graph()->NewNode(common()->LoopExit(), control, loop);
2485 effect = graph()->NewNode(common()->LoopExitEffect(), effect, control);
2486 value = graph()->NewNode(common()->LoopExitValue(), value, control);
2493 graph()->NewNode(common()->Throw(), check_throw, check_fail);
2494 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
2496 ReplaceWithValue(node, value, effect, control);
2497 return Replace(value);
2504 Callable GetCallableForArrayIndexOf(ElementsKind elements_kind,
2506 switch (elements_kind) {
2507 case PACKED_SMI_ELEMENTS:
2508 case HOLEY_SMI_ELEMENTS:
2509 case PACKED_ELEMENTS:
2510 case HOLEY_ELEMENTS:
2511 return Builtins::CallableFor(isolate, Builtins::kArrayIndexOfSmiOrObject);
2512 case PACKED_DOUBLE_ELEMENTS:
2513 return Builtins::CallableFor(isolate,
2514 Builtins::kArrayIndexOfPackedDoubles);
2516 DCHECK_EQ(HOLEY_DOUBLE_ELEMENTS, elements_kind);
2517 return Builtins::CallableFor(isolate,
2518 Builtins::kArrayIndexOfHoleyDoubles);
2524 Callable GetCallableForArrayIncludes(ElementsKind elements_kind,
2526 switch (elements_kind) {
2527 case PACKED_SMI_ELEMENTS:
2528 case HOLEY_SMI_ELEMENTS:
2529 case PACKED_ELEMENTS:
2530 case HOLEY_ELEMENTS:
2531 return Builtins::CallableFor(isolate,
2532 Builtins::kArrayIncludesSmiOrObject);
2533 case PACKED_DOUBLE_ELEMENTS:
2534 return Builtins::CallableFor(isolate,
2535 Builtins::kArrayIncludesPackedDoubles);
2537 DCHECK_EQ(HOLEY_DOUBLE_ELEMENTS, elements_kind);
2538 return Builtins::CallableFor(isolate,
2539 Builtins::kArrayIncludesHoleyDoubles);
2551 Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
2552 SearchVariant search_variant, Node* node) {
2553 CallParameters
const& p = CallParametersOf(node->op());
2554 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
2559 if (!NodeProperties::GetMapWitness(broker(), node).ToHandle(&map))
2562 MapRef receiver_map(broker(), map);
2563 if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
2566 ElementsKind
const elements_kind = receiver_map.elements_kind();
2567 if (IsHoleyElementsKind(elements_kind)) {
2568 dependencies()->DependOnProtector(
2569 PropertyCellRef(broker(), factory()->no_elements_protector()));
2572 Callable
const callable =
2573 search_variant == SearchVariant::kIndexOf
2574 ? GetCallableForArrayIndexOf(elements_kind, isolate())
2575 : GetCallableForArrayIncludes(elements_kind, isolate());
2576 CallDescriptor
const*
const desc = Linkage::GetStubCallDescriptor(
2577 graph()->zone(), callable.descriptor(),
2578 callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
2579 Operator::kEliminatable);
2583 Node* receiver = NodeProperties::GetValueInput(node, 1);
2584 Node* effect = NodeProperties::GetEffectInput(node);
2585 Node* control = NodeProperties::GetControlInput(node);
2586 Node* elements = effect = graph()->NewNode(
2587 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
2589 Node* search_element = (node->op()->ValueInputCount() >= 3)
2590 ? NodeProperties::GetValueInput(node, 2)
2591 : jsgraph()->UndefinedConstant();
2592 Node* length = effect = graph()->NewNode(
2593 simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
2594 receiver, effect, control);
2595 Node* new_from_index = jsgraph()->ZeroConstant();
2596 if (node->op()->ValueInputCount() >= 4) {
2597 Node* from_index = NodeProperties::GetValueInput(node, 3);
2598 from_index = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
2599 from_index, effect, control);
2603 new_from_index = graph()->NewNode(
2604 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
2605 graph()->NewNode(simplified()->NumberLessThan(), from_index,
2606 jsgraph()->ZeroConstant()),
2608 simplified()->NumberMax(),
2609 graph()->NewNode(simplified()->NumberAdd(), length, from_index),
2610 jsgraph()->ZeroConstant()),
2614 Node* context = NodeProperties::GetContextInput(node);
2615 Node* replacement_node = effect = graph()->NewNode(
2616 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), elements,
2617 search_element, length, new_from_index, context, effect);
2618 ReplaceWithValue(node, replacement_node, effect);
2619 return Replace(replacement_node);
2622 Reduction JSCallReducer::ReduceArraySome(Node* node,
2623 const SharedFunctionInfoRef& shared) {
2624 if (!FLAG_turbo_inline_array_builtins)
return NoChange();
2625 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
2626 CallParameters
const& p = CallParametersOf(node->op());
2627 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
2631 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
2632 Node* effect = NodeProperties::GetEffectInput(node);
2633 Node* control = NodeProperties::GetControlInput(node);
2634 Node* context = NodeProperties::GetContextInput(node);
2636 Node* receiver = NodeProperties::GetValueInput(node, 1);
2637 Node* fncallback = node->op()->ValueInputCount() > 2
2638 ? NodeProperties::GetValueInput(node, 2)
2639 : jsgraph()->UndefinedConstant();
2640 Node* this_arg = node->op()->ValueInputCount() > 3
2641 ? NodeProperties::GetValueInput(node, 3)
2642 : jsgraph()->UndefinedConstant();
2643 ZoneHandleSet<Map> receiver_maps;
2644 NodeProperties::InferReceiverMapsResult result =
2645 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
2647 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
2650 if (!isolate()->IsArraySpeciesLookupChainIntact())
return NoChange();
2653 if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
2657 if (IsHoleyElementsKind(kind)) {
2658 dependencies()->DependOnProtector(
2659 PropertyCellRef(broker(), factory()->no_elements_protector()));
2662 dependencies()->DependOnProtector(
2663 PropertyCellRef(broker(), factory()->array_species_protector()));
2665 Node* k = jsgraph()->ZeroConstant();
2668 if (result == NodeProperties::kUnreliableReceiverMaps) {
2670 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
2671 receiver_maps, p.feedback()),
2672 receiver, effect, control);
2676 effect = graph()->NewNode(
2677 simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
2680 Node* original_length = effect = graph()->NewNode(
2681 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
2686 Node* check_fail =
nullptr;
2687 Node* check_throw =
nullptr;
2692 std::vector<Node*> checkpoint_params(
2693 {receiver, fncallback, this_arg, k, original_length});
2694 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
2696 Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2697 jsgraph(), shared, Builtins::kArraySomeLoopLazyDeoptContinuation,
2698 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
2699 outer_frame_state, ContinuationFrameStateMode::LAZY);
2700 WireInCallbackIsCallableCheck(fncallback, context, check_frame_state,
2701 effect, &control, &check_fail, &check_throw);
2705 Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
2706 Node* eloop = effect =
2707 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
2708 Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
2709 NodeProperties::MergeControlToEnd(graph(), common(), terminate);
2710 Node* vloop = k = graph()->NewNode(
2711 common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop);
2713 Node* continue_test =
2714 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
2715 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2716 continue_test, control);
2718 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
2719 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
2723 std::vector<Node*> checkpoint_params(
2724 {receiver, fncallback, this_arg, k, original_length});
2725 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
2727 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2728 jsgraph(), shared, Builtins::kArraySomeLoopEagerDeoptContinuation,
2729 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
2730 outer_frame_state, ContinuationFrameStateMode::EAGER);
2733 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
2738 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
2739 receiver_maps, p.feedback()),
2740 receiver, effect, control);
2743 SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
2746 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
2748 Node* hole_true =
nullptr;
2749 Node* hole_false =
nullptr;
2750 Node* effect_true = effect;
2752 if (IsHoleyElementsKind(kind)) {
2756 if (IsDoubleElementsKind(kind)) {
2757 check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
2759 check = graph()->NewNode(simplified()->ReferenceEqual(), element,
2760 jsgraph()->TheHoleConstant());
2763 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
2764 hole_true = graph()->NewNode(common()->IfTrue(), branch);
2765 hole_false = graph()->NewNode(common()->IfFalse(), branch);
2766 control = hole_false;
2771 element = effect = graph()->NewNode(
2772 common()->TypeGuard(Type::NonInternal()), element, effect, control);
2775 Node* callback_value =
nullptr;
2779 std::vector<Node*> checkpoint_params(
2780 {receiver, fncallback, this_arg, k, original_length});
2781 const int stack_parameters =
static_cast<int>(checkpoint_params.size());
2783 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
2784 jsgraph(), shared, Builtins::kArraySomeLoopLazyDeoptContinuation,
2785 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
2786 outer_frame_state, ContinuationFrameStateMode::LAZY);
2788 callback_value = control = effect = graph()->NewNode(
2789 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
2790 receiver, context, frame_state, effect, control);
2794 Node* on_exception =
nullptr;
2795 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
2796 RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
2797 &check_fail, &control);
2801 Node* if_true_callback;
2802 Node* etrue_callback;
2804 Node* boolean_result =
2805 graph()->NewNode(simplified()->ToBoolean(), callback_value);
2806 Node* boolean_branch = graph()->NewNode(
2807 common()->Branch(BranchHint::kFalse), boolean_result, control);
2808 if_true_callback = graph()->NewNode(common()->IfTrue(), boolean_branch);
2809 etrue_callback = effect;
2812 control = graph()->NewNode(common()->IfFalse(), boolean_branch);
2815 if (IsHoleyElementsKind(kind)) {
2816 Node* after_call_control = control;
2817 Node* after_call_effect = effect;
2818 control = hole_true;
2819 effect = effect_true;
2821 control = graph()->NewNode(common()->Merge(2), control, after_call_control);
2822 effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
2826 loop->ReplaceInput(1, control);
2827 vloop->ReplaceInput(1, next_k);
2828 eloop->ReplaceInput(1, effect);
2830 control = graph()->NewNode(common()->Merge(2), if_false, if_true_callback);
2832 graph()->NewNode(common()->EffectPhi(2), eloop, etrue_callback, control);
2833 Node* value = graph()->NewNode(
2834 common()->Phi(MachineRepresentation::kTagged, 2),
2835 jsgraph()->FalseConstant(), jsgraph()->TrueConstant(), control);
2839 control = graph()->NewNode(common()->LoopExit(), control, loop);
2840 effect = graph()->NewNode(common()->LoopExitEffect(), effect, control);
2841 value = graph()->NewNode(common()->LoopExitValue(), value, control);
2848 graph()->NewNode(common()->Throw(), check_throw, check_fail);
2849 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
2851 ReplaceWithValue(node, value, effect, control);
2852 return Replace(value);
2855 Reduction JSCallReducer::ReduceCallApiFunction(
2856 Node* node,
const SharedFunctionInfoRef& shared) {
2857 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
2858 CallParameters
const& p = CallParametersOf(node->op());
2859 int const argc =
static_cast<int>(p.arity()) - 2;
2860 Node* target = NodeProperties::GetValueInput(node, 0);
2862 (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
2863 ? jsgraph()->Constant(native_context().global_proxy_object())
2864 : NodeProperties::GetValueInput(node, 1);
2865 Node* effect = NodeProperties::GetEffectInput(node);
2866 Node* control = NodeProperties::GetControlInput(node);
2868 Handle<FunctionTemplateInfo> function_template_info(
2869 FunctionTemplateInfo::cast(shared.object()->function_data()), isolate());
2874 if (argc > CallApiCallbackStub::kArgMax)
return NoChange();
2878 ZoneHandleSet<Map> receiver_maps;
2879 NodeProperties::InferReceiverMapsResult result =
2880 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
2882 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
2883 for (Handle<Map> map : receiver_maps) {
2884 MapRef receiver_map(broker(), map);
2885 if (!receiver_map.IsJSObjectMap() ||
2886 (!function_template_info->accept_any_receiver() &&
2887 receiver_map.is_access_check_needed())) {
2892 if (result == NodeProperties::kUnreliableReceiverMaps) {
2893 if (!receiver_map.is_stable())
return NoChange();
2898 CallOptimization call_optimization(isolate(), function_template_info);
2899 if (!call_optimization.is_simple_api_call())
return NoChange();
2900 CallOptimization::HolderLookup lookup;
2901 Handle<JSObject> api_holder =
2902 call_optimization.LookupHolderOfExpectedType(receiver_maps[0], &lookup);
2903 if (lookup == CallOptimization::kHolderNotFound)
return NoChange();
2904 for (
size_t i = 1;
i < receiver_maps.size(); ++
i) {
2905 CallOptimization::HolderLookup lookupi;
2906 Handle<JSObject> holder = call_optimization.LookupHolderOfExpectedType(
2907 receiver_maps[
i], &lookupi);
2908 if (lookup != lookupi)
return NoChange();
2909 if (!api_holder.is_identical_to(holder))
return NoChange();
2913 if (result == NodeProperties::kUnreliableReceiverMaps) {
2914 for (Handle<Map> map : receiver_maps) {
2915 MapRef receiver_map(broker(), map);
2916 dependencies()->DependOnStableMap(receiver_map);
2921 Node* context = effect = graph()->NewNode(
2922 simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
2930 Handle<CallHandlerInfo> call_handler_info(
2931 CallHandlerInfo::cast(function_template_info->call_code()), isolate());
2932 Handle<Object> data(call_handler_info->data(), isolate());
2933 Callable call_api_callback = CodeFactory::CallApiCallback(isolate(), argc);
2934 CallInterfaceDescriptor cid = call_api_callback.descriptor();
2935 auto call_descriptor = Linkage::GetStubCallDescriptor(
2936 graph()->zone(), cid,
2937 cid.GetStackParameterCount() + argc + 1 ,
2938 CallDescriptor::kNeedsFrameState);
2939 ApiFunction api_function(v8::ToCData<Address>(call_handler_info->callback()));
2940 Node* holder = lookup == CallOptimization::kHolderFound
2941 ? jsgraph()->HeapConstant(api_holder)
2943 ExternalReference function_reference = ExternalReference::Create(
2944 &api_function, ExternalReference::DIRECT_API_CALL);
2945 node->InsertInput(graph()->zone(), 0,
2946 jsgraph()->HeapConstant(call_api_callback.code()));
2947 node->ReplaceInput(1, context);
2948 node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(data));
2949 node->InsertInput(graph()->zone(), 3, holder);
2950 node->InsertInput(graph()->zone(), 4,
2951 jsgraph()->ExternalConstant(function_reference));
2952 node->ReplaceInput(5, receiver);
2953 node->RemoveInput(6 + argc);
2954 node->ReplaceInput(7 + argc, effect);
2955 NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
2956 return Changed(node);
2963 bool IsSafeArgumentsElements(Node* node) {
2964 for (Edge
const edge : node->use_edges()) {
2965 if (!NodeProperties::IsValueEdge(edge))
continue;
2966 if (edge.from()->opcode() != IrOpcode::kLoadField &&
2967 edge.from()->opcode() != IrOpcode::kLoadElement) {
2976 Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
2977 Node* node,
int arity, CallFrequency
const& frequency,
2978 VectorSlotPair
const& feedback) {
2979 DCHECK(node->opcode() == IrOpcode::kJSCallWithArrayLike ||
2980 node->opcode() == IrOpcode::kJSCallWithSpread ||
2981 node->opcode() == IrOpcode::kJSConstructWithArrayLike ||
2982 node->opcode() == IrOpcode::kJSConstructWithSpread);
2986 if ((node->opcode() == IrOpcode::kJSCallWithSpread ||
2987 node->opcode() == IrOpcode::kJSConstructWithSpread) &&
2988 !isolate()->IsArrayIteratorLookupChainIntact()) {
2994 Node* arguments_list = NodeProperties::GetValueInput(node, arity);
2995 if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) {
2998 for (Edge edge : arguments_list->use_edges()) {
2999 if (!NodeProperties::IsValueEdge(edge))
continue;
3000 Node*
const user = edge.from();
3001 switch (user->opcode()) {
3002 case IrOpcode::kCheckMaps:
3003 case IrOpcode::kFrameState:
3004 case IrOpcode::kStateValues:
3005 case IrOpcode::kReferenceEqual:
3006 case IrOpcode::kReturn:
3009 case IrOpcode::kLoadField: {
3010 DCHECK_EQ(arguments_list, user->InputAt(0));
3011 FieldAccess
const& access = FieldAccessOf(user->op());
3012 if (access.offset == JSArray::kLengthOffset) {
3015 static_cast<int>(JSArray::kLengthOffset) ==
3016 static_cast<int>(JSArgumentsObjectWithLength::kLengthOffset));
3018 }
else if (access.offset == JSObject::kElementsOffset) {
3020 if (IsSafeArgumentsElements(user))
continue;
3024 case IrOpcode::kJSCallWithArrayLike:
3026 if (user->InputAt(2) == arguments_list)
continue;
3028 case IrOpcode::kJSConstructWithArrayLike:
3030 if (user->InputAt(1) == arguments_list)
continue;
3032 case IrOpcode::kJSCallWithSpread: {
3034 CallParameters p = CallParametersOf(user->op());
3035 int const arity =
static_cast<int>(p.arity() - 1);
3036 if (user->InputAt(arity) == arguments_list)
continue;
3039 case IrOpcode::kJSConstructWithSpread: {
3041 ConstructParameters p = ConstructParametersOf(user->op());
3042 int const arity =
static_cast<int>(p.arity() - 2);
3043 if (user->InputAt(arity) == arguments_list)
continue;
3052 waitlist_.insert(node);
3059 CreateArgumentsType
const type = CreateArgumentsTypeOf(arguments_list->op());
3060 Node* frame_state = NodeProperties::GetFrameStateInput(arguments_list);
3061 FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
3062 int start_index = 0;
3064 int formal_parameter_count;
3066 Handle<SharedFunctionInfo> shared;
3067 if (!state_info.shared_info().ToHandle(&shared))
return NoChange();
3068 formal_parameter_count = SharedFunctionInfoRef(broker(), shared)
3069 .internal_formal_parameter_count();
3072 if (type == CreateArgumentsType::kMappedArguments) {
3076 if (formal_parameter_count != 0) {
3077 Node* effect = NodeProperties::GetEffectInput(node);
3078 if (!NodeProperties::NoObservableSideEffectBetween(effect,
3083 }
else if (type == CreateArgumentsType::kRestParameter) {
3084 start_index = formal_parameter_count;
3090 if (node->opcode() == IrOpcode::kJSCallWithSpread ||
3091 node->opcode() == IrOpcode::kJSConstructWithSpread) {
3092 dependencies()->DependOnProtector(
3093 PropertyCellRef(broker(), factory()->array_iterator_protector()));
3097 node->RemoveInput(arity--);
3100 Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
3101 if (outer_state->opcode() != IrOpcode::kFrameState) {
3102 Operator
const* op =
3103 (node->opcode() == IrOpcode::kJSCallWithArrayLike ||
3104 node->opcode() == IrOpcode::kJSCallWithSpread)
3105 ? javascript()->CallForwardVarargs(arity + 1, start_index)
3106 : javascript()->ConstructForwardVarargs(arity + 2, start_index);
3107 NodeProperties::ChangeOp(node, op);
3108 return Changed(node);
3113 FrameStateInfo outer_info = FrameStateInfoOf(outer_state->op());
3114 if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
3116 frame_state = outer_state;
3119 Node*
const parameters = frame_state->InputAt(kFrameStateParametersInput);
3120 for (
int i = start_index + 1;
i < parameters->InputCount(); ++
i) {
3121 node->InsertInput(graph()->zone(), static_cast<int>(++arity),
3122 parameters->InputAt(
i));
3125 if (node->opcode() == IrOpcode::kJSCallWithArrayLike ||
3126 node->opcode() == IrOpcode::kJSCallWithSpread) {
3127 NodeProperties::ChangeOp(
3128 node, javascript()->Call(arity + 1, frequency, feedback));
3129 Reduction
const reduction = ReduceJSCall(node);
3130 return reduction.Changed() ? reduction : Changed(node);
3132 NodeProperties::ChangeOp(
3133 node, javascript()->Construct(arity + 2, frequency, feedback));
3134 Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
3135 Node* frame_state = NodeProperties::GetFrameStateInput(node);
3136 Node* context = NodeProperties::GetContextInput(node);
3137 Node* effect = NodeProperties::GetEffectInput(node);
3138 Node* control = NodeProperties::GetControlInput(node);
3144 graph()->NewNode(simplified()->ObjectIsConstructor(), new_target);
3145 Node* check_branch =
3146 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
3147 Node* check_fail = graph()->NewNode(common()->IfFalse(), check_branch);
3148 Node* check_throw = check_fail = graph()->NewNode(
3149 javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
3150 jsgraph()->Constant(static_cast<int>(MessageTemplate::kNotConstructor)),
3151 new_target, context, frame_state, effect, check_fail);
3152 control = graph()->NewNode(common()->IfTrue(), check_branch);
3153 NodeProperties::ReplaceControlInput(node, control);
3156 Node* on_exception =
nullptr;
3157 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
3159 Node* if_exception =
3160 graph()->NewNode(common()->IfException(), check_throw, check_fail);
3161 check_fail = graph()->NewNode(common()->IfSuccess(), check_fail);
3165 graph()->NewNode(common()->Merge(2), if_exception, on_exception);
3166 Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception,
3167 on_exception, merge);
3169 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
3170 if_exception, on_exception, merge);
3171 ReplaceWithValue(on_exception, phi, ephi, merge);
3172 merge->ReplaceInput(1, on_exception);
3173 ephi->ReplaceInput(1, on_exception);
3174 phi->ReplaceInput(1, on_exception);
3181 graph()->NewNode(common()->Throw(), check_throw, check_fail);
3182 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
3184 Reduction
const reduction = ReduceJSConstruct(node);
3185 return reduction.Changed() ? reduction : Changed(node);
3191 bool ShouldUseCallICFeedback(Node* node) {
3192 HeapObjectMatcher m(node);
3193 if (m.HasValue() || m.IsJSCreateClosure()) {
3198 }
else if (m.IsPhi()) {
3200 Node* control = NodeProperties::GetControlInput(node);
3201 if (control->opcode() == IrOpcode::kLoop)
return false;
3204 int const value_input_count = m.node()->op()->ValueInputCount();
3205 for (
int n = 0; n < value_input_count; ++n) {
3206 if (ShouldUseCallICFeedback(node->InputAt(n)))
return true;
3213 base::Optional<HeapObjectRef> GetHeapObjectFeedback(
3214 JSHeapBroker* broker,
const FeedbackNexus& nexus) {
3216 if (!nexus.GetFeedback()->GetHeapObject(&
object))
return base::nullopt;
3217 return HeapObjectRef(broker, handle(
object, broker->isolate()));
3222 Reduction JSCallReducer::ReduceJSCall(Node* node) {
3223 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
3224 CallParameters
const& p = CallParametersOf(node->op());
3225 Node* target = NodeProperties::GetValueInput(node, 0);
3226 Node* control = NodeProperties::GetControlInput(node);
3227 Node* effect = NodeProperties::GetEffectInput(node);
3228 size_t arity = p.arity();
3229 DCHECK_LE(2u, arity);
3232 HeapObjectMatcher m(target);
3234 ObjectRef target_ref = m.Ref(broker());
3235 if (target_ref.IsJSFunction()) {
3236 JSFunctionRef
function = target_ref.AsJSFunction();
3237 function.Serialize();
3240 if (!
function.native_context().equals(native_context())) {
3244 return ReduceJSCall(node,
function.shared());
3245 }
else if (target_ref.IsJSBoundFunction()) {
3246 JSBoundFunctionRef
function = target_ref.AsJSBoundFunction();
3247 function.Serialize();
3249 ObjectRef bound_this =
function.bound_this();
3250 ConvertReceiverMode
const convert_mode =
3251 bound_this.IsNullOrUndefined()
3252 ? ConvertReceiverMode::kNullOrUndefined
3253 : ConvertReceiverMode::kNotNullOrUndefined;
3256 NodeProperties::ReplaceValueInput(
3257 node, jsgraph()->Constant(
function.bound_target_function()), 0);
3258 NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
3262 FixedArrayRef bound_arguments =
function.bound_arguments();
3263 for (
int i = 0;
i < bound_arguments.length(); ++
i) {
3264 node->InsertInput(graph()->zone(),
i + 2,
3265 jsgraph()->Constant(bound_arguments.get(
i)));
3269 NodeProperties::ChangeOp(
3270 node, javascript()->Call(arity, p.frequency(), VectorSlotPair(),
3274 Reduction
const reduction = ReduceJSCall(node);
3275 return reduction.Changed() ? reduction : Changed(node);
3287 if (target->opcode() == IrOpcode::kJSCreateClosure) {
3288 CreateClosureParameters
const& p = CreateClosureParametersOf(target->op());
3289 return ReduceJSCall(node, SharedFunctionInfoRef(broker(), p.shared_info()));
3295 if (target->opcode() == IrOpcode::kJSCreateBoundFunction) {
3296 Node* bound_target_function = NodeProperties::GetValueInput(target, 0);
3297 Node* bound_this = NodeProperties::GetValueInput(target, 1);
3298 int const bound_arguments_length =
3299 static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());
3302 NodeProperties::ReplaceValueInput(node, bound_target_function, 0);
3303 NodeProperties::ReplaceValueInput(node, bound_this, 1);
3306 for (
int i = 0;
i < bound_arguments_length; ++
i) {
3307 Node* value = NodeProperties::GetValueInput(target, 2 +
i);
3308 node->InsertInput(graph()->zone(), 2 +
i, value);
3313 ConvertReceiverMode
const convert_mode =
3314 NodeProperties::CanBeNullOrUndefined(broker(), bound_this, effect)
3315 ? ConvertReceiverMode::kAny
3316 : ConvertReceiverMode::kNotNullOrUndefined;
3317 NodeProperties::ChangeOp(
3318 node, javascript()->Call(arity, p.frequency(), VectorSlotPair(),
3322 Reduction
const reduction = ReduceJSCall(node);
3323 return reduction.Changed() ? reduction : Changed(node);
3327 if (!p.feedback().IsValid())
return NoChange();
3328 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
3329 if (nexus.IsUninitialized()) {
3330 if (flags() & kBailoutOnUninitialized) {
3332 return ReduceSoftDeoptimize(
3333 node, DeoptimizeReason::kInsufficientTypeFeedbackForCall);
3338 base::Optional<HeapObjectRef> feedback =
3339 GetHeapObjectFeedback(broker(), nexus);
3340 if (feedback.has_value() && ShouldUseCallICFeedback(target) &&
3341 feedback->map().is_callable()) {
3342 Node* target_function = jsgraph()->Constant(*feedback);
3345 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
3347 effect = graph()->NewNode(
3348 simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
3352 NodeProperties::ReplaceValueInput(node, target_function, 0);
3353 NodeProperties::ReplaceEffectInput(node, effect);
3356 Reduction
const reduction = ReduceJSCall(node);
3357 return reduction.Changed() ? reduction : Changed(node);
3363 Reduction JSCallReducer::ReduceJSCall(Node* node,
3364 const SharedFunctionInfoRef& shared) {
3365 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
3366 Node* target = NodeProperties::GetValueInput(node, 0);
3369 if (shared.HasBreakInfo())
return NoChange();
3372 if (IsClassConstructor(shared.kind())) {
3373 NodeProperties::ReplaceValueInputs(node, target);
3374 NodeProperties::ChangeOp(
3375 node, javascript()->CallRuntime(
3376 Runtime::kThrowConstructorNonCallableError, 1));
3377 return Changed(node);
3383 shared.HasBuiltinId() ? shared.builtin_id() : Builtins::kNoBuiltinId;
3384 switch (builtin_id) {
3385 case Builtins::kArrayConstructor:
3386 return ReduceArrayConstructor(node);
3387 case Builtins::kBooleanConstructor:
3388 return ReduceBooleanConstructor(node);
3389 case Builtins::kFunctionPrototypeApply:
3390 return ReduceFunctionPrototypeApply(node);
3391 case Builtins::kFastFunctionPrototypeBind:
3392 return ReduceFunctionPrototypeBind(node);
3393 case Builtins::kFunctionPrototypeCall:
3394 return ReduceFunctionPrototypeCall(node);
3395 case Builtins::kFunctionPrototypeHasInstance:
3396 return ReduceFunctionPrototypeHasInstance(node);
3397 case Builtins::kObjectConstructor:
3398 return ReduceObjectConstructor(node);
3399 case Builtins::kObjectCreate:
3400 return ReduceObjectCreate(node);
3401 case Builtins::kObjectGetPrototypeOf:
3402 return ReduceObjectGetPrototypeOf(node);
3403 case Builtins::kObjectIs:
3404 return ReduceObjectIs(node);
3405 case Builtins::kObjectPrototypeGetProto:
3406 return ReduceObjectPrototypeGetProto(node);
3407 case Builtins::kObjectPrototypeHasOwnProperty:
3408 return ReduceObjectPrototypeHasOwnProperty(node);
3409 case Builtins::kObjectPrototypeIsPrototypeOf:
3410 return ReduceObjectPrototypeIsPrototypeOf(node);
3411 case Builtins::kReflectApply:
3412 return ReduceReflectApply(node);
3413 case Builtins::kReflectConstruct:
3414 return ReduceReflectConstruct(node);
3415 case Builtins::kReflectGet:
3416 return ReduceReflectGet(node);
3417 case Builtins::kReflectGetPrototypeOf:
3418 return ReduceReflectGetPrototypeOf(node);
3419 case Builtins::kReflectHas:
3420 return ReduceReflectHas(node);
3421 case Builtins::kArrayForEach:
3422 return ReduceArrayForEach(node, shared);
3423 case Builtins::kArrayMap:
3424 return ReduceArrayMap(node, shared);
3425 case Builtins::kArrayFilter:
3426 return ReduceArrayFilter(node, shared);
3427 case Builtins::kArrayReduce:
3428 return ReduceArrayReduce(node, ArrayReduceDirection::kLeft, shared);
3429 case Builtins::kArrayReduceRight:
3430 return ReduceArrayReduce(node, ArrayReduceDirection::kRight, shared);
3431 case Builtins::kArrayPrototypeFind:
3432 return ReduceArrayFind(node, ArrayFindVariant::kFind, shared);
3433 case Builtins::kArrayPrototypeFindIndex:
3434 return ReduceArrayFind(node, ArrayFindVariant::kFindIndex, shared);
3435 case Builtins::kArrayEvery:
3436 return ReduceArrayEvery(node, shared);
3437 case Builtins::kArrayIndexOf:
3438 return ReduceArrayIndexOfIncludes(SearchVariant::kIndexOf, node);
3439 case Builtins::kArrayIncludes:
3440 return ReduceArrayIndexOfIncludes(SearchVariant::kIncludes, node);
3441 case Builtins::kArraySome:
3442 return ReduceArraySome(node, shared);
3443 case Builtins::kArrayPrototypePush:
3444 return ReduceArrayPrototypePush(node);
3445 case Builtins::kArrayPrototypePop:
3446 return ReduceArrayPrototypePop(node);
3447 case Builtins::kArrayPrototypeShift:
3448 return ReduceArrayPrototypeShift(node);
3449 case Builtins::kArrayPrototypeSlice:
3450 return ReduceArrayPrototypeSlice(node);
3451 case Builtins::kArrayPrototypeEntries:
3452 return ReduceArrayIterator(node, IterationKind::kEntries);
3453 case Builtins::kArrayPrototypeKeys:
3454 return ReduceArrayIterator(node, IterationKind::kKeys);
3455 case Builtins::kArrayPrototypeValues:
3456 return ReduceArrayIterator(node, IterationKind::kValues);
3457 case Builtins::kArrayIteratorPrototypeNext:
3458 return ReduceArrayIteratorPrototypeNext(node);
3459 case Builtins::kArrayIsArray:
3460 return ReduceArrayIsArray(node);
3461 case Builtins::kArrayBufferIsView:
3462 return ReduceArrayBufferIsView(node);
3463 case Builtins::kDataViewPrototypeGetByteLength:
3464 return ReduceArrayBufferViewAccessor(
3465 node, JS_DATA_VIEW_TYPE,
3466 AccessBuilder::ForJSArrayBufferViewByteLength());
3467 case Builtins::kDataViewPrototypeGetByteOffset:
3468 return ReduceArrayBufferViewAccessor(
3469 node, JS_DATA_VIEW_TYPE,
3470 AccessBuilder::ForJSArrayBufferViewByteOffset());
3471 case Builtins::kDataViewPrototypeGetUint8:
3472 return ReduceDataViewAccess(node, DataViewAccess::kGet,
3473 ExternalArrayType::kExternalUint8Array);
3474 case Builtins::kDataViewPrototypeGetInt8:
3475 return ReduceDataViewAccess(node, DataViewAccess::kGet,
3476 ExternalArrayType::kExternalInt8Array);
3477 case Builtins::kDataViewPrototypeGetUint16:
3478 return ReduceDataViewAccess(node, DataViewAccess::kGet,
3479 ExternalArrayType::kExternalUint16Array);
3480 case Builtins::kDataViewPrototypeGetInt16:
3481 return ReduceDataViewAccess(node, DataViewAccess::kGet,
3482 ExternalArrayType::kExternalInt16Array);
3483 case Builtins::kDataViewPrototypeGetUint32:
3484 return ReduceDataViewAccess(node, DataViewAccess::kGet,
3485 ExternalArrayType::kExternalUint32Array);
3486 case Builtins::kDataViewPrototypeGetInt32:
3487 return ReduceDataViewAccess(node, DataViewAccess::kGet,
3488 ExternalArrayType::kExternalInt32Array);
3489 case Builtins::kDataViewPrototypeGetFloat32:
3490 return ReduceDataViewAccess(node, DataViewAccess::kGet,
3491 ExternalArrayType::kExternalFloat32Array);
3492 case Builtins::kDataViewPrototypeGetFloat64:
3493 return ReduceDataViewAccess(node, DataViewAccess::kGet,
3494 ExternalArrayType::kExternalFloat64Array);
3495 case Builtins::kDataViewPrototypeSetUint8:
3496 return ReduceDataViewAccess(node, DataViewAccess::kSet,
3497 ExternalArrayType::kExternalUint8Array);
3498 case Builtins::kDataViewPrototypeSetInt8:
3499 return ReduceDataViewAccess(node, DataViewAccess::kSet,
3500 ExternalArrayType::kExternalInt8Array);
3501 case Builtins::kDataViewPrototypeSetUint16:
3502 return ReduceDataViewAccess(node, DataViewAccess::kSet,
3503 ExternalArrayType::kExternalUint16Array);
3504 case Builtins::kDataViewPrototypeSetInt16:
3505 return ReduceDataViewAccess(node, DataViewAccess::kSet,
3506 ExternalArrayType::kExternalInt16Array);
3507 case Builtins::kDataViewPrototypeSetUint32:
3508 return ReduceDataViewAccess(node, DataViewAccess::kSet,
3509 ExternalArrayType::kExternalUint32Array);
3510 case Builtins::kDataViewPrototypeSetInt32:
3511 return ReduceDataViewAccess(node, DataViewAccess::kSet,
3512 ExternalArrayType::kExternalInt32Array);
3513 case Builtins::kDataViewPrototypeSetFloat32:
3514 return ReduceDataViewAccess(node, DataViewAccess::kSet,
3515 ExternalArrayType::kExternalFloat32Array);
3516 case Builtins::kDataViewPrototypeSetFloat64:
3517 return ReduceDataViewAccess(node, DataViewAccess::kSet,
3518 ExternalArrayType::kExternalFloat64Array);
3519 case Builtins::kTypedArrayPrototypeByteLength:
3520 return ReduceArrayBufferViewAccessor(
3521 node, JS_TYPED_ARRAY_TYPE,
3522 AccessBuilder::ForJSArrayBufferViewByteLength());
3523 case Builtins::kTypedArrayPrototypeByteOffset:
3524 return ReduceArrayBufferViewAccessor(
3525 node, JS_TYPED_ARRAY_TYPE,
3526 AccessBuilder::ForJSArrayBufferViewByteOffset());
3527 case Builtins::kTypedArrayPrototypeLength:
3528 return ReduceArrayBufferViewAccessor(
3529 node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength());
3530 case Builtins::kTypedArrayPrototypeToStringTag:
3531 return ReduceTypedArrayPrototypeToStringTag(node);
3532 case Builtins::kMathAbs:
3533 return ReduceMathUnary(node, simplified()->NumberAbs());
3534 case Builtins::kMathAcos:
3535 return ReduceMathUnary(node, simplified()->NumberAcos());
3536 case Builtins::kMathAcosh:
3537 return ReduceMathUnary(node, simplified()->NumberAcosh());
3538 case Builtins::kMathAsin:
3539 return ReduceMathUnary(node, simplified()->NumberAsin());
3540 case Builtins::kMathAsinh:
3541 return ReduceMathUnary(node, simplified()->NumberAsinh());
3542 case Builtins::kMathAtan:
3543 return ReduceMathUnary(node, simplified()->NumberAtan());
3544 case Builtins::kMathAtanh:
3545 return ReduceMathUnary(node, simplified()->NumberAtanh());
3546 case Builtins::kMathCbrt:
3547 return ReduceMathUnary(node, simplified()->NumberCbrt());
3548 case Builtins::kMathCeil:
3549 return ReduceMathUnary(node, simplified()->NumberCeil());
3550 case Builtins::kMathCos:
3551 return ReduceMathUnary(node, simplified()->NumberCos());
3552 case Builtins::kMathCosh:
3553 return ReduceMathUnary(node, simplified()->NumberCosh());
3554 case Builtins::kMathExp:
3555 return ReduceMathUnary(node, simplified()->NumberExp());
3556 case Builtins::kMathExpm1:
3557 return ReduceMathUnary(node, simplified()->NumberExpm1());
3558 case Builtins::kMathFloor:
3559 return ReduceMathUnary(node, simplified()->NumberFloor());
3560 case Builtins::kMathFround:
3561 return ReduceMathUnary(node, simplified()->NumberFround());
3562 case Builtins::kMathLog:
3563 return ReduceMathUnary(node, simplified()->NumberLog());
3564 case Builtins::kMathLog1p:
3565 return ReduceMathUnary(node, simplified()->NumberLog1p());
3566 case Builtins::kMathLog10:
3567 return ReduceMathUnary(node, simplified()->NumberLog10());
3568 case Builtins::kMathLog2:
3569 return ReduceMathUnary(node, simplified()->NumberLog2());
3570 case Builtins::kMathRound:
3571 return ReduceMathUnary(node, simplified()->NumberRound());
3572 case Builtins::kMathSign:
3573 return ReduceMathUnary(node, simplified()->NumberSign());
3574 case Builtins::kMathSin:
3575 return ReduceMathUnary(node, simplified()->NumberSin());
3576 case Builtins::kMathSinh:
3577 return ReduceMathUnary(node, simplified()->NumberSinh());
3578 case Builtins::kMathSqrt:
3579 return ReduceMathUnary(node, simplified()->NumberSqrt());
3580 case Builtins::kMathTan:
3581 return ReduceMathUnary(node, simplified()->NumberTan());
3582 case Builtins::kMathTanh:
3583 return ReduceMathUnary(node, simplified()->NumberTanh());
3584 case Builtins::kMathTrunc:
3585 return ReduceMathUnary(node, simplified()->NumberTrunc());
3586 case Builtins::kMathAtan2:
3587 return ReduceMathBinary(node, simplified()->NumberAtan2());
3588 case Builtins::kMathPow:
3589 return ReduceMathBinary(node, simplified()->NumberPow());
3590 case Builtins::kMathClz32:
3591 return ReduceMathClz32(node);
3592 case Builtins::kMathImul:
3593 return ReduceMathImul(node);
3594 case Builtins::kMathMax:
3595 return ReduceMathMinMax(node, simplified()->NumberMax(),
3596 jsgraph()->Constant(-V8_INFINITY));
3597 case Builtins::kMathMin:
3598 return ReduceMathMinMax(node, simplified()->NumberMin(),
3599 jsgraph()->Constant(V8_INFINITY));
3600 case Builtins::kNumberIsFinite:
3601 return ReduceNumberIsFinite(node);
3602 case Builtins::kNumberIsInteger:
3603 return ReduceNumberIsInteger(node);
3604 case Builtins::kNumberIsSafeInteger:
3605 return ReduceNumberIsSafeInteger(node);
3606 case Builtins::kNumberIsNaN:
3607 return ReduceNumberIsNaN(node);
3608 case Builtins::kNumberParseInt:
3609 return ReduceNumberParseInt(node);
3610 case Builtins::kGlobalIsFinite:
3611 return ReduceGlobalIsFinite(node);
3612 case Builtins::kGlobalIsNaN:
3613 return ReduceGlobalIsNaN(node);
3614 case Builtins::kMapPrototypeGet:
3615 return ReduceMapPrototypeGet(node);
3616 case Builtins::kMapPrototypeHas:
3617 return ReduceMapPrototypeHas(node);
3618 case Builtins::kRegExpPrototypeTest:
3619 return ReduceRegExpPrototypeTest(node);
3620 case Builtins::kReturnReceiver:
3621 return ReduceReturnReceiver(node);
3622 case Builtins::kStringPrototypeIndexOf:
3623 return ReduceStringPrototypeIndexOf(node);
3624 case Builtins::kStringPrototypeCharAt:
3625 return ReduceStringPrototypeCharAt(node);
3626 case Builtins::kStringPrototypeCharCodeAt:
3627 return ReduceStringPrototypeStringAt(simplified()->StringCharCodeAt(),
3629 case Builtins::kStringPrototypeCodePointAt:
3630 return ReduceStringPrototypeStringAt(
3631 simplified()->StringCodePointAt(UnicodeEncoding::UTF32), node);
3632 case Builtins::kStringPrototypeSubstring:
3633 return ReduceStringPrototypeSubstring(node);
3634 case Builtins::kStringPrototypeSlice:
3635 return ReduceStringPrototypeSlice(node);
3636 case Builtins::kStringPrototypeSubstr:
3637 return ReduceStringPrototypeSubstr(node);
3638 #ifdef V8_INTL_SUPPORT 3639 case Builtins::kStringPrototypeToLowerCaseIntl:
3640 return ReduceStringPrototypeToLowerCaseIntl(node);
3641 case Builtins::kStringPrototypeToUpperCaseIntl:
3642 return ReduceStringPrototypeToUpperCaseIntl(node);
3643 #endif // V8_INTL_SUPPORT 3644 case Builtins::kStringFromCharCode:
3645 return ReduceStringFromCharCode(node);
3646 case Builtins::kStringFromCodePoint:
3647 return ReduceStringFromCodePoint(node);
3648 case Builtins::kStringPrototypeIterator:
3649 return ReduceStringPrototypeIterator(node);
3650 case Builtins::kStringIteratorPrototypeNext:
3651 return ReduceStringIteratorPrototypeNext(node);
3652 case Builtins::kStringPrototypeConcat:
3653 return ReduceStringPrototypeConcat(node);
3654 case Builtins::kTypedArrayPrototypeEntries:
3655 return ReduceArrayIterator(node, IterationKind::kEntries);
3656 case Builtins::kTypedArrayPrototypeKeys:
3657 return ReduceArrayIterator(node, IterationKind::kKeys);
3658 case Builtins::kTypedArrayPrototypeValues:
3659 return ReduceArrayIterator(node, IterationKind::kValues);
3660 case Builtins::kPromiseInternalConstructor:
3661 return ReducePromiseInternalConstructor(node);
3662 case Builtins::kPromiseInternalReject:
3663 return ReducePromiseInternalReject(node);
3664 case Builtins::kPromiseInternalResolve:
3665 return ReducePromiseInternalResolve(node);
3666 case Builtins::kPromisePrototypeCatch:
3667 return ReducePromisePrototypeCatch(node);
3668 case Builtins::kPromisePrototypeFinally:
3669 return ReducePromisePrototypeFinally(node);
3670 case Builtins::kPromisePrototypeThen:
3671 return ReducePromisePrototypeThen(node);
3672 case Builtins::kPromiseResolveTrampoline:
3673 return ReducePromiseResolveTrampoline(node);
3674 case Builtins::kMapPrototypeEntries:
3675 return ReduceCollectionIteration(node, CollectionKind::kMap,
3676 IterationKind::kEntries);
3677 case Builtins::kMapPrototypeKeys:
3678 return ReduceCollectionIteration(node, CollectionKind::kMap,
3679 IterationKind::kKeys);
3680 case Builtins::kMapPrototypeGetSize:
3681 return ReduceCollectionPrototypeSize(node, CollectionKind::kMap);
3682 case Builtins::kMapPrototypeValues:
3683 return ReduceCollectionIteration(node, CollectionKind::kMap,
3684 IterationKind::kValues);
3685 case Builtins::kMapIteratorPrototypeNext:
3686 return ReduceCollectionIteratorPrototypeNext(
3687 node, OrderedHashMap::kEntrySize, factory()->empty_ordered_hash_map(),
3688 FIRST_MAP_ITERATOR_TYPE, LAST_MAP_ITERATOR_TYPE);
3689 case Builtins::kSetPrototypeEntries:
3690 return ReduceCollectionIteration(node, CollectionKind::kSet,
3691 IterationKind::kEntries);
3692 case Builtins::kSetPrototypeGetSize:
3693 return ReduceCollectionPrototypeSize(node, CollectionKind::kSet);
3694 case Builtins::kSetPrototypeValues:
3695 return ReduceCollectionIteration(node, CollectionKind::kSet,
3696 IterationKind::kValues);
3697 case Builtins::kSetIteratorPrototypeNext:
3698 return ReduceCollectionIteratorPrototypeNext(
3699 node, OrderedHashSet::kEntrySize, factory()->empty_ordered_hash_set(),
3700 FIRST_SET_ITERATOR_TYPE, LAST_SET_ITERATOR_TYPE);
3701 case Builtins::kDatePrototypeGetTime:
3702 return ReduceDatePrototypeGetTime(node);
3703 case Builtins::kDateNow:
3704 return ReduceDateNow(node);
3705 case Builtins::kNumberConstructor:
3706 return ReduceNumberConstructor(node);
3711 if (!FLAG_runtime_stats && shared.object()->IsApiFunction()) {
3712 return ReduceCallApiFunction(node, shared);
3717 Reduction JSCallReducer::ReduceJSCallWithArrayLike(Node* node) {
3718 DCHECK_EQ(IrOpcode::kJSCallWithArrayLike, node->opcode());
3719 CallFrequency frequency = CallFrequencyOf(node->op());
3720 VectorSlotPair feedback;
3721 return ReduceCallOrConstructWithArrayLikeOrSpread(node, 2, frequency,
3725 Reduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
3726 DCHECK_EQ(IrOpcode::kJSCallWithSpread, node->opcode());
3727 CallParameters
const& p = CallParametersOf(node->op());
3728 DCHECK_LE(3u, p.arity());
3729 int arity =
static_cast<int>(p.arity() - 1);
3730 CallFrequency frequency = p.frequency();
3731 VectorSlotPair feedback = p.feedback();
3732 return ReduceCallOrConstructWithArrayLikeOrSpread(node, arity, frequency,
3736 Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
3737 DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
3738 ConstructParameters
const& p = ConstructParametersOf(node->op());
3739 DCHECK_LE(2u, p.arity());
3740 int arity =
static_cast<int>(p.arity() - 2);
3741 Node* target = NodeProperties::GetValueInput(node, 0);
3742 Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
3743 Node* effect = NodeProperties::GetEffectInput(node);
3744 Node* control = NodeProperties::GetControlInput(node);
3747 if (p.feedback().IsValid()) {
3748 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
3749 if (nexus.IsUninitialized()) {
3750 if (flags() & kBailoutOnUninitialized) {
3753 return ReduceSoftDeoptimize(
3754 node, DeoptimizeReason::kInsufficientTypeFeedbackForConstruct);
3759 base::Optional<HeapObjectRef> feedback =
3760 GetHeapObjectFeedback(broker(), nexus);
3761 if (feedback.has_value() && feedback->IsAllocationSite()) {
3767 Node* array_function =
3768 jsgraph()->Constant(native_context().array_function());
3771 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
3773 effect = graph()->NewNode(
3774 simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
3778 NodeProperties::ReplaceEffectInput(node, effect);
3779 for (
int i = arity;
i > 0; --
i) {
3780 NodeProperties::ReplaceValueInput(
3781 node, NodeProperties::GetValueInput(node,
i),
i + 1);
3783 NodeProperties::ReplaceValueInput(node, array_function, 1);
3784 NodeProperties::ChangeOp(
3785 node, javascript()->CreateArray(
3786 arity, feedback->AsAllocationSite().object()));
3787 return Changed(node);
3788 }
else if (feedback.has_value() &&
3789 !HeapObjectMatcher(new_target).HasValue() &&
3790 feedback->map().is_constructor()) {
3791 Node* new_target_feedback = jsgraph()->Constant(*feedback);
3794 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), new_target,
3795 new_target_feedback);
3796 effect = graph()->NewNode(
3797 simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
3801 NodeProperties::ReplaceValueInput(node, new_target_feedback, arity + 1);
3802 NodeProperties::ReplaceEffectInput(node, effect);
3803 if (target == new_target) {
3804 NodeProperties::ReplaceValueInput(node, new_target_feedback, 0);
3808 Reduction
const reduction = ReduceJSConstruct(node);
3809 return reduction.Changed() ? reduction : Changed(node);
3814 HeapObjectMatcher m(target);
3816 HeapObjectRef target_ref = m.Ref(broker()).AsHeapObject();
3819 if (!target_ref.map().is_constructor()) {
3820 NodeProperties::ReplaceValueInputs(node, target);
3821 NodeProperties::ChangeOp(node,
3822 javascript()->CallRuntime(
3823 Runtime::kThrowConstructedNonConstructable));
3824 return Changed(node);
3827 if (target_ref.IsJSFunction()) {
3828 JSFunctionRef
function = target_ref.AsJSFunction();
3829 function.Serialize();
3832 if (
function.shared().HasBreakInfo())
return NoChange();
3835 if (!
function.native_context().equals(native_context())) {
3840 int builtin_id =
function.shared().HasBuiltinId()
3841 ?
function.shared().builtin_id()
3842 : Builtins::kNoBuiltinId;
3843 switch (builtin_id) {
3844 case Builtins::kArrayConstructor: {
3847 for (
int i = arity;
i > 0; --
i) {
3848 NodeProperties::ReplaceValueInput(
3849 node, NodeProperties::GetValueInput(node,
i),
i + 1);
3851 NodeProperties::ReplaceValueInput(node, new_target, 1);
3852 NodeProperties::ChangeOp(
3853 node, javascript()->CreateArray(arity, Handle<AllocationSite>()));
3854 return Changed(node);
3856 case Builtins::kObjectConstructor: {
3860 NodeProperties::ChangeOp(node, javascript()->Create());
3861 return Changed(node);
3867 HeapObjectMatcher mnew_target(new_target);
3868 if (mnew_target.HasValue() &&
3869 !mnew_target.Ref(broker()).equals(
function)) {
3871 for (
int i = arity;
i > 0; --
i) node->RemoveInput(
i);
3872 NodeProperties::ChangeOp(node, javascript()->Create());
3873 return Changed(node);
3877 case Builtins::kPromiseConstructor:
3878 return ReducePromiseConstructor(node);
3879 case Builtins::kTypedArrayConstructor:
3880 return ReduceTypedArrayConstructor(node,
function.shared());
3884 }
else if (target_ref.IsJSBoundFunction()) {
3885 JSBoundFunctionRef
function = target_ref.AsJSBoundFunction();
3886 function.Serialize();
3888 ObjectRef bound_target_function =
function.bound_target_function();
3889 FixedArrayRef bound_arguments =
function.bound_arguments();
3892 NodeProperties::ReplaceValueInput(
3893 node, jsgraph()->Constant(bound_target_function), 0);
3897 NodeProperties::ReplaceValueInput(
3899 graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
3900 graph()->NewNode(simplified()->ReferenceEqual(),
3901 target, new_target),
3902 jsgraph()->Constant(bound_target_function),
3907 for (
int i = 0;
i < bound_arguments.length(); ++
i) {
3908 node->InsertInput(graph()->zone(),
i + 1,
3909 jsgraph()->Constant(bound_arguments.get(
i)));
3914 NodeProperties::ChangeOp(
3916 javascript()->Construct(arity + 2, p.frequency(), VectorSlotPair()));
3919 Reduction
const reduction = ReduceJSConstruct(node);
3920 return reduction.Changed() ? reduction : Changed(node);
3929 if (target->opcode() == IrOpcode::kJSCreateBoundFunction) {
3930 Node* bound_target_function = NodeProperties::GetValueInput(target, 0);
3931 int const bound_arguments_length =
3932 static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());
3935 NodeProperties::ReplaceValueInput(node, bound_target_function, 0);
3939 NodeProperties::ReplaceValueInput(
3941 graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
3942 graph()->NewNode(simplified()->ReferenceEqual(),
3943 target, new_target),
3944 bound_target_function, new_target),
3948 for (
int i = 0;
i < bound_arguments_length; ++
i) {
3949 Node* value = NodeProperties::GetValueInput(target, 2 +
i);
3950 node->InsertInput(graph()->zone(), 1 +
i, value);
3955 NodeProperties::ChangeOp(
3957 javascript()->Construct(arity + 2, p.frequency(), VectorSlotPair()));
3960 Reduction
const reduction = ReduceJSConstruct(node);
3961 return reduction.Changed() ? reduction : Changed(node);
3968 Reduction JSCallReducer::ReduceStringPrototypeIndexOf(Node* node) {
3969 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
3970 CallParameters
const& p = CallParametersOf(node->op());
3971 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
3975 Node* effect = NodeProperties::GetEffectInput(node);
3976 Node* control = NodeProperties::GetControlInput(node);
3977 if (node->op()->ValueInputCount() >= 3) {
3978 Node* receiver = NodeProperties::GetValueInput(node, 1);
3979 Node* new_receiver = effect = graph()->NewNode(
3980 simplified()->CheckString(p.feedback()), receiver, effect, control);
3982 Node* search_string = NodeProperties::GetValueInput(node, 2);
3983 Node* new_search_string = effect =
3984 graph()->NewNode(simplified()->CheckString(p.feedback()), search_string,
3987 Node* new_position = jsgraph()->ZeroConstant();
3988 if (node->op()->ValueInputCount() >= 4) {
3989 Node* position = NodeProperties::GetValueInput(node, 3);
3990 new_position = effect = graph()->NewNode(
3991 simplified()->CheckSmi(p.feedback()), position, effect, control);
3994 NodeProperties::ReplaceEffectInput(node, effect);
3995 RelaxEffectsAndControls(node);
3996 node->ReplaceInput(0, new_receiver);
3997 node->ReplaceInput(1, new_search_string);
3998 node->ReplaceInput(2, new_position);
3999 node->TrimInputCount(3);
4000 NodeProperties::ChangeOp(node, simplified()->StringIndexOf());
4001 return Changed(node);
4007 Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) {
4008 if (node->op()->ValueInputCount() < 3)
return NoChange();
4009 CallParameters
const& p = CallParametersOf(node->op());
4010 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
4014 Node* effect = NodeProperties::GetEffectInput(node);
4015 Node* control = NodeProperties::GetControlInput(node);
4016 Node* receiver = NodeProperties::GetValueInput(node, 1);
4017 Node* start = NodeProperties::GetValueInput(node, 2);
4018 Node* end = node->op()->ValueInputCount() > 3
4019 ? NodeProperties::GetValueInput(node, 3)
4020 : jsgraph()->UndefinedConstant();
4022 receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
4023 receiver, effect, control);
4025 start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
4028 Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
4030 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
4031 jsgraph()->UndefinedConstant());
4033 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
4035 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
4036 Node* etrue = effect;
4037 Node* vtrue = length;
4039 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
4040 Node* efalse = effect;
4041 Node* vfalse = efalse = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
4042 end, efalse, if_false);
4044 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
4045 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
4046 end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
4047 vtrue, vfalse, control);
4049 graph()->NewNode(simplified()->NumberMin(),
4050 graph()->NewNode(simplified()->NumberMax(), start,
4051 jsgraph()->ZeroConstant()),
4054 graph()->NewNode(simplified()->NumberMin(),
4055 graph()->NewNode(simplified()->NumberMax(), end,
4056 jsgraph()->ZeroConstant()),
4060 graph()->NewNode(simplified()->NumberMin(), finalStart, finalEnd);
4061 Node* to = graph()->NewNode(simplified()->NumberMax(), finalStart, finalEnd);
4063 Node* value = effect = graph()->NewNode(simplified()->StringSubstring(),
4064 receiver, from, to, effect, control);
4065 ReplaceWithValue(node, value, effect, control);
4066 return Replace(value);
4070 Reduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) {
4071 if (node->op()->ValueInputCount() < 3)
return NoChange();
4072 CallParameters
const& p = CallParametersOf(node->op());
4073 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
4077 Node* effect = NodeProperties::GetEffectInput(node);
4078 Node* control = NodeProperties::GetControlInput(node);
4079 Node* receiver = NodeProperties::GetValueInput(node, 1);
4080 Node* start = NodeProperties::GetValueInput(node, 2);
4081 Node* end = node->op()->ValueInputCount() > 3
4082 ? NodeProperties::GetValueInput(node, 3)
4083 : jsgraph()->UndefinedConstant();
4085 receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
4086 receiver, effect, control);
4088 start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
4091 Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
4095 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
4096 jsgraph()->UndefinedConstant());
4099 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
4101 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
4102 Node* etrue = effect;
4103 Node* vtrue = length;
4105 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
4106 Node* efalse = effect;
4107 Node* vfalse = efalse = graph()->NewNode(
4108 simplified()->CheckSmi(p.feedback()), end, efalse, if_false);
4110 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
4111 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
4112 end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
4113 vtrue, vfalse, control);
4116 Node* from = graph()->NewNode(
4117 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
4118 graph()->NewNode(simplified()->NumberLessThan(), start,
4119 jsgraph()->ZeroConstant()),
4121 simplified()->NumberMax(),
4122 graph()->NewNode(simplified()->NumberAdd(), length, start),
4123 jsgraph()->ZeroConstant()),
4124 graph()->NewNode(simplified()->NumberMin(), start, length));
4127 from = effect = graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()),
4128 from, effect, control);
4130 Node* to = graph()->NewNode(
4131 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
4132 graph()->NewNode(simplified()->NumberLessThan(), end,
4133 jsgraph()->ZeroConstant()),
4134 graph()->NewNode(simplified()->NumberMax(),
4135 graph()->NewNode(simplified()->NumberAdd(), length, end),
4136 jsgraph()->ZeroConstant()),
4137 graph()->NewNode(simplified()->NumberMin(), end, length));
4140 to = effect = graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()), to,
4143 Node* result_string =
nullptr;
4146 Node* check = graph()->NewNode(simplified()->NumberLessThan(), from, to);
4149 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
4151 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
4152 Node* etrue = effect;
4153 Node* vtrue = etrue = graph()->NewNode(simplified()->StringSubstring(),
4154 receiver, from, to, etrue, if_true);
4156 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
4157 Node* efalse = effect;
4158 Node* vfalse = jsgraph()->EmptyStringConstant();
4160 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
4161 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
4163 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
4164 vtrue, vfalse, control);
4167 ReplaceWithValue(node, result_string, effect, control);
4168 return Replace(result_string);
4172 Reduction JSCallReducer::ReduceStringPrototypeSubstr(Node* node) {
4173 if (node->op()->ValueInputCount() < 3)
return NoChange();
4174 CallParameters
const& p = CallParametersOf(node->op());
4175 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
4179 Node* effect = NodeProperties::GetEffectInput(node);
4180 Node* control = NodeProperties::GetControlInput(node);
4181 Node* receiver = NodeProperties::GetValueInput(node, 1);
4182 Node* start = NodeProperties::GetValueInput(node, 2);
4183 Node* end = node->op()->ValueInputCount() > 3
4184 ? NodeProperties::GetValueInput(node, 3)
4185 : jsgraph()->UndefinedConstant();
4187 receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
4188 receiver, effect, control);
4190 start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
4193 Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
4197 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
4198 jsgraph()->UndefinedConstant());
4200 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
4202 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
4203 Node* etrue = effect;
4204 Node* vtrue = length;
4206 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
4207 Node* efalse = effect;
4208 Node* vfalse = efalse = graph()->NewNode(
4209 simplified()->CheckSmi(p.feedback()), end, efalse, if_false);
4211 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
4212 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
4213 end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
4214 vtrue, vfalse, control);
4217 Node* initStart = graph()->NewNode(
4218 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
4219 graph()->NewNode(simplified()->NumberLessThan(), start,
4220 jsgraph()->ZeroConstant()),
4222 simplified()->NumberMax(),
4223 graph()->NewNode(simplified()->NumberAdd(), length, start),
4224 jsgraph()->ZeroConstant()),
4228 initStart = effect = graph()->NewNode(
4229 common()->TypeGuard(Type::UnsignedSmall()), initStart, effect, control);
4231 Node* resultLength = graph()->NewNode(
4232 simplified()->NumberMin(),
4233 graph()->NewNode(simplified()->NumberMax(), end,
4234 jsgraph()->ZeroConstant()),
4235 graph()->NewNode(simplified()->NumberSubtract(), length, initStart));
4239 Node* to = effect = graph()->NewNode(
4240 common()->TypeGuard(Type::UnsignedSmall()),
4241 graph()->NewNode(simplified()->NumberAdd(), initStart, resultLength),
4244 Node* result_string =
nullptr;
4247 Node* check = graph()->NewNode(simplified()->NumberLessThan(),
4248 jsgraph()->ZeroConstant(), resultLength);
4251 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
4253 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
4254 Node* etrue = effect;
4255 Node* vtrue = etrue =
4256 graph()->NewNode(simplified()->StringSubstring(), receiver, initStart,
4257 to, etrue, if_true);
4259 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
4260 Node* efalse = effect;
4261 Node* vfalse = jsgraph()->EmptyStringConstant();
4263 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
4264 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
4266 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
4267 vtrue, vfalse, control);
4270 ReplaceWithValue(node, result_string, effect, control);
4271 return Replace(result_string);
4274 Reduction JSCallReducer::ReduceJSConstructWithArrayLike(Node* node) {
4275 DCHECK_EQ(IrOpcode::kJSConstructWithArrayLike, node->opcode());
4276 CallFrequency frequency = CallFrequencyOf(node->op());
4277 VectorSlotPair feedback;
4278 return ReduceCallOrConstructWithArrayLikeOrSpread(node, 1, frequency,
4282 Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) {
4283 DCHECK_EQ(IrOpcode::kJSConstructWithSpread, node->opcode());
4284 ConstructParameters
const& p = ConstructParametersOf(node->op());
4285 DCHECK_LE(3u, p.arity());
4286 int arity =
static_cast<int>(p.arity() - 2);
4287 CallFrequency frequency = p.frequency();
4288 VectorSlotPair feedback = p.feedback();
4289 return ReduceCallOrConstructWithArrayLikeOrSpread(node, arity, frequency,
4293 Reduction JSCallReducer::ReduceReturnReceiver(Node* node) {
4294 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
4295 Node* receiver = NodeProperties::GetValueInput(node, 1);
4296 ReplaceWithValue(node, receiver);
4297 return Replace(receiver);
4300 Reduction JSCallReducer::ReduceSoftDeoptimize(Node* node,
4301 DeoptimizeReason reason) {
4302 Node* effect = NodeProperties::GetEffectInput(node);
4303 Node* control = NodeProperties::GetControlInput(node);
4304 Node* frame_state = NodeProperties::FindFrameStateBefore(node);
4305 Node* deoptimize = graph()->NewNode(
4306 common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
4307 frame_state, effect, control);
4309 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
4310 Revisit(graph()->end());
4311 node->TrimInputCount(0);
4312 NodeProperties::ChangeOp(node, common()->Dead());
4313 return Changed(node);
4319 bool IsReadOnlyLengthDescriptor(Isolate* isolate, Handle<Map> jsarray_map) {
4320 DCHECK(!jsarray_map->is_dictionary_map());
4321 Handle<Name> length_string = isolate->factory()->length_string();
4322 DescriptorArray* descriptors = jsarray_map->instance_descriptors();
4323 int number = descriptors->Search(*length_string, *jsarray_map);
4324 DCHECK_NE(DescriptorArray::kNotFound, number);
4325 return descriptors->GetDetails(number).IsReadOnly();
4329 bool CanInlineArrayResizeOperation(Isolate* isolate, MapRef& receiver_map) {
4330 receiver_map.SerializePrototype();
4331 if (!receiver_map.prototype().IsJSArray())
return false;
4332 JSArrayRef receiver_prototype = receiver_map.prototype().AsJSArray();
4333 return receiver_map.instance_type() == JS_ARRAY_TYPE &&
4334 IsFastElementsKind(receiver_map.elements_kind()) &&
4335 !receiver_map.is_dictionary_map() && receiver_map.is_extensible() &&
4336 isolate->IsAnyInitialArrayPrototype(receiver_prototype.object()) &&
4337 !IsReadOnlyLengthDescriptor(isolate, receiver_map.object());
4343 Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
4344 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
4345 CallParameters
const& p = CallParametersOf(node->op());
4346 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
4350 PropertyCellRef no_elements_protector(broker(),
4351 factory()->no_elements_protector());
4352 if (no_elements_protector.value().AsSmi() != Isolate::kProtectorValid) {
4356 int const num_values = node->op()->ValueInputCount() - 2;
4357 Node* receiver = NodeProperties::GetValueInput(node, 1);
4358 Node* effect = NodeProperties::GetEffectInput(node);
4359 Node* control = NodeProperties::GetControlInput(node);
4362 ZoneHandleSet<Map> receiver_maps;
4363 NodeProperties::InferReceiverMapsResult result =
4364 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
4366 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
4367 DCHECK_NE(0, receiver_maps.size());
4369 ElementsKind kind = receiver_maps[0]->elements_kind();
4371 for (Handle<Map> map : receiver_maps) {
4372 MapRef receiver_map(broker(), map);
4373 receiver_map.SerializePrototype();
4374 if (!CanInlineArrayResizeOperation(isolate(), receiver_map))
4376 if (!UnionElementsKindUptoPackedness(&kind, receiver_map.elements_kind()))
4381 dependencies()->DependOnProtector(no_elements_protector);
4385 if (result == NodeProperties::kUnreliableReceiverMaps) {
4387 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
4388 receiver_maps, p.feedback()),
4389 receiver, effect, control);
4393 std::vector<Node*> values(num_values);
4394 for (
int i = 0;
i < num_values; ++
i) {
4395 values[
i] = NodeProperties::GetValueInput(node, 2 +
i);
4398 for (
auto& value : values) {
4399 if (IsSmiElementsKind(kind)) {
4400 value = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
4401 value, effect, control);
4402 }
else if (IsDoubleElementsKind(kind)) {
4403 value = effect = graph()->NewNode(simplified()->CheckNumber(p.feedback()),
4404 value, effect, control);
4406 value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
4411 Node* length = effect = graph()->NewNode(
4412 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
4414 Node* value = length;
4417 if (num_values > 0) {
4419 Node* new_length = value = graph()->NewNode(
4420 simplified()->NumberAdd(), length, jsgraph()->Constant(num_values));
4423 Node* elements = effect = graph()->NewNode(
4424 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
4426 Node* elements_length = effect = graph()->NewNode(
4427 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), elements,
4430 GrowFastElementsMode mode =
4431 IsDoubleElementsKind(kind) ? GrowFastElementsMode::kDoubleElements
4432 : GrowFastElementsMode::kSmiOrObjectElements;
4433 elements = effect = graph()->NewNode(
4434 simplified()->MaybeGrowFastElements(mode, p.feedback()), receiver,
4436 graph()->NewNode(simplified()->NumberAdd(), length,
4437 jsgraph()->Constant(num_values - 1)),
4438 elements_length, effect, control);
4442 effect = graph()->NewNode(
4443 simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
4444 receiver, new_length, effect, control);
4447 for (
int i = 0;
i < num_values; ++
i) {
4448 Node* value = values[
i];
4449 Node* index = graph()->NewNode(simplified()->NumberAdd(), length,
4450 jsgraph()->Constant(
i));
4451 effect = graph()->NewNode(
4452 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(kind)),
4453 elements, index, value, effect, control);
4457 ReplaceWithValue(node, value, effect, control);
4458 return Replace(value);
4462 Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
4463 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
4464 CallParameters
const& p = CallParametersOf(node->op());
4465 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
4469 PropertyCellRef no_elements_protector(broker(),
4470 factory()->no_elements_protector());
4471 if (no_elements_protector.value().AsSmi() != Isolate::kProtectorValid) {
4475 Node* receiver = NodeProperties::GetValueInput(node, 1);
4476 Node* effect = NodeProperties::GetEffectInput(node);
4477 Node* control = NodeProperties::GetControlInput(node);
4479 ZoneHandleSet<Map> receiver_maps;
4480 NodeProperties::InferReceiverMapsResult result =
4481 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
4483 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
4484 DCHECK_NE(0, receiver_maps.size());
4486 ElementsKind kind = receiver_maps[0]->elements_kind();
4487 for (Handle<Map> map : receiver_maps) {
4488 MapRef receiver_map(broker(), map);
4489 receiver_map.SerializePrototype();
4490 if (!CanInlineArrayResizeOperation(isolate(), receiver_map))
4494 if (receiver_map.elements_kind() == HOLEY_DOUBLE_ELEMENTS)
4496 if (!UnionElementsKindUptoSize(&kind, receiver_map.elements_kind()))
4501 dependencies()->DependOnProtector(no_elements_protector);
4505 if (result == NodeProperties::kUnreliableReceiverMaps) {
4507 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
4508 receiver_maps, p.feedback()),
4509 receiver, effect, control);
4513 Node* length = effect = graph()->NewNode(
4514 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
4518 Node* check = graph()->NewNode(simplified()->NumberEqual(), length,
4519 jsgraph()->ZeroConstant());
4521 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
4523 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
4524 Node* etrue = effect;
4525 Node* vtrue = jsgraph()->UndefinedConstant();
4527 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
4528 Node* efalse = effect;
4535 Node* elements = efalse = graph()->NewNode(
4536 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
4540 if (IsSmiOrObjectElementsKind(kind)) {
4542 graph()->NewNode(simplified()->EnsureWritableFastElements(), receiver,
4543 elements, efalse, if_false);
4547 length = graph()->NewNode(simplified()->NumberSubtract(), length,
4548 jsgraph()->OneConstant());
4551 efalse = graph()->NewNode(
4552 simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
4553 receiver, length, efalse, if_false);
4556 vfalse = efalse = graph()->NewNode(
4557 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(kind)),
4558 elements, length, efalse, if_false);
4561 efalse = graph()->NewNode(
4562 simplified()->StoreElement(
4563 AccessBuilder::ForFixedArrayElement(GetHoleyElementsKind(kind))),
4564 elements, length, jsgraph()->TheHoleConstant(), efalse, if_false);
4567 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
4568 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
4569 Node* value = graph()->NewNode(
4570 common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control);
4574 if (IsHoleyElementsKind(kind)) {
4576 graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
4579 ReplaceWithValue(node, value, effect, control);
4580 return Replace(value);
4584 Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
4585 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
4586 CallParameters
const& p = CallParametersOf(node->op());
4587 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
4591 PropertyCellRef no_elements_protector(broker(),
4592 factory()->no_elements_protector());
4593 if (no_elements_protector.value().AsSmi() != Isolate::kProtectorValid) {
4597 Node* target = NodeProperties::GetValueInput(node, 0);
4598 Node* receiver = NodeProperties::GetValueInput(node, 1);
4599 Node* context = NodeProperties::GetContextInput(node);
4600 Node* frame_state = NodeProperties::GetFrameStateInput(node);
4601 Node* effect = NodeProperties::GetEffectInput(node);
4602 Node* control = NodeProperties::GetControlInput(node);
4604 ZoneHandleSet<Map> receiver_maps;
4605 NodeProperties::InferReceiverMapsResult result =
4606 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
4608 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
4609 DCHECK_NE(0, receiver_maps.size());
4611 ElementsKind kind = receiver_maps[0]->elements_kind();
4612 for (Handle<Map> map : receiver_maps) {
4613 MapRef receiver_map(broker(), map);
4614 receiver_map.SerializePrototype();
4615 if (!CanInlineArrayResizeOperation(isolate(), receiver_map))
4619 if (receiver_map.elements_kind() == HOLEY_DOUBLE_ELEMENTS)
4621 if (!UnionElementsKindUptoSize(&kind, receiver_map.elements_kind()))
4626 dependencies()->DependOnProtector(no_elements_protector);
4630 if (result == NodeProperties::kUnreliableReceiverMaps) {
4632 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
4633 receiver_maps, p.feedback()),
4634 receiver, effect, control);
4638 Node* length = effect = graph()->NewNode(
4639 simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
4643 Node* check0 = graph()->NewNode(simplified()->NumberEqual(), length,
4644 jsgraph()->ZeroConstant());
4646 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
4648 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
4649 Node* etrue0 = effect;
4650 Node* vtrue0 = jsgraph()->UndefinedConstant();
4652 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
4653 Node* efalse0 = effect;
4658 graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
4659 jsgraph()->Constant(JSArray::kMaxCopyElements));
4660 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
4663 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
4664 Node* etrue1 = efalse0;
4667 Node* elements = etrue1 = graph()->NewNode(
4668 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
4669 receiver, etrue1, if_true1);
4672 vtrue1 = etrue1 = graph()->NewNode(
4673 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(kind)),
4674 elements, jsgraph()->ZeroConstant(), etrue1, if_true1);
4677 if (IsSmiOrObjectElementsKind(kind)) {
4679 graph()->NewNode(simplified()->EnsureWritableFastElements(),
4680 receiver, elements, etrue1, if_true1);
4684 Node* loop = graph()->NewNode(common()->Loop(2), if_true1, if_true1);
4686 graph()->NewNode(common()->EffectPhi(2), etrue1, etrue1, loop);
4687 Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
4688 NodeProperties::MergeControlToEnd(graph(), common(), terminate);
4689 Node* index = graph()->NewNode(
4690 common()->Phi(MachineRepresentation::kTagged, 2),
4691 jsgraph()->OneConstant(),
4692 jsgraph()->Constant(JSArray::kMaxCopyElements - 1), loop);
4696 graph()->NewNode(simplified()->NumberLessThan(), index, length);
4697 Node* branch2 = graph()->NewNode(common()->Branch(), check2, loop);
4699 if_true1 = graph()->NewNode(common()->IfFalse(), branch2);
4702 Node* control = graph()->NewNode(common()->IfTrue(), branch2);
4703 Node* effect = etrue1;
4705 ElementAccess
const access = AccessBuilder::ForFixedArrayElement(kind);
4706 Node* value = effect =
4707 graph()->NewNode(simplified()->LoadElement(access), elements, index,
4710 graph()->NewNode(simplified()->StoreElement(access), elements,
4711 graph()->NewNode(simplified()->NumberSubtract(),
4712 index, jsgraph()->OneConstant()),
4713 value, effect, control);
4715 loop->ReplaceInput(1, control);
4716 eloop->ReplaceInput(1, effect);
4717 index->ReplaceInput(1,
4718 graph()->NewNode(simplified()->NumberAdd(), index,
4719 jsgraph()->OneConstant()));
4723 length = graph()->NewNode(simplified()->NumberSubtract(), length,
4724 jsgraph()->OneConstant());
4727 etrue1 = graph()->NewNode(
4728 simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
4729 receiver, length, etrue1, if_true1);
4732 etrue1 = graph()->NewNode(
4733 simplified()->StoreElement(
4734 AccessBuilder::ForFixedArrayElement(GetHoleyElementsKind(kind))),
4735 elements, length, jsgraph()->TheHoleConstant(), etrue1, if_true1);
4738 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
4739 Node* efalse1 = efalse0;
4743 const int builtin_index = Builtins::kArrayShift;
4744 auto call_descriptor = Linkage::GetCEntryStubCallDescriptor(
4745 graph()->zone(), 1, BuiltinArguments::kNumExtraArgsWithReceiver,
4746 Builtins::name(builtin_index), node->op()->properties(),
4747 CallDescriptor::kNeedsFrameState);
4749 jsgraph()->CEntryStubConstant(1, kDontSaveFPRegs, kArgvOnStack,
true);
4750 Address builtin_entry = Builtins::CppEntryOf(builtin_index);
4752 jsgraph()->ExternalConstant(ExternalReference::Create(builtin_entry));
4754 jsgraph()->Constant(BuiltinArguments::kNumExtraArgsWithReceiver);
4755 if_false1 = efalse1 = vfalse1 =
4756 graph()->NewNode(common()->Call(call_descriptor), stub_code, receiver,
4757 jsgraph()->PaddingConstant(), argc, target,
4758 jsgraph()->UndefinedConstant(), entry, argc, context,
4759 frame_state, efalse1, if_false1);
4762 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
4764 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
4765 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
4766 vtrue1, vfalse1, if_false0);
4769 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
4770 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
4772 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
4773 vtrue0, vfalse0, control);
4777 if (IsHoleyElementsKind(kind)) {
4779 graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
4782 ReplaceWithValue(node, value, effect, control);
4783 return Replace(value);
4787 Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) {
4788 if (!FLAG_turbo_inline_array_builtins)
return NoChange();
4789 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
4790 CallParameters
const& p = CallParametersOf(node->op());
4791 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
4795 Node* receiver = NodeProperties::GetValueInput(node, 1);
4796 Node* start = node->op()->ValueInputCount() > 2
4797 ? NodeProperties::GetValueInput(node, 2)
4798 : jsgraph()->ZeroConstant();
4799 Node* end = node->op()->ValueInputCount() > 3
4800 ? NodeProperties::GetValueInput(node, 3)
4801 : jsgraph()->UndefinedConstant();
4802 Node* context = NodeProperties::GetContextInput(node);
4803 Node* effect = NodeProperties::GetEffectInput(node);
4804 Node* control = NodeProperties::GetControlInput(node);
4809 if (!NumberMatcher(start).Is(0) ||
4810 !HeapObjectMatcher(end).Is(factory()->undefined_value())) {
4815 ZoneHandleSet<Map> receiver_maps;
4816 NodeProperties::InferReceiverMapsResult result =
4817 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
4819 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
4822 if (!isolate()->IsArraySpeciesLookupChainIntact())
return NoChange();
4827 bool can_be_holey =
false;
4828 for (Handle<Map> map : receiver_maps) {
4829 MapRef receiver_map(broker(), map);
4830 if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) {
4834 if (IsHoleyElementsKind(receiver_map.elements_kind())) {
4835 can_be_holey =
true;
4840 dependencies()->DependOnProtector(
4841 PropertyCellRef(broker(), factory()->array_species_protector()));
4845 dependencies()->DependOnProtector(
4846 PropertyCellRef(broker(), factory()->no_elements_protector()));
4851 if (result == NodeProperties::kUnreliableReceiverMaps) {
4853 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
4854 receiver_maps, p.feedback()),
4855 receiver, effect, control);
4865 Builtins::CallableFor(isolate(), Builtins::kCloneFastJSArray);
4866 auto call_descriptor = Linkage::GetStubCallDescriptor(
4867 graph()->zone(), callable.descriptor(),
4868 callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
4869 Operator::kNoThrow | Operator::kNoDeopt);
4873 Node* clone = effect = graph()->NewNode(
4874 common()->Call(call_descriptor), jsgraph()->HeapConstant(callable.code()),
4875 receiver, context, effect, control);
4877 ReplaceWithValue(node, clone, effect, control);
4878 return Replace(clone);
4882 Reduction JSCallReducer::ReduceArrayIsArray(Node* node) {
4884 if (node->op()->ValueInputCount() < 3) {
4885 Node* value = jsgraph()->FalseConstant();
4886 ReplaceWithValue(node, value);
4887 return Replace(value);
4890 Node* effect = NodeProperties::GetEffectInput(node);
4891 Node* control = NodeProperties::GetControlInput(node);
4892 Node* context = NodeProperties::GetContextInput(node);
4893 Node* frame_state = NodeProperties::GetFrameStateInput(node);
4894 Node*
object = NodeProperties::GetValueInput(node, 2);
4895 node->ReplaceInput(0,
object);
4896 node->ReplaceInput(1, context);
4897 node->ReplaceInput(2, frame_state);
4898 node->ReplaceInput(3, effect);
4899 node->ReplaceInput(4, control);
4900 node->TrimInputCount(5);
4901 NodeProperties::ChangeOp(node, javascript()->ObjectIsArray());
4902 return Changed(node);
4905 Reduction JSCallReducer::ReduceArrayIterator(Node* node, IterationKind kind) {
4906 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
4907 Node* receiver = NodeProperties::GetValueInput(node, 1);
4908 Node* context = NodeProperties::GetContextInput(node);
4909 Node* effect = NodeProperties::GetEffectInput(node);
4910 Node* control = NodeProperties::GetControlInput(node);
4913 ZoneHandleSet<Map> receiver_maps;
4914 NodeProperties::InferReceiverMapsResult result =
4915 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
4917 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
4918 DCHECK_NE(0, receiver_maps.size());
4919 for (Handle<Map> map : receiver_maps) {
4920 MapRef receiver_map(broker(), map);
4921 if (!receiver_map.IsJSReceiverMap())
return NoChange();
4925 RelaxControls(node);
4926 node->ReplaceInput(0, receiver);
4927 node->ReplaceInput(1, context);
4928 node->ReplaceInput(2, effect);
4929 node->ReplaceInput(3, control);
4930 node->TrimInputCount(4);
4931 NodeProperties::ChangeOp(node, javascript()->CreateArrayIterator(kind));
4932 return Changed(node);
4937 bool InferIteratedObjectMaps(JSHeapBroker* broker, Node* iterator,
4938 ZoneHandleSet<Map>* iterated_object_maps) {
4939 DCHECK_EQ(IrOpcode::kJSCreateArrayIterator, iterator->opcode());
4940 Node* iterated_object = NodeProperties::GetValueInput(iterator, 0);
4941 Node* effect = NodeProperties::GetEffectInput(iterator);
4943 NodeProperties::InferReceiverMapsResult result =
4944 NodeProperties::InferReceiverMaps(broker, iterated_object, effect,
4945 iterated_object_maps);
4946 return result != NodeProperties::kNoReceiverMaps;
4952 Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
4953 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
4954 CallParameters
const& p = CallParametersOf(node->op());
4955 Node* iterator = NodeProperties::GetValueInput(node, 1);
4956 Node* context = NodeProperties::GetContextInput(node);
4957 Node* effect = NodeProperties::GetEffectInput(node);
4958 Node* control = NodeProperties::GetControlInput(node);
4960 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
4965 if (iterator->opcode() != IrOpcode::kJSCreateArrayIterator)
return NoChange();
4966 IterationKind
const iteration_kind =
4967 CreateArrayIteratorParametersOf(iterator->op()).kind();
4970 ZoneHandleSet<Map> iterated_object_maps;
4971 if (!InferIteratedObjectMaps(broker(), iterator, &iterated_object_maps)) {
4974 DCHECK_NE(0, iterated_object_maps.size());
4977 ElementsKind elements_kind =
4978 MapRef(broker(), iterated_object_maps[0]).elements_kind();
4979 if (IsFixedTypedArrayElementsKind(elements_kind)) {
4981 if (elements_kind == BIGUINT64_ELEMENTS ||
4982 elements_kind == BIGINT64_ELEMENTS) {
4985 for (Handle<Map> map : iterated_object_maps) {
4986 MapRef iterated_object_map(broker(), map);
4987 if (iterated_object_map.elements_kind() != elements_kind) {
4992 if (!CanInlineArrayIteratingBuiltin(broker(), iterated_object_maps,
4999 if (IsHoleyElementsKind(elements_kind)) {
5000 dependencies()->DependOnProtector(
5001 PropertyCellRef(broker(), factory()->no_elements_protector()));
5005 Node* iterated_object = effect =
5006 graph()->NewNode(simplified()->LoadField(
5007 AccessBuilder::ForJSArrayIteratorIteratedObject()),
5008 iterator, effect, control);
5011 effect = graph()->NewNode(
5012 simplified()->CheckMaps(CheckMapsFlag::kNone, iterated_object_maps,
5014 iterated_object, effect, control);
5016 if (IsFixedTypedArrayElementsKind(elements_kind)) {
5018 if (isolate()->IsArrayBufferNeuteringIntact()) {
5021 dependencies()->DependOnProtector(PropertyCellRef(
5022 broker(), factory()->array_buffer_neutering_protector()));
5025 Node* buffer = effect = graph()->NewNode(
5026 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
5027 iterated_object, effect, control);
5028 Node* buffer_bit_field = effect = graph()->NewNode(
5029 simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
5030 buffer, effect, control);
5031 Node* check = graph()->NewNode(
5032 simplified()->NumberEqual(),
5034 simplified()->NumberBitwiseAnd(), buffer_bit_field,
5035 jsgraph()->Constant(JSArrayBuffer::WasNeuteredBit::kMask)),
5036 jsgraph()->ZeroConstant());
5037 effect = graph()->NewNode(
5038 simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasNeutered,
5040 check, effect, control);
5048 FieldAccess index_access = AccessBuilder::ForJSArrayIteratorNextIndex();
5049 if (IsFixedTypedArrayElementsKind(elements_kind)) {
5050 index_access.type = TypeCache::Get().kJSTypedArrayLengthType;
5051 index_access.machine_type = MachineType::TaggedSigned();
5052 index_access.write_barrier_kind = kNoWriteBarrier;
5054 index_access.type = TypeCache::Get().kJSArrayLengthType;
5056 Node* index = effect = graph()->NewNode(simplified()->LoadField(index_access),
5057 iterator, effect, control);
5065 Node* elements = effect = graph()->NewNode(
5066 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
5067 iterated_object, effect, control);
5072 FieldAccess length_access =
5073 IsFixedTypedArrayElementsKind(elements_kind)
5074 ? AccessBuilder::ForJSTypedArrayLength()
5075 : AccessBuilder::ForJSArrayLength(elements_kind);
5076 Node* length = effect = graph()->NewNode(
5077 simplified()->LoadField(length_access), iterated_object, effect, control);
5080 Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, length);
5082 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
5086 Node* etrue = effect;
5087 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
5090 index = etrue = graph()->NewNode(
5091 common()->TypeGuard(
5092 Type::Range(0.0, length_access.type.Max() - 1.0, graph()->zone())),
5093 index, etrue, if_true);
5095 done_true = jsgraph()->FalseConstant();
5096 if (iteration_kind == IterationKind::kKeys) {
5100 DCHECK(iteration_kind == IterationKind::kEntries ||
5101 iteration_kind == IterationKind::kValues);
5103 if (IsFixedTypedArrayElementsKind(elements_kind)) {
5104 Node* base_ptr = etrue = graph()->NewNode(
5105 simplified()->LoadField(
5106 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
5107 elements, etrue, if_true);
5108 Node* external_ptr = etrue = graph()->NewNode(
5109 simplified()->LoadField(
5110 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
5111 elements, etrue, if_true);
5113 ExternalArrayType array_type = kExternalInt8Array;
5114 switch (elements_kind) {
5115 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \ 5116 case TYPE##_ELEMENTS: \ 5117 array_type = kExternal##Type##Array; \ 5119 TYPED_ARRAYS(TYPED_ARRAY_CASE)
5122 #undef TYPED_ARRAY_CASE 5125 Node* buffer = etrue =
5126 graph()->NewNode(simplified()->LoadField(
5127 AccessBuilder::ForJSArrayBufferViewBuffer()),
5128 iterated_object, etrue, if_true);
5130 value_true = etrue =
5131 graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
5132 base_ptr, external_ptr, index, etrue, if_true);
5134 value_true = etrue = graph()->NewNode(
5135 simplified()->LoadElement(
5136 AccessBuilder::ForFixedArrayElement(elements_kind)),
5137 elements, index, etrue, if_true);
5140 if (elements_kind == HOLEY_ELEMENTS ||
5141 elements_kind == HOLEY_SMI_ELEMENTS) {
5142 value_true = graph()->NewNode(
5143 simplified()->ConvertTaggedHoleToUndefined(), value_true);
5144 }
else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
5146 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
5147 value_true = etrue = graph()->NewNode(
5148 simplified()->CheckFloat64Hole(mode, p.feedback()), value_true,
5153 if (iteration_kind == IterationKind::kEntries) {
5155 value_true = etrue =
5156 graph()->NewNode(javascript()->CreateKeyValueArray(), index,
5157 value_true, context, etrue);
5159 DCHECK_EQ(IterationKind::kValues, iteration_kind);
5165 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
5166 jsgraph()->OneConstant());
5167 etrue = graph()->NewNode(simplified()->StoreField(index_access), iterator,
5168 next_index, etrue, if_true);
5173 Node* efalse = effect;
5174 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
5177 done_false = jsgraph()->TrueConstant();
5178 value_false = jsgraph()->UndefinedConstant();
5180 if (!IsFixedTypedArrayElementsKind(elements_kind)) {
5191 Node* end_index = jsgraph()->Constant(index_access.type.Max());
5192 efalse = graph()->NewNode(simplified()->StoreField(index_access),
5193 iterator, end_index, efalse, if_false);
5197 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
5198 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
5200 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
5201 value_true, value_false, control);
5203 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
5204 done_true, done_false, control);
5207 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
5208 value, done, context, effect);
5209 ReplaceWithValue(node, value, effect, control);
5210 return Replace(value);
5215 Reduction JSCallReducer::ReduceStringPrototypeStringAt(
5216 const Operator* string_access_operator, Node* node) {
5217 DCHECK(string_access_operator->opcode() == IrOpcode::kStringCharCodeAt ||
5218 string_access_operator->opcode() == IrOpcode::kStringCodePointAt);
5219 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5220 CallParameters
const& p = CallParametersOf(node->op());
5221 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5225 Node* receiver = NodeProperties::GetValueInput(node, 1);
5226 Node* index = node->op()->ValueInputCount() >= 3
5227 ? NodeProperties::GetValueInput(node, 2)
5228 : jsgraph()->ZeroConstant();
5229 Node* effect = NodeProperties::GetEffectInput(node);
5230 Node* control = NodeProperties::GetControlInput(node);
5233 receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
5234 receiver, effect, control);
5237 Node* receiver_length =
5238 graph()->NewNode(simplified()->StringLength(), receiver);
5241 index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
5242 index, receiver_length, effect, control);
5245 Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
5246 Node* value = effect = graph()->NewNode(string_access_operator, receiver,
5247 masked_index, effect, control);
5249 ReplaceWithValue(node, value, effect, control);
5250 return Replace(value);
5254 Reduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) {
5255 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5256 CallParameters
const& p = CallParametersOf(node->op());
5257 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5261 Node* receiver = NodeProperties::GetValueInput(node, 1);
5262 Node* index = node->op()->ValueInputCount() >= 3
5263 ? NodeProperties::GetValueInput(node, 2)
5264 : jsgraph()->ZeroConstant();
5265 Node* effect = NodeProperties::GetEffectInput(node);
5266 Node* control = NodeProperties::GetControlInput(node);
5269 receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
5270 receiver, effect, control);
5273 Node* receiver_length =
5274 graph()->NewNode(simplified()->StringLength(), receiver);
5277 index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
5278 index, receiver_length, effect, control);
5281 Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
5282 Node* value = effect =
5283 graph()->NewNode(simplified()->StringCharCodeAt(), receiver, masked_index,
5285 value = graph()->NewNode(simplified()->StringFromSingleCharCode(), value);
5287 ReplaceWithValue(node, value, effect, control);
5288 return Replace(value);
5291 #ifdef V8_INTL_SUPPORT 5293 Reduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) {
5294 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5295 CallParameters
const& p = CallParametersOf(node->op());
5296 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5299 Node* effect = NodeProperties::GetEffectInput(node);
5300 Node* control = NodeProperties::GetControlInput(node);
5302 Node* receiver = effect =
5303 graph()->NewNode(simplified()->CheckString(p.feedback()),
5304 NodeProperties::GetValueInput(node, 1), effect, control);
5306 NodeProperties::ReplaceEffectInput(node, effect);
5307 RelaxEffectsAndControls(node);
5308 node->ReplaceInput(0, receiver);
5309 node->TrimInputCount(1);
5310 NodeProperties::ChangeOp(node, simplified()->StringToLowerCaseIntl());
5311 NodeProperties::SetType(node, Type::String());
5312 return Changed(node);
5315 Reduction JSCallReducer::ReduceStringPrototypeToUpperCaseIntl(Node* node) {
5316 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5317 CallParameters
const& p = CallParametersOf(node->op());
5318 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5321 Node* effect = NodeProperties::GetEffectInput(node);
5322 Node* control = NodeProperties::GetControlInput(node);
5324 Node* receiver = effect =
5325 graph()->NewNode(simplified()->CheckString(p.feedback()),
5326 NodeProperties::GetValueInput(node, 1), effect, control);
5328 NodeProperties::ReplaceEffectInput(node, effect);
5329 RelaxEffectsAndControls(node);
5330 node->ReplaceInput(0, receiver);
5331 node->TrimInputCount(1);
5332 NodeProperties::ChangeOp(node, simplified()->StringToUpperCaseIntl());
5333 NodeProperties::SetType(node, Type::String());
5334 return Changed(node);
5337 #endif // V8_INTL_SUPPORT 5340 Reduction JSCallReducer::ReduceStringFromCharCode(Node* node) {
5341 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5342 CallParameters
const& p = CallParametersOf(node->op());
5343 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5346 if (node->op()->ValueInputCount() == 3) {
5347 Node* effect = NodeProperties::GetEffectInput(node);
5348 Node* control = NodeProperties::GetControlInput(node);
5349 Node* input = NodeProperties::GetValueInput(node, 2);
5351 input = effect = graph()->NewNode(
5352 simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
5354 input, effect, control);
5357 graph()->NewNode(simplified()->StringFromSingleCharCode(), input);
5358 ReplaceWithValue(node, value, effect);
5359 return Replace(value);
5365 Reduction JSCallReducer::ReduceStringFromCodePoint(Node* node) {
5366 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5367 CallParameters
const& p = CallParametersOf(node->op());
5368 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5371 if (node->op()->ValueInputCount() == 3) {
5372 Node* effect = NodeProperties::GetEffectInput(node);
5373 Node* control = NodeProperties::GetControlInput(node);
5374 Node* input = NodeProperties::GetValueInput(node, 2);
5377 graph()->NewNode(simplified()->CheckBounds(p.feedback()), input,
5378 jsgraph()->Constant(0x10FFFF + 1), effect, control);
5380 Node* value = graph()->NewNode(
5381 simplified()->StringFromSingleCodePoint(UnicodeEncoding::UTF32), input);
5382 ReplaceWithValue(node, value, effect);
5383 return Replace(value);
5388 Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) {
5389 CallParameters
const& p = CallParametersOf(node->op());
5390 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5393 Node* effect = NodeProperties::GetEffectInput(node);
5394 Node* control = NodeProperties::GetControlInput(node);
5395 Node* receiver = effect =
5396 graph()->NewNode(simplified()->CheckString(p.feedback()),
5397 NodeProperties::GetValueInput(node, 1), effect, control);
5398 Node* iterator = effect =
5399 graph()->NewNode(javascript()->CreateStringIterator(), receiver,
5400 jsgraph()->NoContextConstant(), effect);
5401 ReplaceWithValue(node, iterator, effect, control);
5402 return Replace(iterator);
5405 Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
5406 Node* receiver = NodeProperties::GetValueInput(node, 1);
5407 Node* effect = NodeProperties::GetEffectInput(node);
5408 Node* control = NodeProperties::GetControlInput(node);
5409 Node* context = NodeProperties::GetContextInput(node);
5410 if (NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
5411 JS_STRING_ITERATOR_TYPE)) {
5412 Node*
string = effect = graph()->NewNode(
5413 simplified()->LoadField(AccessBuilder::ForJSStringIteratorString()),
5414 receiver, effect, control);
5415 Node* index = effect = graph()->NewNode(
5416 simplified()->LoadField(AccessBuilder::ForJSStringIteratorIndex()),
5417 receiver, effect, control);
5418 Node* length = graph()->NewNode(simplified()->StringLength(),
string);
5422 graph()->NewNode(simplified()->NumberLessThan(), index, length);
5424 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
5426 Node* etrue0 = effect;
5427 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
5431 done_true = jsgraph()->FalseConstant();
5432 Node* codepoint = etrue0 = graph()->NewNode(
5433 simplified()->StringCodePointAt(UnicodeEncoding::UTF16),
string,
5434 index, etrue0, if_true0);
5435 vtrue0 = graph()->NewNode(
5436 simplified()->StringFromSingleCodePoint(UnicodeEncoding::UTF16),
5441 graph()->NewNode(simplified()->StringLength(), vtrue0);
5442 index = graph()->NewNode(simplified()->NumberAdd(), index, char_length);
5443 etrue0 = graph()->NewNode(
5444 simplified()->StoreField(AccessBuilder::ForJSStringIteratorIndex()),
5445 receiver, index, etrue0, if_true0);
5448 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
5452 vfalse0 = jsgraph()->UndefinedConstant();
5453 done_false = jsgraph()->TrueConstant();
5456 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
5457 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, effect, control);
5459 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
5460 vtrue0, vfalse0, control);
5462 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
5463 done_true, done_false, control);
5465 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
5466 value, done, context, effect);
5468 ReplaceWithValue(node, value, effect, control);
5469 return Replace(value);
5475 Reduction JSCallReducer::ReduceStringPrototypeConcat(Node* node) {
5476 if (node->op()->ValueInputCount() < 2 || node->op()->ValueInputCount() > 3) {
5479 CallParameters
const& p = CallParametersOf(node->op());
5480 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5484 Node* effect = NodeProperties::GetEffectInput(node);
5485 Node* control = NodeProperties::GetControlInput(node);
5486 Node* receiver = effect =
5487 graph()->NewNode(simplified()->CheckString(p.feedback()),
5488 NodeProperties::GetValueInput(node, 1), effect, control);
5490 if (node->op()->ValueInputCount() < 3) {
5491 ReplaceWithValue(node, receiver, effect, control);
5492 return Replace(receiver);
5495 Node* argument = effect =
5496 graph()->NewNode(simplified()->CheckString(p.feedback()),
5497 NodeProperties::GetValueInput(node, 2), effect, control);
5498 Node* receiver_length =
5499 graph()->NewNode(simplified()->StringLength(), receiver);
5500 Node* argument_length =
5501 graph()->NewNode(simplified()->StringLength(), argument);
5502 Node* length = graph()->NewNode(simplified()->NumberAdd(), receiver_length,
5504 length = effect = graph()->NewNode(
5505 simplified()->CheckBounds(p.feedback()), length,
5506 jsgraph()->Constant(String::kMaxLength + 1), effect, control);
5508 Node* value = graph()->NewNode(simplified()->StringConcat(), length, receiver,
5511 ReplaceWithValue(node, value, effect, control);
5512 return Replace(value);
5515 Node* JSCallReducer::CreateArtificialFrameState(
5516 Node* node, Node* outer_frame_state,
int parameter_count,
5517 BailoutId bailout_id, FrameStateType frame_state_type,
5518 const SharedFunctionInfoRef& shared, Node* context) {
5519 const FrameStateFunctionInfo* state_info =
5520 common()->CreateFrameStateFunctionInfo(
5521 frame_state_type, parameter_count + 1, 0, shared.object());
5523 const Operator* op = common()->FrameState(
5524 bailout_id, OutputFrameStateCombine::Ignore(), state_info);
5525 const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
5526 Node* node0 = graph()->NewNode(op0);
5527 std::vector<Node*> params;
5528 params.reserve(parameter_count + 1);
5529 for (
int parameter = 0; parameter < parameter_count + 1; ++parameter) {
5530 params.push_back(node->InputAt(1 + parameter));
5532 const Operator* op_param = common()->StateValues(
5533 static_cast<int>(params.size()), SparseInputMask::Dense());
5534 Node* params_node = graph()->NewNode(
5535 op_param, static_cast<int>(params.size()), ¶ms.front());
5537 context = jsgraph()->UndefinedConstant();
5539 return graph()->NewNode(op, params_node, node0, node0, context,
5540 node->InputAt(0), outer_frame_state);
5543 Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
5544 DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
5545 ConstructParameters
const& p = ConstructParametersOf(node->op());
5546 int arity =
static_cast<int>(p.arity() - 2);
5548 if (arity < 1)
return NoChange();
5549 Node* target = NodeProperties::GetValueInput(node, 0);
5550 Node* executor = NodeProperties::GetValueInput(node, 1);
5551 Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
5553 Node* context = NodeProperties::GetContextInput(node);
5554 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
5555 Node* effect = NodeProperties::GetEffectInput(node);
5556 Node* control = NodeProperties::GetControlInput(node);
5558 if (!FLAG_experimental_inline_promise_constructor)
return NoChange();
5559 if (!isolate()->IsPromiseHookProtectorIntact())
return NoChange();
5562 if (target != new_target)
return NoChange();
5564 dependencies()->DependOnProtector(
5565 PropertyCellRef(broker(), factory()->promise_hook_protector()));
5567 SharedFunctionInfoRef promise_shared =
5568 native_context().promise_function().shared();
5574 DCHECK_EQ(1, promise_shared.internal_formal_parameter_count());
5575 Node* constructor_frame_state = CreateArtificialFrameState(
5576 node, outer_frame_state, 1, BailoutId::ConstructStubInvoke(),
5577 FrameStateType::kConstructStub, promise_shared, context);
5581 const std::vector<Node*> checkpoint_parameters({
5582 jsgraph()->UndefinedConstant(),
5583 jsgraph()->UndefinedConstant(),
5584 jsgraph()->UndefinedConstant(),
5585 jsgraph()->TheHoleConstant()
5587 int checkpoint_parameters_size =
5588 static_cast<int>(checkpoint_parameters.size());
5589 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
5590 jsgraph(), promise_shared,
5591 Builtins::kPromiseConstructorLazyDeoptContinuation, target, context,
5592 checkpoint_parameters.data(), checkpoint_parameters_size,
5593 constructor_frame_state, ContinuationFrameStateMode::LAZY);
5596 Node* check_fail =
nullptr;
5597 Node* check_throw =
nullptr;
5598 WireInCallbackIsCallableCheck(executor, context, frame_state, effect,
5599 &control, &check_fail, &check_throw);
5602 Node* promise = effect =
5603 graph()->NewNode(javascript()->CreatePromise(), context, effect);
5607 Node* promise_context = effect = graph()->NewNode(
5608 javascript()->CreateFunctionContext(
5609 handle(native_context().
object()->scope_info(), isolate()),
5610 PromiseBuiltinsAssembler::kPromiseContextLength -
5611 Context::MIN_CONTEXT_SLOTS,
5613 context, effect, control);
5615 graph()->NewNode(simplified()->StoreField(AccessBuilder::ForContextSlot(
5616 PromiseBuiltinsAssembler::kPromiseSlot)),
5617 promise_context, promise, effect, control);
5618 effect = graph()->NewNode(
5619 simplified()->StoreField(AccessBuilder::ForContextSlot(
5620 PromiseBuiltinsAssembler::kAlreadyResolvedSlot)),
5621 promise_context, jsgraph()->FalseConstant(), effect, control);
5622 effect = graph()->NewNode(
5623 simplified()->StoreField(AccessBuilder::ForContextSlot(
5624 PromiseBuiltinsAssembler::kDebugEventSlot)),
5625 promise_context, jsgraph()->TrueConstant(), effect, control);
5628 SharedFunctionInfoRef resolve_shared =
5629 native_context().promise_capability_default_resolve_shared_fun();
5630 Node* resolve = effect = graph()->NewNode(
5631 javascript()->CreateClosure(
5632 resolve_shared.object(), factory()->many_closures_cell(),
5633 handle(resolve_shared.object()->GetCode(), isolate())),
5634 promise_context, effect, control);
5637 SharedFunctionInfoRef reject_shared =
5638 native_context().promise_capability_default_reject_shared_fun();
5639 Node* reject = effect = graph()->NewNode(
5640 javascript()->CreateClosure(
5641 reject_shared.object(), factory()->many_closures_cell(),
5642 handle(reject_shared.object()->GetCode(), isolate())),
5643 promise_context, effect, control);
5645 const std::vector<Node*> checkpoint_parameters_continuation(
5646 {jsgraph()->UndefinedConstant() , promise, reject});
5647 int checkpoint_parameters_continuation_size =
5648 static_cast<int>(checkpoint_parameters_continuation.size());
5651 frame_state = CreateJavaScriptBuiltinContinuationFrameState(
5652 jsgraph(), promise_shared,
5653 Builtins::kPromiseConstructorLazyDeoptContinuation, target, context,
5654 checkpoint_parameters_continuation.data(),
5655 checkpoint_parameters_continuation_size, constructor_frame_state,
5656 ContinuationFrameStateMode::LAZY_WITH_CATCH);
5659 effect = control = graph()->NewNode(
5660 javascript()->Call(4, p.frequency(), VectorSlotPair(),
5661 ConvertReceiverMode::kNullOrUndefined,
5662 SpeculationMode::kDisallowSpeculation),
5663 executor, jsgraph()->UndefinedConstant(), resolve, reject, context,
5664 frame_state, effect, control);
5666 Node* exception_effect = effect;
5667 Node* exception_control = control;
5669 Node* reason = exception_effect = exception_control = graph()->NewNode(
5670 common()->IfException(), exception_control, exception_effect);
5672 exception_effect = exception_control = graph()->NewNode(
5673 javascript()->Call(3, p.frequency(), VectorSlotPair(),
5674 ConvertReceiverMode::kNullOrUndefined,
5675 SpeculationMode::kDisallowSpeculation),
5676 reject, jsgraph()->UndefinedConstant(), reason, context, frame_state,
5677 exception_effect, exception_control);
5680 Node* on_exception =
nullptr;
5681 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
5682 RewirePostCallbackExceptionEdges(check_throw, on_exception,
5683 exception_effect, &check_fail,
5684 &exception_control);
5688 Node* success_effect = effect;
5689 Node* success_control = control;
5691 success_control = graph()->NewNode(common()->IfSuccess(), success_control);
5695 graph()->NewNode(common()->Merge(2), success_control, exception_control);
5696 effect = graph()->NewNode(common()->EffectPhi(2), success_effect,
5697 exception_effect, control);
5704 graph()->NewNode(common()->Throw(), check_throw, check_fail);
5705 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
5707 ReplaceWithValue(node, promise, effect, control);
5708 return Replace(promise);
5712 Reduction JSCallReducer::ReducePromiseInternalConstructor(Node* node) {
5713 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5714 Node* context = NodeProperties::GetContextInput(node);
5715 Node* effect = NodeProperties::GetEffectInput(node);
5718 if (!isolate()->IsPromiseHookProtectorIntact())
return NoChange();
5720 dependencies()->DependOnProtector(
5721 PropertyCellRef(broker(), factory()->promise_hook_protector()));
5724 Node* value = effect =
5725 graph()->NewNode(javascript()->CreatePromise(), context, effect);
5727 ReplaceWithValue(node, value, effect);
5728 return Replace(value);
5732 Reduction JSCallReducer::ReducePromiseInternalReject(Node* node) {
5733 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5734 Node* promise = node->op()->ValueInputCount() >= 2
5735 ? NodeProperties::GetValueInput(node, 2)
5736 : jsgraph()->UndefinedConstant();
5737 Node* reason = node->op()->ValueInputCount() >= 3
5738 ? NodeProperties::GetValueInput(node, 3)
5739 : jsgraph()->UndefinedConstant();
5740 Node* debug_event = jsgraph()->TrueConstant();
5741 Node* frame_state = NodeProperties::GetFrameStateInput(node);
5742 Node* context = NodeProperties::GetContextInput(node);
5743 Node* effect = NodeProperties::GetEffectInput(node);
5744 Node* control = NodeProperties::GetControlInput(node);
5747 Node* value = effect =
5748 graph()->NewNode(javascript()->RejectPromise(), promise, reason,
5749 debug_event, context, frame_state, effect, control);
5751 ReplaceWithValue(node, value, effect, control);
5752 return Replace(value);
5756 Reduction JSCallReducer::ReducePromiseInternalResolve(Node* node) {
5757 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5758 Node* promise = node->op()->ValueInputCount() >= 2
5759 ? NodeProperties::GetValueInput(node, 2)
5760 : jsgraph()->UndefinedConstant();
5761 Node* resolution = node->op()->ValueInputCount() >= 3
5762 ? NodeProperties::GetValueInput(node, 3)
5763 : jsgraph()->UndefinedConstant();
5764 Node* frame_state = NodeProperties::GetFrameStateInput(node);
5765 Node* context = NodeProperties::GetContextInput(node);
5766 Node* effect = NodeProperties::GetEffectInput(node);
5767 Node* control = NodeProperties::GetControlInput(node);
5770 Node* value = effect =
5771 graph()->NewNode(javascript()->ResolvePromise(), promise, resolution,
5772 context, frame_state, effect, control);
5774 ReplaceWithValue(node, value, effect, control);
5775 return Replace(value);
5779 Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
5780 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5781 CallParameters
const& p = CallParametersOf(node->op());
5782 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5785 int arity =
static_cast<int>(p.arity() - 2);
5786 Node* receiver = NodeProperties::GetValueInput(node, 1);
5787 Node* effect = NodeProperties::GetEffectInput(node);
5788 Node* control = NodeProperties::GetControlInput(node);
5794 if (!isolate()->IsPromiseThenLookupChainIntact())
return NoChange();
5797 ZoneHandleSet<Map> receiver_maps;
5798 NodeProperties::InferReceiverMapsResult result =
5799 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
5801 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
5802 DCHECK_NE(0, receiver_maps.size());
5806 for (Handle<Map> map : receiver_maps) {
5807 MapRef receiver_map(broker(), map);
5808 if (!receiver_map.IsJSPromiseMap())
return NoChange();
5809 receiver_map.SerializePrototype();
5810 if (!receiver_map.prototype().equals(
5811 native_context().promise_prototype())) {
5816 dependencies()->DependOnProtector(
5817 PropertyCellRef(broker(), factory()->promise_then_protector()));
5821 if (result == NodeProperties::kUnreliableReceiverMaps) {
5823 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
5824 receiver_maps, p.feedback()),
5825 receiver, effect, control);
5831 Node* target = jsgraph()->Constant(native_context().promise_then());
5832 NodeProperties::ReplaceValueInput(node, target, 0);
5833 NodeProperties::ReplaceEffectInput(node, effect);
5834 for (; arity > 1; --arity) node->RemoveInput(3);
5835 for (; arity < 2; ++arity) {
5836 node->InsertInput(graph()->zone(), 2, jsgraph()->UndefinedConstant());
5838 NodeProperties::ChangeOp(
5839 node, javascript()->Call(2 + arity, p.frequency(), p.feedback(),
5840 ConvertReceiverMode::kNotNullOrUndefined,
5841 p.speculation_mode()));
5842 Reduction
const reduction = ReducePromisePrototypeThen(node);
5843 return reduction.Changed() ? reduction : Changed(node);
5847 Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
5848 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
5849 CallParameters
const& p = CallParametersOf(node->op());
5850 int arity =
static_cast<int>(p.arity() - 2);
5851 Node* receiver = NodeProperties::GetValueInput(node, 1);
5852 Node* on_finally = arity >= 1 ? NodeProperties::GetValueInput(node, 2)
5853 : jsgraph()->UndefinedConstant();
5854 Node* effect = NodeProperties::GetEffectInput(node);
5855 Node* control = NodeProperties::GetControlInput(node);
5856 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
5861 if (!isolate()->IsPromiseHookProtectorIntact())
return NoChange();
5867 if (!isolate()->IsPromiseThenLookupChainIntact())
return NoChange();
5873 if (!isolate()->IsPromiseSpeciesLookupChainIntact())
return NoChange();
5876 ZoneHandleSet<Map> receiver_maps;
5877 NodeProperties::InferReceiverMapsResult result =
5878 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
5880 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
5881 DCHECK_NE(0, receiver_maps.size());
5885 for (Handle<Map> map : receiver_maps) {
5886 MapRef receiver_map(broker(), map);
5887 if (!receiver_map.IsJSPromiseMap())
return NoChange();
5888 receiver_map.SerializePrototype();
5889 if (!receiver_map.prototype().equals(
5890 native_context().promise_prototype())) {
5895 dependencies()->DependOnProtector(
5896 PropertyCellRef(broker(), factory()->promise_hook_protector()));
5897 dependencies()->DependOnProtector(
5898 PropertyCellRef(broker(), factory()->promise_then_protector()));
5899 dependencies()->DependOnProtector(
5900 PropertyCellRef(broker(), factory()->promise_species_protector()));
5904 if (result == NodeProperties::kUnreliableReceiverMaps) {
5906 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
5907 receiver_maps, p.feedback()),
5908 receiver, effect, control);
5913 Node* check = graph()->NewNode(simplified()->ObjectIsCallable(), on_finally);
5915 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
5917 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
5918 Node* etrue = effect;
5922 Node* context = jsgraph()->Constant(native_context());
5924 jsgraph()->Constant(native_context().promise_function());
5927 context = etrue = graph()->NewNode(
5928 javascript()->CreateFunctionContext(
5929 handle(native_context().
object()->scope_info(), isolate()),
5930 PromiseBuiltinsAssembler::kPromiseFinallyContextLength -
5931 Context::MIN_CONTEXT_SLOTS,
5933 context, etrue, if_true);
5935 graph()->NewNode(simplified()->StoreField(AccessBuilder::ForContextSlot(
5936 PromiseBuiltinsAssembler::kOnFinallySlot)),
5937 context, on_finally, etrue, if_true);
5939 graph()->NewNode(simplified()->StoreField(AccessBuilder::ForContextSlot(
5940 PromiseBuiltinsAssembler::kConstructorSlot)),
5941 context, constructor, etrue, if_true);
5944 SharedFunctionInfoRef catch_finally =
5945 native_context().promise_catch_finally_shared_fun();
5946 catch_true = etrue = graph()->NewNode(
5947 javascript()->CreateClosure(
5948 catch_finally.object(), factory()->many_closures_cell(),
5949 handle(catch_finally.object()->GetCode(), isolate())),
5950 context, etrue, if_true);
5953 SharedFunctionInfoRef then_finally =
5954 native_context().promise_then_finally_shared_fun();
5955 then_true = etrue = graph()->NewNode(
5956 javascript()->CreateClosure(
5957 then_finally.object(), factory()->many_closures_cell(),
5958 handle(then_finally.object()->GetCode(), isolate())),
5959 context, etrue, if_true);
5962 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
5963 Node* efalse = effect;
5964 Node* catch_false = on_finally;
5965 Node* then_false = on_finally;
5967 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
5968 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
5969 Node* catch_finally =
5970 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
5971 catch_true, catch_false, control);
5972 Node* then_finally =
5973 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
5974 then_true, then_false, control);
5979 effect = graph()->NewNode(simplified()->MapGuard(receiver_maps), receiver,
5985 Node* target = jsgraph()->Constant(native_context().promise_then());
5986 NodeProperties::ReplaceValueInput(node, target, 0);
5987 NodeProperties::ReplaceEffectInput(node, effect);
5988 NodeProperties::ReplaceControlInput(node, control);
5989 for (; arity > 2; --arity) node->RemoveInput(2);
5990 for (; arity < 2; ++arity)
5991 node->InsertInput(graph()->zone(), 2, then_finally);
5992 node->ReplaceInput(2, then_finally);
5993 node->ReplaceInput(3, catch_finally);
5994 NodeProperties::ChangeOp(
5995 node, javascript()->Call(2 + arity, p.frequency(), p.feedback(),
5996 ConvertReceiverMode::kNotNullOrUndefined,
5997 p.speculation_mode()));
5998 Reduction
const reduction = ReducePromisePrototypeThen(node);
5999 return reduction.Changed() ? reduction : Changed(node);
6002 Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
6003 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
6004 CallParameters
const& p = CallParametersOf(node->op());
6005 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
6009 Node* receiver = NodeProperties::GetValueInput(node, 1);
6010 Node* on_fulfilled = node->op()->ValueInputCount() > 2
6011 ? NodeProperties::GetValueInput(node, 2)
6012 : jsgraph()->UndefinedConstant();
6013 Node* on_rejected = node->op()->ValueInputCount() > 3
6014 ? NodeProperties::GetValueInput(node, 3)
6015 : jsgraph()->UndefinedConstant();
6016 Node* context = NodeProperties::GetContextInput(node);
6017 Node* effect = NodeProperties::GetEffectInput(node);
6018 Node* control = NodeProperties::GetControlInput(node);
6019 Node* frame_state = NodeProperties::GetFrameStateInput(node);
6022 if (!isolate()->IsPromiseHookProtectorIntact())
return NoChange();
6028 if (!isolate()->IsPromiseSpeciesLookupChainIntact())
return NoChange();
6031 ZoneHandleSet<Map> receiver_maps;
6032 NodeProperties::InferReceiverMapsResult infer_receiver_maps_result =
6033 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
6035 if (infer_receiver_maps_result == NodeProperties::kNoReceiverMaps) {
6038 DCHECK_NE(0, receiver_maps.size());
6042 for (Handle<Map> map : receiver_maps) {
6043 MapRef receiver_map(broker(), map);
6044 if (!receiver_map.IsJSPromiseMap())
return NoChange();
6045 receiver_map.SerializePrototype();
6046 if (!receiver_map.prototype().equals(
6047 native_context().promise_prototype())) {
6052 dependencies()->DependOnProtector(
6053 PropertyCellRef(broker(), factory()->promise_hook_protector()));
6054 dependencies()->DependOnProtector(
6055 PropertyCellRef(broker(), factory()->promise_species_protector()));
6059 if (infer_receiver_maps_result == NodeProperties::kUnreliableReceiverMaps) {
6061 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
6062 receiver_maps, p.feedback()),
6063 receiver, effect, control);
6067 on_fulfilled = graph()->NewNode(
6068 common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
6069 graph()->NewNode(simplified()->ObjectIsCallable(), on_fulfilled),
6070 on_fulfilled, jsgraph()->UndefinedConstant());
6073 on_rejected = graph()->NewNode(
6074 common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
6075 graph()->NewNode(simplified()->ObjectIsCallable(), on_rejected),
6076 on_rejected, jsgraph()->UndefinedConstant());
6079 Node* result = effect =
6080 graph()->NewNode(javascript()->CreatePromise(), context, effect);
6083 result = effect = graph()->NewNode(
6084 javascript()->PerformPromiseThen(), receiver, on_fulfilled, on_rejected,
6085 result, context, frame_state, effect, control);
6093 MapRef result_map = native_context().promise_function().initial_map();
6094 effect = graph()->NewNode(
6095 simplified()->MapGuard(ZoneHandleSet<Map>(result_map.object())), result,
6098 ReplaceWithValue(node, result, effect, control);
6099 return Replace(result);
6103 Reduction JSCallReducer::ReducePromiseResolveTrampoline(Node* node) {
6104 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
6105 Node* receiver = NodeProperties::GetValueInput(node, 1);
6106 Node* value = node->op()->ValueInputCount() > 2
6107 ? NodeProperties::GetValueInput(node, 2)
6108 : jsgraph()->UndefinedConstant();
6109 Node* context = NodeProperties::GetContextInput(node);
6110 Node* frame_state = NodeProperties::GetFrameStateInput(node);
6111 Node* effect = NodeProperties::GetEffectInput(node);
6112 Node* control = NodeProperties::GetControlInput(node);
6115 ZoneHandleSet<Map> receiver_maps;
6116 NodeProperties::InferReceiverMapsResult infer_receiver_maps_result =
6117 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
6119 if (infer_receiver_maps_result == NodeProperties::kNoReceiverMaps) {
6122 DCHECK_NE(0, receiver_maps.size());
6125 for (Handle<Map> map : receiver_maps) {
6126 MapRef receiver_map(broker(), map);
6127 if (!receiver_map.IsJSReceiverMap())
return NoChange();
6131 node->ReplaceInput(0, receiver);
6132 node->ReplaceInput(1, value);
6133 node->ReplaceInput(2, context);
6134 node->ReplaceInput(3, frame_state);
6135 node->ReplaceInput(4, effect);
6136 node->ReplaceInput(5, control);
6137 node->TrimInputCount(6);
6138 NodeProperties::ChangeOp(node, javascript()->PromiseResolve());
6139 return Changed(node);
6143 Reduction JSCallReducer::ReduceTypedArrayConstructor(
6144 Node* node,
const SharedFunctionInfoRef& shared) {
6145 DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
6146 ConstructParameters
const& p = ConstructParametersOf(node->op());
6147 int arity =
static_cast<int>(p.arity() - 2);
6148 Node* target = NodeProperties::GetValueInput(node, 0);
6149 Node* arg1 = (arity >= 1) ? NodeProperties::GetValueInput(node, 1)
6150 : jsgraph()->UndefinedConstant();
6151 Node* arg2 = (arity >= 2) ? NodeProperties::GetValueInput(node, 2)
6152 : jsgraph()->UndefinedConstant();
6153 Node* arg3 = (arity >= 3) ? NodeProperties::GetValueInput(node, 3)
6154 : jsgraph()->UndefinedConstant();
6155 Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
6156 Node* context = NodeProperties::GetContextInput(node);
6157 Node* frame_state = NodeProperties::GetFrameStateInput(node);
6158 Node* effect = NodeProperties::GetEffectInput(node);
6159 Node* control = NodeProperties::GetControlInput(node);
6163 frame_state = CreateArtificialFrameState(
6164 node, frame_state, arity, BailoutId::ConstructStubInvoke(),
6165 FrameStateType::kConstructStub, shared, context);
6170 Node*
const parameters[] = {jsgraph()->TheHoleConstant()};
6171 int const num_parameters =
static_cast<int>(arraysize(parameters));
6172 frame_state = CreateJavaScriptBuiltinContinuationFrameState(
6173 jsgraph(), shared, Builtins::kGenericConstructorLazyDeoptContinuation,
6174 target, context, parameters, num_parameters, frame_state,
6175 ContinuationFrameStateMode::LAZY);
6178 graph()->NewNode(javascript()->CreateTypedArray(), target, new_target,
6179 arg1, arg2, arg3, context, frame_state, effect, control);
6180 return Replace(result);
6184 Reduction JSCallReducer::ReduceTypedArrayPrototypeToStringTag(Node* node) {
6185 Node* receiver = NodeProperties::GetValueInput(node, 1);
6186 Node* effect = NodeProperties::GetEffectInput(node);
6187 Node* control = NodeProperties::GetControlInput(node);
6189 NodeVector values(graph()->zone());
6190 NodeVector effects(graph()->zone());
6191 NodeVector controls(graph()->zone());
6193 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
6195 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
6197 values.push_back(jsgraph()->UndefinedConstant());
6198 effects.push_back(effect);
6199 controls.push_back(graph()->NewNode(common()->IfTrue(), control));
6201 control = graph()->NewNode(common()->IfFalse(), control);
6202 Node* receiver_map = effect =
6203 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
6204 receiver, effect, control);
6205 Node* receiver_bit_field2 = effect = graph()->NewNode(
6206 simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map,
6208 Node* receiver_elements_kind = graph()->NewNode(
6209 simplified()->NumberShiftRightLogical(),
6210 graph()->NewNode(simplified()->NumberBitwiseAnd(), receiver_bit_field2,
6211 jsgraph()->Constant(Map::ElementsKindBits::kMask)),
6212 jsgraph()->Constant(Map::ElementsKindBits::kShift));
6217 receiver_elements_kind = graph()->NewNode(
6218 simplified()->NumberSubtract(), receiver_elements_kind,
6219 jsgraph()->Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));
6221 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \ 6223 Node* check = graph()->NewNode( \ 6224 simplified()->NumberEqual(), receiver_elements_kind, \ 6225 jsgraph()->Constant(TYPE##_ELEMENTS - \ 6226 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)); \ 6227 control = graph()->NewNode(common()->Branch(), check, control); \ 6228 values.push_back(jsgraph()->HeapConstant( \ 6229 factory()->InternalizeUtf8String(#Type "Array"))); \ 6230 effects.push_back(effect); \ 6231 controls.push_back(graph()->NewNode(common()->IfTrue(), control)); \ 6232 control = graph()->NewNode(common()->IfFalse(), control); \ 6234 TYPED_ARRAYS(TYPED_ARRAY_CASE)
6235 #undef TYPED_ARRAY_CASE 6237 values.push_back(jsgraph()->UndefinedConstant());
6238 effects.push_back(effect);
6239 controls.push_back(control);
6241 int const count =
static_cast<int>(controls.size());
6242 control = graph()->NewNode(common()->Merge(count), count, &controls.front());
6243 effects.push_back(control);
6245 graph()->NewNode(common()->EffectPhi(count), count + 1, &effects.front());
6246 values.push_back(control);
6248 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
6249 count + 1, &values.front());
6250 ReplaceWithValue(node, value, effect, control);
6251 return Replace(value);
6255 Reduction JSCallReducer::ReduceNumberIsFinite(Node* node) {
6256 if (node->op()->ValueInputCount() < 3) {
6257 Node* value = jsgraph()->FalseConstant();
6258 ReplaceWithValue(node, value);
6259 return Replace(value);
6261 Node* input = NodeProperties::GetValueInput(node, 2);
6262 Node* value = graph()->NewNode(simplified()->ObjectIsFiniteNumber(), input);
6263 ReplaceWithValue(node, value);
6264 return Replace(value);
6268 Reduction JSCallReducer::ReduceNumberIsInteger(Node* node) {
6269 if (node->op()->ValueInputCount() < 3) {
6270 Node* value = jsgraph()->FalseConstant();
6271 ReplaceWithValue(node, value);
6272 return Replace(value);
6274 Node* input = NodeProperties::GetValueInput(node, 2);
6275 Node* value = graph()->NewNode(simplified()->ObjectIsInteger(), input);
6276 ReplaceWithValue(node, value);
6277 return Replace(value);
6281 Reduction JSCallReducer::ReduceNumberIsSafeInteger(Node* node) {
6282 if (node->op()->ValueInputCount() < 3) {
6283 Node* value = jsgraph()->FalseConstant();
6284 ReplaceWithValue(node, value);
6285 return Replace(value);
6287 Node* input = NodeProperties::GetValueInput(node, 2);
6288 Node* value = graph()->NewNode(simplified()->ObjectIsSafeInteger(), input);
6289 ReplaceWithValue(node, value);
6290 return Replace(value);
6294 Reduction JSCallReducer::ReduceNumberIsNaN(Node* node) {
6295 if (node->op()->ValueInputCount() < 3) {
6296 Node* value = jsgraph()->FalseConstant();
6297 ReplaceWithValue(node, value);
6298 return Replace(value);
6300 Node* input = NodeProperties::GetValueInput(node, 2);
6301 Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
6302 ReplaceWithValue(node, value);
6303 return Replace(value);
6306 Reduction JSCallReducer::ReduceMapPrototypeGet(Node* node) {
6308 if (node->op()->ValueInputCount() != 3)
return NoChange();
6309 Node* receiver = NodeProperties::GetValueInput(node, 1);
6310 Node* effect = NodeProperties::GetEffectInput(node);
6311 Node* control = NodeProperties::GetControlInput(node);
6312 Node* key = NodeProperties::GetValueInput(node, 2);
6314 if (!NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
6318 Node* table = effect = graph()->NewNode(
6319 simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
6322 Node* entry = effect = graph()->NewNode(
6323 simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
6325 Node* check = graph()->NewNode(simplified()->NumberEqual(), entry,
6326 jsgraph()->MinusOneConstant());
6328 Node* branch = graph()->NewNode(common()->Branch(), check, control);
6331 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
6332 Node* etrue = effect;
6333 Node* vtrue = jsgraph()->UndefinedConstant();
6336 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
6337 Node* efalse = effect;
6338 Node* vfalse = efalse = graph()->NewNode(
6339 simplified()->LoadElement(AccessBuilder::ForOrderedHashMapEntryValue()),
6340 table, entry, efalse, if_false);
6342 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
6343 Node* value = graph()->NewNode(
6344 common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control);
6345 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
6347 ReplaceWithValue(node, value, effect, control);
6348 return Replace(value);
6351 Reduction JSCallReducer::ReduceMapPrototypeHas(Node* node) {
6353 if (node->op()->ValueInputCount() != 3)
return NoChange();
6354 Node* receiver = NodeProperties::GetValueInput(node, 1);
6355 Node* effect = NodeProperties::GetEffectInput(node);
6356 Node* control = NodeProperties::GetControlInput(node);
6357 Node* key = NodeProperties::GetValueInput(node, 2);
6359 if (!NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
6363 Node* table = effect = graph()->NewNode(
6364 simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
6367 Node* index = effect = graph()->NewNode(
6368 simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
6370 Node* value = graph()->NewNode(simplified()->NumberEqual(), index,
6371 jsgraph()->MinusOneConstant());
6372 value = graph()->NewNode(simplified()->BooleanNot(), value);
6374 ReplaceWithValue(node, value, effect, control);
6375 return Replace(value);
6380 InstanceType InstanceTypeForCollectionKind(CollectionKind kind) {
6382 case CollectionKind::kMap:
6384 case CollectionKind::kSet:
6392 Reduction JSCallReducer::ReduceCollectionIteration(
6393 Node* node, CollectionKind collection_kind, IterationKind iteration_kind) {
6394 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
6395 Node* receiver = NodeProperties::GetValueInput(node, 1);
6396 Node* context = NodeProperties::GetContextInput(node);
6397 Node* effect = NodeProperties::GetEffectInput(node);
6398 Node* control = NodeProperties::GetControlInput(node);
6399 if (NodeProperties::HasInstanceTypeWitness(
6400 broker(), receiver, effect,
6401 InstanceTypeForCollectionKind(collection_kind))) {
6402 Node* js_create_iterator = effect = graph()->NewNode(
6403 javascript()->CreateCollectionIterator(collection_kind, iteration_kind),
6404 receiver, context, effect, control);
6405 ReplaceWithValue(node, js_create_iterator, effect);
6406 return Replace(js_create_iterator);
6411 Reduction JSCallReducer::ReduceCollectionPrototypeSize(
6412 Node* node, CollectionKind collection_kind) {
6413 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
6414 Node* receiver = NodeProperties::GetValueInput(node, 1);
6415 Node* effect = NodeProperties::GetEffectInput(node);
6416 Node* control = NodeProperties::GetControlInput(node);
6417 if (NodeProperties::HasInstanceTypeWitness(
6418 broker(), receiver, effect,
6419 InstanceTypeForCollectionKind(collection_kind))) {
6420 Node* table = effect = graph()->NewNode(
6421 simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
6422 receiver, effect, control);
6423 Node* value = effect = graph()->NewNode(
6424 simplified()->LoadField(
6425 AccessBuilder::ForOrderedHashMapOrSetNumberOfElements()),
6426 table, effect, control);
6427 ReplaceWithValue(node, value, effect, control);
6428 return Replace(value);
6433 Reduction JSCallReducer::ReduceCollectionIteratorPrototypeNext(
6434 Node* node,
int entry_size, Handle<HeapObject> empty_collection,
6435 InstanceType collection_iterator_instance_type_first,
6436 InstanceType collection_iterator_instance_type_last) {
6437 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
6438 Node* receiver = NodeProperties::GetValueInput(node, 1);
6439 Node* context = NodeProperties::GetContextInput(node);
6440 Node* effect = NodeProperties::GetEffectInput(node);
6441 Node* control = NodeProperties::GetControlInput(node);
6456 InstanceType receiver_instance_type;
6457 ZoneHandleSet<Map> receiver_maps;
6458 NodeProperties::InferReceiverMapsResult result =
6459 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
6461 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
6462 DCHECK_NE(0, receiver_maps.size());
6463 receiver_instance_type = receiver_maps[0]->instance_type();
6464 for (
size_t i = 1;
i < receiver_maps.size(); ++
i) {
6465 if (receiver_maps[
i]->instance_type() != receiver_instance_type) {
6469 if (receiver_instance_type < collection_iterator_instance_type_first ||
6470 receiver_instance_type > collection_iterator_instance_type_last) {
6479 Node* loop = control =
6480 graph()->NewNode(common()->Loop(2), control, control);
6481 Node* eloop = effect =
6482 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
6483 Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
6484 NodeProperties::MergeControlToEnd(graph(), common(), terminate);
6487 Node* table = effect = graph()->NewNode(
6488 simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
6489 receiver, effect, control);
6490 Node* next_table = effect =
6491 graph()->NewNode(simplified()->LoadField(
6492 AccessBuilder::ForOrderedHashMapOrSetNextTable()),
6493 table, effect, control);
6494 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), next_table);
6496 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
6499 done_loop = graph()->NewNode(common()->IfTrue(), control);
6500 done_eloop = effect;
6503 control = graph()->NewNode(common()->IfFalse(), control);
6506 Node* index = effect = graph()->NewNode(
6507 simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
6508 receiver, effect, control);
6509 Callable
const callable =
6510 Builtins::CallableFor(isolate(), Builtins::kOrderedHashTableHealIndex);
6511 auto call_descriptor = Linkage::GetStubCallDescriptor(
6512 graph()->zone(), callable.descriptor(),
6513 callable.descriptor().GetStackParameterCount(),
6514 CallDescriptor::kNoFlags, Operator::kEliminatable);
6516 graph()->NewNode(common()->Call(call_descriptor),
6517 jsgraph()->HeapConstant(callable.code()), table, index,
6518 jsgraph()->NoContextConstant(), effect);
6520 index = effect = graph()->NewNode(
6521 common()->TypeGuard(TypeCache::Get().kFixedArrayLengthType), index,
6525 effect = graph()->NewNode(
6526 simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorIndex()),
6527 receiver, index, effect, control);
6528 effect = graph()->NewNode(
6529 simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorTable()),
6530 receiver, next_table, effect, control);
6533 loop->ReplaceInput(1, control);
6534 eloop->ReplaceInput(1, effect);
6536 control = done_loop;
6537 effect = done_eloop;
6541 Node* index = effect = graph()->NewNode(
6542 simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
6543 receiver, effect, control);
6544 Node* table = effect = graph()->NewNode(
6545 simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
6546 receiver, effect, control);
6550 Node* iterator_result = effect = graph()->NewNode(
6551 javascript()->CreateIterResultObject(), jsgraph()->UndefinedConstant(),
6552 jsgraph()->TrueConstant(), context, effect);
6559 Node* number_of_buckets = effect = graph()->NewNode(
6560 simplified()->LoadField(
6561 AccessBuilder::ForOrderedHashMapOrSetNumberOfBuckets()),
6562 table, effect, control);
6563 Node* number_of_elements = effect = graph()->NewNode(
6564 simplified()->LoadField(
6565 AccessBuilder::ForOrderedHashMapOrSetNumberOfElements()),
6566 table, effect, control);
6567 Node* number_of_deleted_elements = effect = graph()->NewNode(
6568 simplified()->LoadField(
6569 AccessBuilder::ForOrderedHashMapOrSetNumberOfDeletedElements()),
6570 table, effect, control);
6571 Node* used_capacity =
6572 graph()->NewNode(simplified()->NumberAdd(), number_of_elements,
6573 number_of_deleted_elements);
6576 Node* loop = graph()->NewNode(common()->Loop(2), control, control);
6578 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
6579 Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
6580 NodeProperties::MergeControlToEnd(graph(), common(), terminate);
6581 Node* iloop = graph()->NewNode(
6582 common()->Phi(MachineRepresentation::kTagged, 2), index, index, loop);
6584 Node* index = effect = graph()->NewNode(
6585 common()->TypeGuard(TypeCache::Get().kFixedArrayLengthType), iloop,
6588 Node* check0 = graph()->NewNode(simplified()->NumberLessThan(), index,
6591 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, loop);
6593 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
6594 Node* efalse0 = effect;
6597 efalse0 = graph()->NewNode(
6598 simplified()->StoreField(
6599 AccessBuilder::ForJSCollectionIteratorTable()),
6600 receiver, jsgraph()->HeapConstant(empty_collection), efalse0,
6603 controls[0] = if_false0;
6604 effects[0] = efalse0;
6607 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
6608 Node* etrue0 = effect;
6611 STATIC_ASSERT(OrderedHashMap::kHashTableStartIndex ==
6612 OrderedHashSet::kHashTableStartIndex);
6613 Node* entry_start_position = graph()->NewNode(
6614 simplified()->NumberAdd(),
6616 simplified()->NumberAdd(),
6617 graph()->NewNode(simplified()->NumberMultiply(), index,
6618 jsgraph()->Constant(entry_size)),
6620 jsgraph()->Constant(OrderedHashMap::kHashTableStartIndex));
6621 Node* entry_key = etrue0 = graph()->NewNode(
6622 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
6623 table, entry_start_position, etrue0, if_true0);
6626 index = graph()->NewNode(simplified()->NumberAdd(), index,
6627 jsgraph()->OneConstant());
6630 graph()->NewNode(simplified()->ReferenceEqual(), entry_key,
6631 jsgraph()->TheHoleConstant());
6632 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
6637 Node* control = graph()->NewNode(common()->IfFalse(), branch1);
6638 Node* effect = etrue0;
6639 Node* value = effect =
6640 graph()->NewNode(common()->TypeGuard(Type::NonInternal()),
6641 entry_key, effect, control);
6642 Node* done = jsgraph()->FalseConstant();
6645 effect = graph()->NewNode(
6646 simplified()->StoreField(
6647 AccessBuilder::ForJSCollectionIteratorIndex()),
6648 receiver, index, effect, control);
6651 switch (receiver_instance_type) {
6652 case JS_MAP_KEY_ITERATOR_TYPE:
6653 case JS_SET_VALUE_ITERATOR_TYPE:
6656 case JS_SET_KEY_VALUE_ITERATOR_TYPE:
6658 graph()->NewNode(javascript()->CreateKeyValueArray(), value,
6659 value, context, effect);
6662 case JS_MAP_VALUE_ITERATOR_TYPE:
6663 value = effect = graph()->NewNode(
6664 simplified()->LoadElement(
6665 AccessBuilder::ForFixedArrayElement()),
6668 simplified()->NumberAdd(), entry_start_position,
6669 jsgraph()->Constant(OrderedHashMap::kValueOffset)),
6673 case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
6674 value = effect = graph()->NewNode(
6675 simplified()->LoadElement(
6676 AccessBuilder::ForFixedArrayElement()),
6679 simplified()->NumberAdd(), entry_start_position,
6680 jsgraph()->Constant(OrderedHashMap::kValueOffset)),
6683 graph()->NewNode(javascript()->CreateKeyValueArray(),
6684 entry_key, value, context, effect);
6694 graph()->NewNode(simplified()->StoreField(
6695 AccessBuilder::ForJSIteratorResultValue()),
6696 iterator_result, value, effect, control);
6698 graph()->NewNode(simplified()->StoreField(
6699 AccessBuilder::ForJSIteratorResultDone()),
6700 iterator_result, done, effect, control);
6702 controls[1] = control;
6703 effects[1] = effect;
6707 loop->ReplaceInput(1, graph()->NewNode(common()->IfTrue(), branch1));
6708 eloop->ReplaceInput(1, etrue0);
6709 iloop->ReplaceInput(1, index);
6713 control = effects[2] = graph()->NewNode(common()->Merge(2), 2, controls);
6714 effect = graph()->NewNode(common()->EffectPhi(2), 3, effects);
6718 ReplaceWithValue(node, iterator_result, effect, control);
6719 return Replace(iterator_result);
6722 Reduction JSCallReducer::ReduceArrayBufferIsView(Node* node) {
6723 Node* value = node->op()->ValueInputCount() >= 3
6724 ? NodeProperties::GetValueInput(node, 2)
6725 : jsgraph()->UndefinedConstant();
6726 RelaxEffectsAndControls(node);
6727 node->ReplaceInput(0, value);
6728 node->TrimInputCount(1);
6729 NodeProperties::ChangeOp(node, simplified()->ObjectIsArrayBufferView());
6730 return Changed(node);
6733 Reduction JSCallReducer::ReduceArrayBufferViewAccessor(
6734 Node* node, InstanceType instance_type, FieldAccess
const& access) {
6735 Node* receiver = NodeProperties::GetValueInput(node, 1);
6736 Node* effect = NodeProperties::GetEffectInput(node);
6737 Node* control = NodeProperties::GetControlInput(node);
6739 if (NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
6742 Node* value = effect = graph()->NewNode(simplified()->LoadField(access),
6743 receiver, effect, control);
6746 if (isolate()->IsArrayBufferNeuteringIntact()) {
6749 dependencies()->DependOnProtector(PropertyCellRef(
6750 broker(), factory()->array_buffer_neutering_protector()));
6753 Node* buffer = effect = graph()->NewNode(
6754 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
6755 receiver, effect, control);
6756 Node* buffer_bit_field = effect = graph()->NewNode(
6757 simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
6758 buffer, effect, control);
6759 Node* check = graph()->NewNode(
6760 simplified()->NumberEqual(),
6762 simplified()->NumberBitwiseAnd(), buffer_bit_field,
6763 jsgraph()->Constant(JSArrayBuffer::WasNeuteredBit::kMask)),
6764 jsgraph()->ZeroConstant());
6771 value = graph()->NewNode(
6772 common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
6773 check, value, jsgraph()->ZeroConstant());
6776 ReplaceWithValue(node, value, effect, control);
6777 return Replace(value);
6783 uint32_t ExternalArrayElementSize(
const ExternalArrayType element_type) {
6784 switch (element_type) {
6785 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \ 6786 case kExternal##Type##Array: \ 6787 DCHECK_LE(sizeof(ctype), 8); \ 6788 return sizeof(ctype); 6789 TYPED_ARRAYS(TYPED_ARRAY_CASE)
6792 #undef TYPED_ARRAY_CASE 6797 Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access,
6798 ExternalArrayType element_type) {
6799 size_t const element_size = ExternalArrayElementSize(element_type);
6800 CallParameters
const& p = CallParametersOf(node->op());
6801 Node* effect = NodeProperties::GetEffectInput(node);
6802 Node* control = NodeProperties::GetControlInput(node);
6803 Node* receiver = NodeProperties::GetValueInput(node, 1);
6804 Node* offset = node->op()->ValueInputCount() > 2
6805 ? NodeProperties::GetValueInput(node, 2)
6806 : jsgraph()->ZeroConstant();
6807 Node* value = (access == DataViewAccess::kGet)
6809 : (node->op()->ValueInputCount() > 3
6810 ? NodeProperties::GetValueInput(node, 3)
6811 : jsgraph()->ZeroConstant());
6812 Node* is_little_endian = (access == DataViewAccess::kGet)
6813 ? (node->op()->ValueInputCount() > 3
6814 ? NodeProperties::GetValueInput(node, 3)
6815 : jsgraph()->FalseConstant())
6816 : (node->op()->ValueInputCount() > 4
6817 ? NodeProperties::GetValueInput(node, 4)
6818 : jsgraph()->FalseConstant());
6820 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
6825 if (NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
6826 JS_DATA_VIEW_TYPE)) {
6830 HeapObjectMatcher m(receiver);
6834 JSDataViewRef dataview = m.Ref(broker()).AsJSDataView();
6835 if (dataview.byte_length() < element_size)
return NoChange();
6839 jsgraph()->Constant(dataview.byte_length() - (element_size - 1));
6841 graph()->NewNode(simplified()->CheckBounds(p.feedback()), offset,
6842 byte_length, effect, control);
6845 byte_offset = jsgraph()->Constant(dataview.byte_offset());
6848 Node* byte_length = effect =
6849 graph()->NewNode(simplified()->LoadField(
6850 AccessBuilder::ForJSArrayBufferViewByteLength()),
6851 receiver, effect, control);
6853 if (element_size > 1) {
6860 byte_length = graph()->NewNode(
6861 simplified()->NumberMax(), jsgraph()->ZeroConstant(),
6862 graph()->NewNode(simplified()->NumberSubtract(), byte_length,
6863 jsgraph()->Constant(element_size - 1)));
6868 graph()->NewNode(simplified()->CheckBounds(p.feedback()), offset,
6869 byte_length, effect, control);
6872 byte_offset = effect =
6873 graph()->NewNode(simplified()->LoadField(
6874 AccessBuilder::ForJSArrayBufferViewByteOffset()),
6875 receiver, effect, control);
6880 graph()->NewNode(simplified()->ToBoolean(), is_little_endian);
6883 if (access == DataViewAccess::kSet) {
6884 value = effect = graph()->NewNode(
6885 simplified()->SpeculativeToNumber(
6886 NumberOperationHint::kNumberOrOddball, p.feedback()),
6887 value, effect, control);
6891 Node* buffer = effect = graph()->NewNode(
6892 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
6893 receiver, effect, control);
6895 if (isolate()->IsArrayBufferNeuteringIntact()) {
6898 dependencies()->DependOnProtector(PropertyCellRef(
6899 broker(), factory()->array_buffer_neutering_protector()));
6902 Node* buffer_bit_field = effect = graph()->NewNode(
6903 simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
6904 buffer, effect, control);
6905 Node* check = graph()->NewNode(
6906 simplified()->NumberEqual(),
6908 simplified()->NumberBitwiseAnd(), buffer_bit_field,
6909 jsgraph()->Constant(JSArrayBuffer::WasNeuteredBit::kMask)),
6910 jsgraph()->ZeroConstant());
6911 effect = graph()->NewNode(
6912 simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasNeutered,
6914 check, effect, control);
6918 Node* backing_store = effect = graph()->NewNode(
6919 simplified()->LoadField(AccessBuilder::ForJSArrayBufferBackingStore()),
6920 buffer, effect, control);
6923 case DataViewAccess::kGet:
6926 graph()->NewNode(simplified()->LoadDataViewElement(element_type),
6927 buffer, backing_store, byte_offset, offset,
6928 is_little_endian, effect, control);
6930 case DataViewAccess::kSet:
6933 graph()->NewNode(simplified()->StoreDataViewElement(element_type),
6934 buffer, backing_store, byte_offset, offset, value,
6935 is_little_endian, effect, control);
6936 value = jsgraph()->UndefinedConstant();
6941 ReplaceWithValue(node, value, effect, control);
6942 return Changed(value);
6949 Reduction JSCallReducer::ReduceGlobalIsFinite(Node* node) {
6950 CallParameters
const& p = CallParametersOf(node->op());
6951 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
6954 if (node->op()->ValueInputCount() < 3) {
6955 Node* value = jsgraph()->FalseConstant();
6956 ReplaceWithValue(node, value);
6957 return Replace(value);
6960 Node* effect = NodeProperties::GetEffectInput(node);
6961 Node* control = NodeProperties::GetControlInput(node);
6962 Node* input = NodeProperties::GetValueInput(node, 2);
6965 graph()->NewNode(simplified()->SpeculativeToNumber(
6966 NumberOperationHint::kNumberOrOddball, p.feedback()),
6967 input, effect, control);
6968 Node* value = graph()->NewNode(simplified()->NumberIsFinite(), input);
6969 ReplaceWithValue(node, value, effect);
6970 return Replace(value);
6974 Reduction JSCallReducer::ReduceGlobalIsNaN(Node* node) {
6975 CallParameters
const& p = CallParametersOf(node->op());
6976 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
6979 if (node->op()->ValueInputCount() < 3) {
6980 Node* value = jsgraph()->TrueConstant();
6981 ReplaceWithValue(node, value);
6982 return Replace(value);
6985 Node* effect = NodeProperties::GetEffectInput(node);
6986 Node* control = NodeProperties::GetControlInput(node);
6987 Node* input = NodeProperties::GetValueInput(node, 2);
6990 graph()->NewNode(simplified()->SpeculativeToNumber(
6991 NumberOperationHint::kNumberOrOddball, p.feedback()),
6992 input, effect, control);
6993 Node* value = graph()->NewNode(simplified()->NumberIsNaN(), input);
6994 ReplaceWithValue(node, value, effect);
6995 return Replace(value);
6999 Reduction JSCallReducer::ReduceDatePrototypeGetTime(Node* node) {
7000 Node* receiver = NodeProperties::GetValueInput(node, 1);
7001 Node* effect = NodeProperties::GetEffectInput(node);
7002 Node* control = NodeProperties::GetControlInput(node);
7003 if (NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
7005 Node* value = effect = graph()->NewNode(
7006 simplified()->LoadField(AccessBuilder::ForJSDateValue()), receiver,
7008 ReplaceWithValue(node, value, effect, control);
7009 return Replace(value);
7015 Reduction JSCallReducer::ReduceDateNow(Node* node) {
7016 Node* effect = NodeProperties::GetEffectInput(node);
7017 Node* control = NodeProperties::GetControlInput(node);
7018 Node* value = effect =
7019 graph()->NewNode(simplified()->DateNow(), effect, control);
7020 ReplaceWithValue(node, value, effect, control);
7021 return Replace(value);
7025 Reduction JSCallReducer::ReduceNumberParseInt(Node* node) {
7027 if (node->op()->ValueInputCount() < 3) {
7028 Node* value = jsgraph()->NaNConstant();
7029 ReplaceWithValue(node, value);
7030 return Replace(value);
7033 int arg_count = node->op()->ValueInputCount();
7034 Node* effect = NodeProperties::GetEffectInput(node);
7035 Node* control = NodeProperties::GetControlInput(node);
7036 Node* context = NodeProperties::GetContextInput(node);
7037 Node* frame_state = NodeProperties::GetFrameStateInput(node);
7038 Node*
object = NodeProperties::GetValueInput(node, 2);
7039 Node* radix = arg_count >= 4 ? NodeProperties::GetValueInput(node, 3)
7040 : jsgraph()->UndefinedConstant();
7041 node->ReplaceInput(0,
object);
7042 node->ReplaceInput(1, radix);
7043 node->ReplaceInput(2, context);
7044 node->ReplaceInput(3, frame_state);
7045 node->ReplaceInput(4, effect);
7046 node->ReplaceInput(5, control);
7047 node->TrimInputCount(6);
7048 NodeProperties::ChangeOp(node, javascript()->ParseInt());
7049 return Changed(node);
7052 Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
7053 if (FLAG_force_slow_path)
return NoChange();
7054 if (node->op()->ValueInputCount() < 3)
return NoChange();
7055 CallParameters
const& p = CallParametersOf(node->op());
7056 if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
7060 Node* effect = NodeProperties::GetEffectInput(node);
7061 Node* control = NodeProperties::GetControlInput(node);
7062 Node* regexp = NodeProperties::GetValueInput(node, 1);
7065 ZoneHandleSet<Map> regexp_maps;
7066 NodeProperties::InferReceiverMapsResult result =
7067 NodeProperties::InferReceiverMaps(broker(), regexp, effect, ®exp_maps);
7069 bool need_map_check =
false;
7071 case NodeProperties::kNoReceiverMaps:
7073 case NodeProperties::kUnreliableReceiverMaps:
7074 need_map_check =
true;
7076 case NodeProperties::kReliableReceiverMaps:
7080 for (
auto map : regexp_maps) {
7081 MapRef receiver_map(broker(), map);
7082 if (receiver_map.instance_type() != JS_REGEXP_TYPE)
return NoChange();
7086 PropertyAccessInfo ai_exec;
7087 AccessInfoFactory access_info_factory(
7088 broker(), dependencies(), native_context().
object(), graph()->zone());
7089 if (!access_info_factory.ComputePropertyAccessInfo(
7090 MapHandles(regexp_maps.begin(), regexp_maps.end()),
7091 factory()->exec_string(), AccessMode::kLoad, &ai_exec)) {
7095 if (ai_exec.IsDataConstant()) {
7096 if (!ai_exec.constant().is_identical_to(
7097 isolate()->regexp_exec_function())) {
7100 }
else if (ai_exec.IsDataConstantField()) {
7101 Handle<JSObject> holder;
7103 if (!ai_exec.holder().ToHandle(&holder))
return NoChange();
7106 Handle<Object> constant = JSObject::FastPropertyAt(
7107 holder, Representation::Tagged(), ai_exec.field_index());
7108 if (!constant.is_identical_to(isolate()->regexp_exec_function())) {
7113 dependencies()->DependOnStablePrototypeChains(
7114 broker(), ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
7117 Handle<Object> exec_on_proto;
7118 Handle<Map> holder_map(holder->map(), isolate());
7119 Handle<DescriptorArray> descriptors(holder_map->instance_descriptors(),
7121 int descriptor_index =
7122 descriptors->Search(*(factory()->exec_string()), *holder_map);
7123 CHECK_NE(descriptor_index, DescriptorArray::kNotFound);
7125 dependencies()->DependOnFieldType(MapRef(broker(), holder_map),
7131 PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
7134 Handle<JSObject> holder;
7135 if (ai_exec.holder().ToHandle(&holder)) {
7136 dependencies()->DependOnStablePrototypeChains(
7137 broker(), ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
7140 if (need_map_check) {
7142 graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
7143 regexp_maps, p.feedback()),
7144 regexp, effect, control);
7147 Node* context = NodeProperties::GetContextInput(node);
7148 Node* frame_state = NodeProperties::GetFrameStateInput(node);
7149 Node* search = NodeProperties::GetValueInput(node, 2);
7150 Node* search_string = effect = graph()->NewNode(
7151 simplified()->CheckString(p.feedback()), search, effect, control);
7153 Node* lastIndex = effect = graph()->NewNode(
7154 simplified()->LoadField(AccessBuilder::ForJSRegExpLastIndex()), regexp,
7157 Node* lastIndexSmi = effect = graph()->NewNode(
7158 simplified()->CheckSmi(p.feedback()), lastIndex, effect, control);
7160 Node* is_positive = graph()->NewNode(simplified()->NumberLessThanOrEqual(),
7161 jsgraph()->ZeroConstant(), lastIndexSmi);
7163 effect = graph()->NewNode(
7164 simplified()->CheckIf(DeoptimizeReason::kNotASmi, p.feedback()),
7165 is_positive, effect, control);
7167 node->ReplaceInput(0, regexp);
7168 node->ReplaceInput(1, search_string);
7169 node->ReplaceInput(2, context);
7170 node->ReplaceInput(3, frame_state);
7171 node->ReplaceInput(4, effect);
7172 node->ReplaceInput(5, control);
7173 node->TrimInputCount(6);
7174 NodeProperties::ChangeOp(node, javascript()->RegExpTest());
7175 return Changed(node);
7179 Reduction JSCallReducer::ReduceNumberConstructor(Node* node) {
7180 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
7181 CallParameters
const& p = CallParametersOf(node->op());
7182 Node* target = NodeProperties::GetValueInput(node, 0);
7183 Node* receiver = NodeProperties::GetValueInput(node, 1);
7184 Node* value = p.arity() < 3 ? jsgraph()->ZeroConstant()
7185 : NodeProperties::GetValueInput(node, 2);
7186 Node* context = NodeProperties::GetContextInput(node);
7187 Node* frame_state = NodeProperties::GetFrameStateInput(node);
7190 SharedFunctionInfoRef shared_info =
7191 native_context().number_function().shared();
7192 Node* stack_parameters[] = {receiver};
7193 int stack_parameter_count = arraysize(stack_parameters);
7194 Node* continuation_frame_state =
7195 CreateJavaScriptBuiltinContinuationFrameState(
7196 jsgraph(), shared_info,
7197 Builtins::kGenericConstructorLazyDeoptContinuation, target, context,
7198 stack_parameters, stack_parameter_count, frame_state,
7199 ContinuationFrameStateMode::LAZY);
7202 NodeProperties::ReplaceValueInputs(node, value);
7203 NodeProperties::ChangeOp(node, javascript()->ToNumberConvertBigInt());
7204 NodeProperties::ReplaceFrameStateInput(node, continuation_frame_state);
7205 return Changed(node);
7208 Graph* JSCallReducer::graph()
const {
return jsgraph()->graph(); }
7210 Isolate* JSCallReducer::isolate()
const {
return jsgraph()->isolate(); }
7212 Factory* JSCallReducer::factory()
const {
return isolate()->factory(); }
7214 CommonOperatorBuilder* JSCallReducer::common()
const {
7215 return jsgraph()->common();
7218 JSOperatorBuilder* JSCallReducer::javascript()
const {
7219 return jsgraph()->javascript();
7222 SimplifiedOperatorBuilder* JSCallReducer::simplified()
const {
7223 return jsgraph()->simplified();