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