1/*
2 * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "DFGFixupPhase.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "ArrayPrototype.h"
32#include "DFGGraph.h"
33#include "DFGInsertionSet.h"
34#include "DFGPhase.h"
35#include "DFGPredictionPropagationPhase.h"
36#include "DFGVariableAccessDataDump.h"
37#include "JSCInlines.h"
38#include "TypeLocation.h"
39
40namespace JSC { namespace DFG {
41
42class FixupPhase : public Phase {
43public:
44 FixupPhase(Graph& graph)
45 : Phase(graph, "fixup")
46 , m_insertionSet(graph)
47 {
48 }
49
50 bool run()
51 {
52 ASSERT(m_graph.m_fixpointState == BeforeFixpoint);
53 ASSERT(m_graph.m_form == ThreadedCPS);
54
55 m_profitabilityChanged = false;
56 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
57 fixupBlock(m_graph.block(blockIndex));
58
59 while (m_profitabilityChanged) {
60 m_profitabilityChanged = false;
61
62 for (unsigned i = m_graph.m_argumentPositions.size(); i--;)
63 m_graph.m_argumentPositions[i].mergeArgumentUnboxingAwareness();
64
65 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
66 fixupGetAndSetLocalsInBlock(m_graph.block(blockIndex));
67 }
68
69 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
70 fixupChecksInBlock(m_graph.block(blockIndex));
71
72 m_graph.m_planStage = PlanStage::AfterFixup;
73
74 return true;
75 }
76
77private:
78
79 void fixupArithDivInt32(Node* node, Edge& leftChild, Edge& rightChild)
80 {
81 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) {
82 fixIntOrBooleanEdge(leftChild);
83 fixIntOrBooleanEdge(rightChild);
84 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
85 node->setArithMode(Arith::Unchecked);
86 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
87 node->setArithMode(Arith::CheckOverflow);
88 else
89 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
90 return;
91 }
92
93 // This will cause conversion nodes to be inserted later.
94 fixDoubleOrBooleanEdge(leftChild);
95 fixDoubleOrBooleanEdge(rightChild);
96
97 // We don't need to do ref'ing on the children because we're stealing them from
98 // the original division.
99 Node* newDivision = m_insertionSet.insertNode(m_indexInBlock, SpecBytecodeDouble, *node);
100 newDivision->setResult(NodeResultDouble);
101
102 node->setOp(DoubleAsInt32);
103 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
104 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
105 node->setArithMode(Arith::CheckOverflow);
106 else
107 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
108
109 }
110
111 void fixupArithPow(Node* node)
112 {
113 if (node->child2()->shouldSpeculateInt32OrBooleanForArithmetic()) {
114 fixDoubleOrBooleanEdge(node->child1());
115 fixIntOrBooleanEdge(node->child2());
116 return;
117 }
118
119 fixDoubleOrBooleanEdge(node->child1());
120 fixDoubleOrBooleanEdge(node->child2());
121 }
122
123 void fixupArithDiv(Node* node, Edge& leftChild, Edge& rightChild)
124 {
125 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
126 fixupArithDivInt32(node, leftChild, rightChild);
127 return;
128 }
129
130 fixDoubleOrBooleanEdge(leftChild);
131 fixDoubleOrBooleanEdge(rightChild);
132 node->setResult(NodeResultDouble);
133 }
134
135 void fixupArithMul(Node* node, Edge& leftChild, Edge& rightChild)
136 {
137 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
138 fixIntOrBooleanEdge(leftChild);
139 fixIntOrBooleanEdge(rightChild);
140 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
141 node->setArithMode(Arith::Unchecked);
142 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) || leftChild.node() == rightChild.node())
143 node->setArithMode(Arith::CheckOverflow);
144 else
145 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
146 return;
147 }
148 if (m_graph.binaryArithShouldSpeculateInt52(node, FixupPass)) {
149 fixEdge<Int52RepUse>(leftChild);
150 fixEdge<Int52RepUse>(rightChild);
151 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) || leftChild.node() == rightChild.node())
152 node->setArithMode(Arith::CheckOverflow);
153 else
154 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
155 node->setResult(NodeResultInt52);
156 return;
157 }
158
159 fixDoubleOrBooleanEdge(leftChild);
160 fixDoubleOrBooleanEdge(rightChild);
161 node->setResult(NodeResultDouble);
162 }
163
164 void fixupBlock(BasicBlock* block)
165 {
166 if (!block)
167 return;
168 ASSERT(block->isReachable);
169 m_block = block;
170 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
171 m_currentNode = block->at(m_indexInBlock);
172 fixupNode(m_currentNode);
173 }
174 m_insertionSet.execute(block);
175 }
176
177 void fixupNode(Node* node)
178 {
179 NodeType op = node->op();
180
181 switch (op) {
182 case SetLocal: {
183 // This gets handled by fixupGetAndSetLocalsInBlock().
184 return;
185 }
186
187 case ValueSub: {
188 Edge& child1 = node->child1();
189 Edge& child2 = node->child2();
190
191 if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
192 fixEdge<BigIntUse>(child1);
193 fixEdge<BigIntUse>(child2);
194 break;
195 }
196
197 if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
198 fixEdge<UntypedUse>(child1);
199 fixEdge<UntypedUse>(child2);
200 break;
201 }
202
203 if (attemptToMakeIntegerAdd(node)) {
204 // FIXME: Clear ArithSub's NodeMustGenerate when ArithMode is unchecked
205 // https://bugs.webkit.org/show_bug.cgi?id=190607
206 node->setOp(ArithSub);
207 break;
208 }
209
210 fixDoubleOrBooleanEdge(node->child1());
211 fixDoubleOrBooleanEdge(node->child2());
212 node->setOp(ArithSub);
213 node->setResult(NodeResultDouble);
214
215 break;
216 }
217
218 case ValueBitXor:
219 case ValueBitOr:
220 case ValueBitAnd: {
221 if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
222 fixEdge<BigIntUse>(node->child1());
223 fixEdge<BigIntUse>(node->child2());
224 break;
225 }
226
227 if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())) {
228 fixEdge<UntypedUse>(node->child1());
229 fixEdge<UntypedUse>(node->child2());
230 break;
231 }
232
233 // In such case, we need to fallback to ArithBitOp
234 switch (op) {
235 case ValueBitXor:
236 node->setOp(ArithBitXor);
237 break;
238 case ValueBitOr:
239 node->setOp(ArithBitOr);
240 break;
241 case ValueBitAnd:
242 node->setOp(ArithBitAnd);
243 break;
244 default:
245 DFG_CRASH(m_graph, node, "Unexpected node during ValueBit operation fixup");
246 break;
247 }
248
249 node->clearFlags(NodeMustGenerate);
250 node->setResult(NodeResultInt32);
251 fixIntConvertingEdge(node->child1());
252 fixIntConvertingEdge(node->child2());
253 break;
254 }
255
256 case ValueBitNot: {
257 Edge& operandEdge = node->child1();
258
259 if (operandEdge.node()->shouldSpeculateBigInt()) {
260 node->clearFlags(NodeMustGenerate);
261 fixEdge<BigIntUse>(operandEdge);
262 } else if (operandEdge.node()->shouldSpeculateUntypedForBitOps())
263 fixEdge<UntypedUse>(operandEdge);
264 else {
265 node->setOp(ArithBitNot);
266 node->setResult(NodeResultInt32);
267 node->clearFlags(NodeMustGenerate);
268 fixIntConvertingEdge(operandEdge);
269 }
270 break;
271 }
272
273 case ArithBitNot: {
274 Edge& operandEdge = node->child1();
275
276 fixIntConvertingEdge(operandEdge);
277 break;
278 }
279
280 case ArithBitXor:
281 case ArithBitOr:
282 case ArithBitAnd: {
283 fixIntConvertingEdge(node->child1());
284 fixIntConvertingEdge(node->child2());
285 break;
286 }
287
288 case BitRShift:
289 case BitLShift:
290 case BitURShift: {
291 if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())) {
292 fixEdge<UntypedUse>(node->child1());
293 fixEdge<UntypedUse>(node->child2());
294 break;
295 }
296 fixIntConvertingEdge(node->child1());
297 fixIntConvertingEdge(node->child2());
298 break;
299 }
300
301 case ArithIMul: {
302 fixIntConvertingEdge(node->child1());
303 fixIntConvertingEdge(node->child2());
304 node->setOp(ArithMul);
305 node->setArithMode(Arith::Unchecked);
306 node->child1().setUseKind(Int32Use);
307 node->child2().setUseKind(Int32Use);
308 break;
309 }
310
311 case ArithClz32: {
312 if (node->child1()->shouldSpeculateNotCell()) {
313 fixIntConvertingEdge(node->child1());
314 node->clearFlags(NodeMustGenerate);
315 } else
316 fixEdge<UntypedUse>(node->child1());
317 break;
318 }
319
320 case UInt32ToNumber: {
321 fixIntConvertingEdge(node->child1());
322 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
323 node->convertToIdentity();
324 else if (node->canSpeculateInt32(FixupPass))
325 node->setArithMode(Arith::CheckOverflow);
326 else {
327 node->setArithMode(Arith::DoOverflow);
328 node->setResult(enableInt52() ? NodeResultInt52 : NodeResultDouble);
329 }
330 break;
331 }
332
333 case ValueNegate: {
334 if (node->child1()->shouldSpeculateInt32OrBoolean() && node->canSpeculateInt32(FixupPass)) {
335 node->setOp(ArithNegate);
336 fixIntOrBooleanEdge(node->child1());
337 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
338 node->setArithMode(Arith::Unchecked);
339 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
340 node->setArithMode(Arith::CheckOverflow);
341 else
342 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
343 node->setResult(NodeResultInt32);
344 node->clearFlags(NodeMustGenerate);
345 break;
346 }
347
348 if (m_graph.unaryArithShouldSpeculateInt52(node, FixupPass)) {
349 node->setOp(ArithNegate);
350 fixEdge<Int52RepUse>(node->child1());
351 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
352 node->setArithMode(Arith::CheckOverflow);
353 else
354 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
355 node->setResult(NodeResultInt52);
356 node->clearFlags(NodeMustGenerate);
357 break;
358 }
359 if (node->child1()->shouldSpeculateNotCell()) {
360 node->setOp(ArithNegate);
361 fixDoubleOrBooleanEdge(node->child1());
362 node->setResult(NodeResultDouble);
363 node->clearFlags(NodeMustGenerate);
364 } else {
365 fixEdge<UntypedUse>(node->child1());
366 node->setResult(NodeResultJS);
367 }
368 break;
369 }
370
371 case ValueAdd: {
372 if (attemptToMakeIntegerAdd(node)) {
373 node->setOp(ArithAdd);
374 break;
375 }
376 if (Node::shouldSpeculateNumberOrBooleanExpectingDefined(node->child1().node(), node->child2().node())) {
377 fixDoubleOrBooleanEdge(node->child1());
378 fixDoubleOrBooleanEdge(node->child2());
379 node->setOp(ArithAdd);
380 node->setResult(NodeResultDouble);
381 break;
382 }
383
384 if (attemptToMakeFastStringAdd(node))
385 break;
386
387 Edge& child1 = node->child1();
388 Edge& child2 = node->child2();
389 if (child1->shouldSpeculateString() || child2->shouldSpeculateString()) {
390 if (child1->shouldSpeculateInt32() || child2->shouldSpeculateInt32()) {
391 auto convertString = [&](Node* node, Edge& edge) {
392 if (edge->shouldSpeculateInt32())
393 convertStringAddUse<Int32Use>(node, edge);
394 else {
395 ASSERT(edge->shouldSpeculateString());
396 convertStringAddUse<StringUse>(node, edge);
397 }
398 };
399 convertString(node, child1);
400 convertString(node, child2);
401 convertToMakeRope(node);
402 break;
403 }
404 }
405
406 if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
407 fixEdge<BigIntUse>(child1);
408 fixEdge<BigIntUse>(child2);
409 } else {
410 fixEdge<UntypedUse>(child1);
411 fixEdge<UntypedUse>(child2);
412 }
413
414 node->setResult(NodeResultJS);
415 break;
416 }
417
418 case StrCat: {
419 if (attemptToMakeFastStringAdd(node))
420 break;
421
422 // FIXME: Remove empty string arguments and possibly turn this into a ToString operation. That
423 // would require a form of ToString that takes a KnownPrimitiveUse. This is necessary because
424 // the implementation of StrCat doesn't dynamically optimize for empty strings.
425 // https://bugs.webkit.org/show_bug.cgi?id=148540
426 m_graph.doToChildren(
427 node,
428 [&] (Edge& edge) {
429 fixEdge<KnownPrimitiveUse>(edge);
430 // StrCat automatically coerces the values into strings before concatenating them.
431 // The ECMA spec says that we're not allowed to automatically coerce a Symbol into
432 // a string. If a Symbol is encountered, a TypeError will be thrown. As a result,
433 // our runtime functions for this slow path expect that they will never be passed
434 // Symbols.
435 m_insertionSet.insertNode(
436 m_indexInBlock, SpecNone, Check, node->origin,
437 Edge(edge.node(), NotSymbolUse));
438 });
439 break;
440 }
441
442 case MakeRope: {
443 fixupMakeRope(node);
444 break;
445 }
446
447 case ArithAdd:
448 case ArithSub: {
449 // FIXME: Clear ArithSub's NodeMustGenerate when ArithMode is unchecked
450 // https://bugs.webkit.org/show_bug.cgi?id=190607
451 if (attemptToMakeIntegerAdd(node))
452 break;
453 fixDoubleOrBooleanEdge(node->child1());
454 fixDoubleOrBooleanEdge(node->child2());
455 node->setResult(NodeResultDouble);
456 break;
457 }
458
459 case ArithNegate: {
460 if (node->child1()->shouldSpeculateInt32OrBoolean() && node->canSpeculateInt32(FixupPass)) {
461 fixIntOrBooleanEdge(node->child1());
462 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
463 node->setArithMode(Arith::Unchecked);
464 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
465 node->setArithMode(Arith::CheckOverflow);
466 else
467 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
468 node->setResult(NodeResultInt32);
469 node->clearFlags(NodeMustGenerate);
470 break;
471 }
472 if (m_graph.unaryArithShouldSpeculateInt52(node, FixupPass)) {
473 fixEdge<Int52RepUse>(node->child1());
474 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
475 node->setArithMode(Arith::CheckOverflow);
476 else
477 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
478 node->setResult(NodeResultInt52);
479 node->clearFlags(NodeMustGenerate);
480 break;
481 }
482
483 fixDoubleOrBooleanEdge(node->child1());
484 node->setResult(NodeResultDouble);
485 node->clearFlags(NodeMustGenerate);
486 break;
487 }
488
489 case ValueMul: {
490 Edge& leftChild = node->child1();
491 Edge& rightChild = node->child2();
492
493 if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) {
494 fixEdge<BigIntUse>(node->child1());
495 fixEdge<BigIntUse>(node->child2());
496 node->clearFlags(NodeMustGenerate);
497 break;
498 }
499
500 // There are cases where we can have BigInt + Int32 operands reaching ValueMul.
501 // Imagine the scenario where ValueMul was never executed, but we can predict types
502 // reaching the node:
503 //
504 // 63: GetLocal(Check:Untyped:@72, JS|MustGen, NonBoolInt32, ...) predicting NonBoolInt32
505 // 64: GetLocal(Check:Untyped:@71, JS|MustGen, BigInt, ...) predicting BigInt
506 // 65: ValueMul(Check:Untyped:@63, Check:Untyped:@64, BigInt|BoolInt32|NonBoolInt32, ...)
507 //
508 // In such scenario, we need to emit ValueMul(Untyped, Untyped), so the runtime can throw
509 // an exception whenever it gets excuted.
510 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) {
511 fixEdge<UntypedUse>(leftChild);
512 fixEdge<UntypedUse>(rightChild);
513 break;
514 }
515
516 // At this point, all other possible specializations are only handled by ArithMul.
517 node->setOp(ArithMul);
518 node->setResult(NodeResultNumber);
519 fixupArithMul(node, leftChild, rightChild);
520 break;
521 }
522
523 case ArithMul: {
524 Edge& leftChild = node->child1();
525 Edge& rightChild = node->child2();
526
527 fixupArithMul(node, leftChild, rightChild);
528 break;
529 }
530
531 case ValueMod:
532 case ValueDiv: {
533 Edge& leftChild = node->child1();
534 Edge& rightChild = node->child2();
535
536 if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) {
537 fixEdge<BigIntUse>(leftChild);
538 fixEdge<BigIntUse>(rightChild);
539 node->clearFlags(NodeMustGenerate);
540 break;
541 }
542
543 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) {
544 fixEdge<UntypedUse>(leftChild);
545 fixEdge<UntypedUse>(rightChild);
546 break;
547 }
548
549 if (op == ValueDiv)
550 node->setOp(ArithDiv);
551 else
552 node->setOp(ArithMod);
553
554 node->setResult(NodeResultNumber);
555 fixupArithDiv(node, leftChild, rightChild);
556 break;
557
558 }
559
560 case ArithDiv:
561 case ArithMod: {
562 Edge& leftChild = node->child1();
563 Edge& rightChild = node->child2();
564
565 fixupArithDiv(node, leftChild, rightChild);
566 break;
567 }
568
569 case ArithMin:
570 case ArithMax: {
571 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
572 fixIntOrBooleanEdge(node->child1());
573 fixIntOrBooleanEdge(node->child2());
574 break;
575 }
576 fixDoubleOrBooleanEdge(node->child1());
577 fixDoubleOrBooleanEdge(node->child2());
578 node->setResult(NodeResultDouble);
579 break;
580 }
581
582 case ArithAbs: {
583 if (node->child1()->shouldSpeculateInt32OrBoolean()
584 && node->canSpeculateInt32(FixupPass)) {
585 fixIntOrBooleanEdge(node->child1());
586 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
587 node->setArithMode(Arith::Unchecked);
588 else
589 node->setArithMode(Arith::CheckOverflow);
590 node->clearFlags(NodeMustGenerate);
591 node->setResult(NodeResultInt32);
592 break;
593 }
594
595 if (node->child1()->shouldSpeculateNotCell()) {
596 fixDoubleOrBooleanEdge(node->child1());
597 node->clearFlags(NodeMustGenerate);
598 } else
599 fixEdge<UntypedUse>(node->child1());
600 node->setResult(NodeResultDouble);
601 break;
602 }
603
604 case ValuePow: {
605 if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
606 fixEdge<BigIntUse>(node->child1());
607 fixEdge<BigIntUse>(node->child2());
608 node->clearFlags(NodeMustGenerate);
609 break;
610 }
611
612 if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
613 fixEdge<UntypedUse>(node->child1());
614 fixEdge<UntypedUse>(node->child2());
615 break;
616 }
617
618 node->setOp(ArithPow);
619 node->clearFlags(NodeMustGenerate);
620 node->setResult(NodeResultDouble);
621
622 fixupArithPow(node);
623 break;
624 }
625
626 case ArithPow: {
627 fixupArithPow(node);
628 break;
629 }
630
631 case ArithRandom: {
632 node->setResult(NodeResultDouble);
633 break;
634 }
635
636 case ArithRound:
637 case ArithFloor:
638 case ArithCeil:
639 case ArithTrunc: {
640 if (node->child1()->shouldSpeculateInt32OrBoolean() && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
641 fixIntOrBooleanEdge(node->child1());
642 insertCheck<Int32Use>(node->child1().node());
643 node->convertToIdentity();
644 break;
645 }
646 if (node->child1()->shouldSpeculateNotCell()) {
647 fixDoubleOrBooleanEdge(node->child1());
648
649 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
650 node->setResult(NodeResultInt32);
651 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
652 node->setArithRoundingMode(Arith::RoundingMode::Int32);
653 else
654 node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
655 } else {
656 node->setResult(NodeResultDouble);
657 node->setArithRoundingMode(Arith::RoundingMode::Double);
658 }
659 node->clearFlags(NodeMustGenerate);
660 } else
661 fixEdge<UntypedUse>(node->child1());
662 break;
663 }
664
665 case ArithFRound:
666 case ArithSqrt:
667 case ArithUnary: {
668 Edge& child1 = node->child1();
669 if (child1->shouldSpeculateNotCell()) {
670 fixDoubleOrBooleanEdge(child1);
671 node->clearFlags(NodeMustGenerate);
672 } else
673 fixEdge<UntypedUse>(child1);
674 break;
675 }
676
677 case LogicalNot: {
678 if (node->child1()->shouldSpeculateBoolean()) {
679 if (node->child1()->result() == NodeResultBoolean) {
680 // This is necessary in case we have a bytecode instruction implemented by:
681 //
682 // a: CompareEq(...)
683 // b: LogicalNot(@a)
684 //
685 // In that case, CompareEq might have a side-effect. Then, we need to make
686 // sure that we know that Branch does not exit.
687 fixEdge<KnownBooleanUse>(node->child1());
688 } else
689 fixEdge<BooleanUse>(node->child1());
690 } else if (node->child1()->shouldSpeculateObjectOrOther())
691 fixEdge<ObjectOrOtherUse>(node->child1());
692 else if (node->child1()->shouldSpeculateInt32OrBoolean())
693 fixIntOrBooleanEdge(node->child1());
694 else if (node->child1()->shouldSpeculateNumber())
695 fixEdge<DoubleRepUse>(node->child1());
696 else if (node->child1()->shouldSpeculateString())
697 fixEdge<StringUse>(node->child1());
698 else if (node->child1()->shouldSpeculateStringOrOther())
699 fixEdge<StringOrOtherUse>(node->child1());
700 else {
701 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
702 if (masqueradesAsUndefinedWatchpoint->isStillValid())
703 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
704 }
705 break;
706 }
707
708 case CompareEq:
709 case CompareLess:
710 case CompareLessEq:
711 case CompareGreater:
712 case CompareGreaterEq: {
713 if (node->op() == CompareEq
714 && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
715 fixEdge<BooleanUse>(node->child1());
716 fixEdge<BooleanUse>(node->child2());
717 node->clearFlags(NodeMustGenerate);
718 break;
719 }
720 if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
721 fixIntOrBooleanEdge(node->child1());
722 fixIntOrBooleanEdge(node->child2());
723 node->clearFlags(NodeMustGenerate);
724 break;
725 }
726 if (Node::shouldSpeculateInt52(node->child1().node(), node->child2().node())) {
727 fixEdge<Int52RepUse>(node->child1());
728 fixEdge<Int52RepUse>(node->child2());
729 node->clearFlags(NodeMustGenerate);
730 break;
731 }
732 if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
733 fixDoubleOrBooleanEdge(node->child1());
734 fixDoubleOrBooleanEdge(node->child2());
735 }
736 if (node->op() != CompareEq
737 && node->child1()->shouldSpeculateNotCell()
738 && node->child2()->shouldSpeculateNotCell()) {
739 if (node->child1()->shouldSpeculateNumberOrBoolean())
740 fixDoubleOrBooleanEdge(node->child1());
741 else
742 fixEdge<DoubleRepUse>(node->child1());
743 if (node->child2()->shouldSpeculateNumberOrBoolean())
744 fixDoubleOrBooleanEdge(node->child2());
745 else
746 fixEdge<DoubleRepUse>(node->child2());
747 node->clearFlags(NodeMustGenerate);
748 break;
749 }
750 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
751 fixEdge<StringIdentUse>(node->child1());
752 fixEdge<StringIdentUse>(node->child2());
753 node->clearFlags(NodeMustGenerate);
754 break;
755 }
756 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
757 fixEdge<StringUse>(node->child1());
758 fixEdge<StringUse>(node->child2());
759 node->clearFlags(NodeMustGenerate);
760 break;
761 }
762
763 if (node->op() != CompareEq)
764 break;
765 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
766 fixEdge<SymbolUse>(node->child1());
767 fixEdge<SymbolUse>(node->child2());
768 node->clearFlags(NodeMustGenerate);
769 break;
770 }
771 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
772 fixEdge<ObjectUse>(node->child1());
773 fixEdge<ObjectUse>(node->child2());
774 node->clearFlags(NodeMustGenerate);
775 break;
776 }
777
778 // If either child can be proved to be Null or Undefined, comparing them is greatly simplified.
779 bool oneArgumentIsUsedAsSpecOther = false;
780 if (node->child1()->isUndefinedOrNullConstant()) {
781 fixEdge<KnownOtherUse>(node->child1());
782 oneArgumentIsUsedAsSpecOther = true;
783 } else if (node->child1()->shouldSpeculateOther()) {
784 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
785 Edge(node->child1().node(), OtherUse));
786 fixEdge<KnownOtherUse>(node->child1());
787 oneArgumentIsUsedAsSpecOther = true;
788 }
789 if (node->child2()->isUndefinedOrNullConstant()) {
790 fixEdge<KnownOtherUse>(node->child2());
791 oneArgumentIsUsedAsSpecOther = true;
792 } else if (node->child2()->shouldSpeculateOther()) {
793 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
794 Edge(node->child2().node(), OtherUse));
795 fixEdge<KnownOtherUse>(node->child2());
796 oneArgumentIsUsedAsSpecOther = true;
797 }
798 if (oneArgumentIsUsedAsSpecOther) {
799 node->clearFlags(NodeMustGenerate);
800 break;
801 }
802
803 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
804 fixEdge<ObjectUse>(node->child1());
805 fixEdge<ObjectOrOtherUse>(node->child2());
806 node->clearFlags(NodeMustGenerate);
807 break;
808 }
809 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
810 fixEdge<ObjectOrOtherUse>(node->child1());
811 fixEdge<ObjectUse>(node->child2());
812 node->clearFlags(NodeMustGenerate);
813 break;
814 }
815
816 break;
817 }
818
819 case CompareStrictEq:
820 case SameValue: {
821 fixupCompareStrictEqAndSameValue(node);
822 break;
823 }
824
825 case StringFromCharCode:
826 if (node->child1()->shouldSpeculateInt32()) {
827 fixEdge<Int32Use>(node->child1());
828 node->clearFlags(NodeMustGenerate);
829 } else
830 fixEdge<UntypedUse>(node->child1());
831 break;
832
833 case StringCharAt:
834 case StringCharCodeAt: {
835 // Currently we have no good way of refining these.
836 ASSERT(node->arrayMode() == ArrayMode(Array::String, Array::Read));
837 blessArrayOperation(node->child1(), node->child2(), node->child3());
838 fixEdge<KnownStringUse>(node->child1());
839 fixEdge<Int32Use>(node->child2());
840 break;
841 }
842
843 case GetByVal: {
844 if (!node->prediction()) {
845 m_insertionSet.insertNode(
846 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
847 }
848
849 node->setArrayMode(
850 node->arrayMode().refine(
851 m_graph, node,
852 m_graph.varArgChild(node, 0)->prediction(),
853 m_graph.varArgChild(node, 1)->prediction(),
854 SpecNone));
855
856 blessArrayOperation(m_graph.varArgChild(node, 0), m_graph.varArgChild(node, 1), m_graph.varArgChild(node, 2));
857
858 ArrayMode arrayMode = node->arrayMode();
859 switch (arrayMode.type()) {
860 case Array::Contiguous:
861 case Array::Double:
862 if (arrayMode.isJSArrayWithOriginalStructure() && arrayMode.speculation() == Array::InBounds) {
863 // Check if SaneChain will work on a per-type basis. Note that:
864 //
865 // 1) We don't want double arrays to sometimes return undefined, since
866 // that would require a change to the return type and it would pessimise
867 // things a lot. So, we'd only want to do that if we actually had
868 // evidence that we could read from a hole. That's pretty annoying.
869 // Likely the best way to handle that case is with an equivalent of
870 // SaneChain for OutOfBounds. For now we just detect when Undefined and
871 // NaN are indistinguishable according to backwards propagation, and just
872 // use SaneChain in that case. This happens to catch a lot of cases.
873 //
874 // 2) We don't want int32 array loads to have to do a hole check just to
875 // coerce to Undefined, since that would mean twice the checks.
876 //
877 // This has two implications. First, we have to do more checks than we'd
878 // like. It's unfortunate that we have to do the hole check. Second,
879 // some accesses that hit a hole will now need to take the full-blown
880 // out-of-bounds slow path. We can fix that with:
881 // https://bugs.webkit.org/show_bug.cgi?id=144668
882
883 bool canDoSaneChain = false;
884 switch (arrayMode.type()) {
885 case Array::Contiguous:
886 // This is happens to be entirely natural. We already would have
887 // returned any JSValue, and now we'll return Undefined. We still do
888 // the check but it doesn't require taking any kind of slow path.
889 canDoSaneChain = true;
890 break;
891
892 case Array::Double:
893 if (!(node->flags() & NodeBytecodeUsesAsOther)) {
894 // Holes look like NaN already, so if the user doesn't care
895 // about the difference between Undefined and NaN then we can
896 // do this.
897 canDoSaneChain = true;
898 }
899 break;
900
901 default:
902 break;
903 }
904
905 if (canDoSaneChain) {
906 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
907 Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(vm());
908 Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(vm());
909 if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
910 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
911 && globalObject->arrayPrototypeChainIsSane()) {
912 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
913 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
914 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
915 }
916 }
917 }
918 break;
919
920 case Array::String:
921 if ((node->prediction() & ~SpecString)
922 || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
923 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
924 break;
925
926 default:
927 break;
928 }
929
930 arrayMode = node->arrayMode();
931 switch (arrayMode.type()) {
932 case Array::SelectUsingPredictions:
933 case Array::Unprofiled:
934 RELEASE_ASSERT_NOT_REACHED();
935 break;
936 case Array::Generic:
937 if (m_graph.varArgChild(node, 0)->shouldSpeculateObject()) {
938 if (m_graph.varArgChild(node, 1)->shouldSpeculateString()) {
939 fixEdge<ObjectUse>(m_graph.varArgChild(node, 0));
940 fixEdge<StringUse>(m_graph.varArgChild(node, 1));
941 break;
942 }
943
944 if (m_graph.varArgChild(node, 1)->shouldSpeculateSymbol()) {
945 fixEdge<ObjectUse>(m_graph.varArgChild(node, 0));
946 fixEdge<SymbolUse>(m_graph.varArgChild(node, 1));
947 break;
948 }
949 }
950#if USE(JSVALUE32_64)
951 fixEdge<CellUse>(m_graph.varArgChild(node, 0)); // Speculating cell due to register pressure on 32-bit.
952#endif
953 break;
954 case Array::ForceExit:
955 break;
956 case Array::String:
957 fixEdge<KnownStringUse>(m_graph.varArgChild(node, 0));
958 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
959 break;
960 default:
961 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
962 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
963 break;
964 }
965
966 switch (arrayMode.type()) {
967 case Array::Double:
968 if (!arrayMode.isOutOfBounds())
969 node->setResult(NodeResultDouble);
970 break;
971
972 case Array::Float32Array:
973 case Array::Float64Array:
974 node->setResult(NodeResultDouble);
975 break;
976
977 case Array::Uint32Array:
978 if (node->shouldSpeculateInt32())
979 break;
980 if (node->shouldSpeculateInt52())
981 node->setResult(NodeResultInt52);
982 else
983 node->setResult(NodeResultDouble);
984 break;
985
986 default:
987 break;
988 }
989
990 break;
991 }
992
993 case PutByValDirect:
994 case PutByVal:
995 case PutByValAlias: {
996 Edge& child1 = m_graph.varArgChild(node, 0);
997 Edge& child2 = m_graph.varArgChild(node, 1);
998 Edge& child3 = m_graph.varArgChild(node, 2);
999
1000 node->setArrayMode(
1001 node->arrayMode().refine(
1002 m_graph, node,
1003 child1->prediction(),
1004 child2->prediction(),
1005 child3->prediction()));
1006
1007 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
1008
1009 switch (node->arrayMode().modeForPut().type()) {
1010 case Array::SelectUsingPredictions:
1011 case Array::SelectUsingArguments:
1012 case Array::Unprofiled:
1013 case Array::Undecided:
1014 RELEASE_ASSERT_NOT_REACHED();
1015 break;
1016 case Array::ForceExit:
1017 case Array::Generic:
1018 if (child1->shouldSpeculateCell()) {
1019 if (child2->shouldSpeculateString()) {
1020 fixEdge<CellUse>(child1);
1021 fixEdge<StringUse>(child2);
1022 break;
1023 }
1024
1025 if (child2->shouldSpeculateSymbol()) {
1026 fixEdge<CellUse>(child1);
1027 fixEdge<SymbolUse>(child2);
1028 break;
1029 }
1030 }
1031#if USE(JSVALUE32_64)
1032 // Due to register pressure on 32-bit, we speculate cell and
1033 // ignore the base-is-not-cell case entirely by letting the
1034 // baseline JIT handle it.
1035 fixEdge<CellUse>(child1);
1036#endif
1037 break;
1038 case Array::Int32:
1039 fixEdge<KnownCellUse>(child1);
1040 fixEdge<Int32Use>(child2);
1041 fixEdge<Int32Use>(child3);
1042 break;
1043 case Array::Double:
1044 fixEdge<KnownCellUse>(child1);
1045 fixEdge<Int32Use>(child2);
1046 fixEdge<DoubleRepRealUse>(child3);
1047 break;
1048 case Array::Int8Array:
1049 case Array::Int16Array:
1050 case Array::Int32Array:
1051 case Array::Uint8Array:
1052 case Array::Uint8ClampedArray:
1053 case Array::Uint16Array:
1054 case Array::Uint32Array:
1055 fixEdge<KnownCellUse>(child1);
1056 fixEdge<Int32Use>(child2);
1057 if (child3->shouldSpeculateInt32())
1058 fixIntOrBooleanEdge(child3);
1059 else if (child3->shouldSpeculateInt52())
1060 fixEdge<Int52RepUse>(child3);
1061 else
1062 fixDoubleOrBooleanEdge(child3);
1063 break;
1064 case Array::Float32Array:
1065 case Array::Float64Array:
1066 fixEdge<KnownCellUse>(child1);
1067 fixEdge<Int32Use>(child2);
1068 fixDoubleOrBooleanEdge(child3);
1069 break;
1070 case Array::Contiguous:
1071 case Array::ArrayStorage:
1072 case Array::SlowPutArrayStorage:
1073 fixEdge<KnownCellUse>(child1);
1074 fixEdge<Int32Use>(child2);
1075 speculateForBarrier(child3);
1076 break;
1077 default:
1078 fixEdge<KnownCellUse>(child1);
1079 fixEdge<Int32Use>(child2);
1080 break;
1081 }
1082 break;
1083 }
1084
1085 case AtomicsAdd:
1086 case AtomicsAnd:
1087 case AtomicsCompareExchange:
1088 case AtomicsExchange:
1089 case AtomicsLoad:
1090 case AtomicsOr:
1091 case AtomicsStore:
1092 case AtomicsSub:
1093 case AtomicsXor: {
1094 Edge& base = m_graph.child(node, 0);
1095 Edge& index = m_graph.child(node, 1);
1096
1097 bool badNews = false;
1098 for (unsigned i = numExtraAtomicsArgs(node->op()); i--;) {
1099 Edge& child = m_graph.child(node, 2 + i);
1100 // NOTE: DFG is not smart enough to handle double->int conversions in atomics. So, we
1101 // just call the function when that happens. But the FTL is totally cool with those
1102 // conversions.
1103 if (!child->shouldSpeculateInt32()
1104 && !child->shouldSpeculateInt52()
1105 && !(child->shouldSpeculateNumberOrBoolean() && m_graph.m_plan.isFTL()))
1106 badNews = true;
1107 }
1108
1109 if (badNews) {
1110 node->setArrayMode(ArrayMode(Array::Generic, node->arrayMode().action()));
1111 break;
1112 }
1113
1114 node->setArrayMode(
1115 node->arrayMode().refine(
1116 m_graph, node, base->prediction(), index->prediction()));
1117
1118 if (node->arrayMode().type() == Array::Generic)
1119 break;
1120
1121 for (unsigned i = numExtraAtomicsArgs(node->op()); i--;) {
1122 Edge& child = m_graph.child(node, 2 + i);
1123 if (child->shouldSpeculateInt32())
1124 fixIntOrBooleanEdge(child);
1125 else if (child->shouldSpeculateInt52())
1126 fixEdge<Int52RepUse>(child);
1127 else {
1128 RELEASE_ASSERT(child->shouldSpeculateNumberOrBoolean() && m_graph.m_plan.isFTL());
1129 fixDoubleOrBooleanEdge(child);
1130 }
1131 }
1132
1133 blessArrayOperation(base, index, m_graph.child(node, 2 + numExtraAtomicsArgs(node->op())));
1134 fixEdge<CellUse>(base);
1135 fixEdge<Int32Use>(index);
1136
1137 if (node->arrayMode().type() == Array::Uint32Array) {
1138 // NOTE: This means basically always doing Int52.
1139 if (node->shouldSpeculateInt52())
1140 node->setResult(NodeResultInt52);
1141 else
1142 node->setResult(NodeResultDouble);
1143 }
1144 break;
1145 }
1146
1147 case AtomicsIsLockFree:
1148 if (node->child1()->shouldSpeculateInt32())
1149 fixIntOrBooleanEdge(node->child1());
1150 break;
1151
1152 case ArrayPush: {
1153 // May need to refine the array mode in case the value prediction contravenes
1154 // the array prediction. For example, we may have evidence showing that the
1155 // array is in Int32 mode, but the value we're storing is likely to be a double.
1156 // Then we should turn this into a conversion to Double array followed by the
1157 // push. On the other hand, we absolutely don't want to refine based on the
1158 // base prediction. If it has non-cell garbage in it, then we want that to be
1159 // ignored. That's because ArrayPush can't handle any array modes that aren't
1160 // array-related - so if refine() turned this into a "Generic" ArrayPush then
1161 // that would break things.
1162 Edge& storageEdge = m_graph.varArgChild(node, 0);
1163 Edge& arrayEdge = m_graph.varArgChild(node, 1);
1164 unsigned elementOffset = 2;
1165 unsigned elementCount = node->numChildren() - elementOffset;
1166 for (unsigned i = 0; i < elementCount; ++i) {
1167 Edge& element = m_graph.varArgChild(node, i + elementOffset);
1168 node->setArrayMode(
1169 node->arrayMode().refine(
1170 m_graph, node,
1171 arrayEdge->prediction() & SpecCell,
1172 SpecInt32Only,
1173 element->prediction()));
1174 }
1175 blessArrayOperation(arrayEdge, Edge(), storageEdge);
1176 fixEdge<KnownCellUse>(arrayEdge);
1177
1178 // Convert `array.push()` to GetArrayLength.
1179 if (!elementCount && node->arrayMode().supportsSelfLength()) {
1180 node->setOpAndDefaultFlags(GetArrayLength);
1181 node->child1() = arrayEdge;
1182 node->child2() = storageEdge;
1183 fixEdge<KnownCellUse>(node->child1());
1184 break;
1185 }
1186
1187 // We do not want to perform osr exit and retry for ArrayPush. We insert Check with appropriate type,
1188 // and ArrayPush uses the edge as known typed edge. Therefore, ArrayPush do not need to perform type checks.
1189 for (unsigned i = 0; i < elementCount; ++i) {
1190 Edge& element = m_graph.varArgChild(node, i + elementOffset);
1191 switch (node->arrayMode().type()) {
1192 case Array::Int32:
1193 fixEdge<Int32Use>(element);
1194 break;
1195 case Array::Double:
1196 fixEdge<DoubleRepRealUse>(element);
1197 break;
1198 case Array::Contiguous:
1199 case Array::ArrayStorage:
1200 speculateForBarrier(element);
1201 break;
1202 default:
1203 break;
1204 }
1205 }
1206 break;
1207 }
1208
1209 case ArrayPop: {
1210 blessArrayOperation(node->child1(), Edge(), node->child2());
1211 fixEdge<KnownCellUse>(node->child1());
1212 break;
1213 }
1214
1215 case ArraySlice: {
1216 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
1217 if (node->numChildren() >= 3) {
1218 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
1219 if (node->numChildren() == 4)
1220 fixEdge<Int32Use>(m_graph.varArgChild(node, 2));
1221 }
1222 break;
1223 }
1224
1225 case ArrayIndexOf:
1226 fixupArrayIndexOf(node);
1227 break;
1228
1229 case RegExpExec:
1230 case RegExpTest: {
1231 fixEdge<KnownCellUse>(node->child1());
1232
1233 if (node->child2()->shouldSpeculateRegExpObject()) {
1234 fixEdge<RegExpObjectUse>(node->child2());
1235
1236 if (node->child3()->shouldSpeculateString())
1237 fixEdge<StringUse>(node->child3());
1238 }
1239 break;
1240 }
1241
1242 case RegExpMatchFast: {
1243 fixEdge<KnownCellUse>(node->child1());
1244 fixEdge<RegExpObjectUse>(node->child2());
1245 fixEdge<StringUse>(node->child3());
1246 break;
1247 }
1248
1249 case StringReplace:
1250 case StringReplaceRegExp: {
1251 if (node->child2()->shouldSpeculateString()) {
1252 m_insertionSet.insertNode(
1253 m_indexInBlock, SpecNone, Check, node->origin,
1254 Edge(node->child2().node(), StringUse));
1255 fixEdge<StringUse>(node->child2());
1256 } else if (op == StringReplace) {
1257 if (node->child2()->shouldSpeculateRegExpObject())
1258 addStringReplacePrimordialChecks(node->child2().node());
1259 else
1260 m_insertionSet.insertNode(
1261 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
1262 }
1263
1264 if (node->child1()->shouldSpeculateString()
1265 && node->child2()->shouldSpeculateRegExpObject()
1266 && node->child3()->shouldSpeculateString()) {
1267
1268 fixEdge<StringUse>(node->child1());
1269 fixEdge<RegExpObjectUse>(node->child2());
1270 fixEdge<StringUse>(node->child3());
1271 break;
1272 }
1273 break;
1274 }
1275
1276 case Branch: {
1277 if (node->child1()->shouldSpeculateBoolean()) {
1278 if (node->child1()->result() == NodeResultBoolean) {
1279 // This is necessary in case we have a bytecode instruction implemented by:
1280 //
1281 // a: CompareEq(...)
1282 // b: Branch(@a)
1283 //
1284 // In that case, CompareEq might have a side-effect. Then, we need to make
1285 // sure that we know that Branch does not exit.
1286 fixEdge<KnownBooleanUse>(node->child1());
1287 } else
1288 fixEdge<BooleanUse>(node->child1());
1289 } else if (node->child1()->shouldSpeculateObjectOrOther())
1290 fixEdge<ObjectOrOtherUse>(node->child1());
1291 else if (node->child1()->shouldSpeculateInt32OrBoolean())
1292 fixIntOrBooleanEdge(node->child1());
1293 else if (node->child1()->shouldSpeculateNumber())
1294 fixEdge<DoubleRepUse>(node->child1());
1295 else if (node->child1()->shouldSpeculateString())
1296 fixEdge<StringUse>(node->child1());
1297 else if (node->child1()->shouldSpeculateStringOrOther())
1298 fixEdge<StringOrOtherUse>(node->child1());
1299 else {
1300 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
1301 if (masqueradesAsUndefinedWatchpoint->isStillValid())
1302 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
1303 }
1304 break;
1305 }
1306
1307 case Switch: {
1308 SwitchData* data = node->switchData();
1309 switch (data->kind) {
1310 case SwitchImm:
1311 if (node->child1()->shouldSpeculateInt32())
1312 fixEdge<Int32Use>(node->child1());
1313 break;
1314 case SwitchChar:
1315 if (node->child1()->shouldSpeculateString())
1316 fixEdge<StringUse>(node->child1());
1317 break;
1318 case SwitchString:
1319 if (node->child1()->shouldSpeculateStringIdent())
1320 fixEdge<StringIdentUse>(node->child1());
1321 else if (node->child1()->shouldSpeculateString())
1322 fixEdge<StringUse>(node->child1());
1323 break;
1324 case SwitchCell:
1325 if (node->child1()->shouldSpeculateCell())
1326 fixEdge<CellUse>(node->child1());
1327 // else it's fine for this to have UntypedUse; we will handle this by just making
1328 // non-cells take the default case.
1329 break;
1330 }
1331 break;
1332 }
1333
1334 case ToPrimitive: {
1335 fixupToPrimitive(node);
1336 break;
1337 }
1338
1339 case ToNumber: {
1340 fixupToNumber(node);
1341 break;
1342 }
1343
1344 case ToString:
1345 case CallStringConstructor: {
1346 fixupToStringOrCallStringConstructor(node);
1347 break;
1348 }
1349
1350 case NewStringObject: {
1351 fixEdge<KnownStringUse>(node->child1());
1352 break;
1353 }
1354
1355 case NewSymbol: {
1356 if (node->child1())
1357 fixEdge<KnownStringUse>(node->child1());
1358 break;
1359 }
1360
1361 case NewArrayWithSpread: {
1362 watchHavingABadTime(node);
1363
1364 BitVector* bitVector = node->bitVector();
1365 for (unsigned i = node->numChildren(); i--;) {
1366 if (bitVector->get(i))
1367 fixEdge<KnownCellUse>(m_graph.m_varArgChildren[node->firstChild() + i]);
1368 else
1369 fixEdge<UntypedUse>(m_graph.m_varArgChildren[node->firstChild() + i]);
1370 }
1371
1372 break;
1373 }
1374
1375 case Spread: {
1376 // Note: We care about performing the protocol on our child's global object, not necessarily ours.
1377
1378 watchHavingABadTime(node->child1().node());
1379
1380 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->child1()->origin.semantic);
1381 // When we go down the fast path, we don't consult the prototype chain, so we must prove
1382 // that it doesn't contain any indexed properties, and that any holes will result in
1383 // jsUndefined().
1384 Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(vm());
1385 Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(vm());
1386 if (node->child1()->shouldSpeculateArray()
1387 && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
1388 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
1389 && globalObject->arrayPrototypeChainIsSane()
1390 && m_graph.isWatchingArrayIteratorProtocolWatchpoint(node->child1().node())
1391 && m_graph.isWatchingHavingABadTimeWatchpoint(node->child1().node())) {
1392 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
1393 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
1394 fixEdge<ArrayUse>(node->child1());
1395 } else
1396 fixEdge<CellUse>(node->child1());
1397 break;
1398 }
1399
1400 case NewArray: {
1401 watchHavingABadTime(node);
1402
1403 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
1404 node->setIndexingType(
1405 leastUpperBoundOfIndexingTypeAndType(
1406 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
1407 }
1408 switch (node->indexingType()) {
1409 case ALL_BLANK_INDEXING_TYPES:
1410 CRASH();
1411 break;
1412 case ALL_UNDECIDED_INDEXING_TYPES:
1413 if (node->numChildren()) {
1414 // This will only happen if the children have no type predictions. We
1415 // would have already exited by now, but insert a forced exit just to
1416 // be safe.
1417 m_insertionSet.insertNode(
1418 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
1419 }
1420 break;
1421 case ALL_INT32_INDEXING_TYPES:
1422 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1423 fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1424 break;
1425 case ALL_DOUBLE_INDEXING_TYPES:
1426 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1427 fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1428 break;
1429 case ALL_CONTIGUOUS_INDEXING_TYPES:
1430 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
1431 break;
1432 default:
1433 CRASH();
1434 break;
1435 }
1436 break;
1437 }
1438
1439 case NewTypedArray: {
1440 watchHavingABadTime(node);
1441
1442 if (node->child1()->shouldSpeculateInt32()) {
1443 fixEdge<Int32Use>(node->child1());
1444 node->clearFlags(NodeMustGenerate);
1445 break;
1446 }
1447 break;
1448 }
1449
1450 case NewArrayWithSize: {
1451 watchHavingABadTime(node);
1452 fixEdge<Int32Use>(node->child1());
1453 break;
1454 }
1455
1456 case NewArrayBuffer: {
1457 watchHavingABadTime(node);
1458 break;
1459 }
1460
1461 case ToObject: {
1462 fixupToObject(node);
1463 break;
1464 }
1465
1466 case CallObjectConstructor: {
1467 fixupCallObjectConstructor(node);
1468 break;
1469 }
1470
1471 case ToThis: {
1472 fixupToThis(node);
1473 break;
1474 }
1475
1476 case PutStructure: {
1477 fixEdge<KnownCellUse>(node->child1());
1478 break;
1479 }
1480
1481 case GetClosureVar:
1482 case GetFromArguments: {
1483 fixEdge<KnownCellUse>(node->child1());
1484 break;
1485 }
1486
1487 case PutClosureVar:
1488 case PutToArguments: {
1489 fixEdge<KnownCellUse>(node->child1());
1490 speculateForBarrier(node->child2());
1491 break;
1492 }
1493
1494 case SkipScope:
1495 case GetScope:
1496 case GetGetter:
1497 case GetSetter:
1498 case GetGlobalObject: {
1499 fixEdge<KnownCellUse>(node->child1());
1500 break;
1501 }
1502
1503 case AllocatePropertyStorage:
1504 case ReallocatePropertyStorage: {
1505 fixEdge<KnownCellUse>(node->child1());
1506 break;
1507 }
1508
1509 case NukeStructureAndSetButterfly: {
1510 fixEdge<KnownCellUse>(node->child1());
1511 break;
1512 }
1513
1514 case TryGetById: {
1515 if (node->child1()->shouldSpeculateCell())
1516 fixEdge<CellUse>(node->child1());
1517 break;
1518 }
1519
1520 case GetByIdDirect:
1521 case GetByIdDirectFlush: {
1522 if (node->child1()->shouldSpeculateCell())
1523 fixEdge<CellUse>(node->child1());
1524 break;
1525 }
1526
1527 case GetById:
1528 case GetByIdFlush: {
1529 // FIXME: This should be done in the ByteCodeParser based on reading the
1530 // PolymorphicAccess, which will surely tell us that this is a AccessCase::ArrayLength.
1531 // https://bugs.webkit.org/show_bug.cgi?id=154990
1532 auto uid = m_graph.identifiers()[node->identifierNumber()];
1533 if (node->child1()->shouldSpeculateCellOrOther()
1534 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1535 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1536 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1537 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1538
1539 if (uid == vm().propertyNames->length.impl()) {
1540 attemptToMakeGetArrayLength(node);
1541 break;
1542 }
1543
1544 if (uid == vm().propertyNames->lastIndex.impl()
1545 && node->child1()->shouldSpeculateRegExpObject()) {
1546 node->setOp(GetRegExpObjectLastIndex);
1547 node->clearFlags(NodeMustGenerate);
1548 fixEdge<RegExpObjectUse>(node->child1());
1549 break;
1550 }
1551 }
1552
1553 if (node->child1()->shouldSpeculateNumber()) {
1554 if (uid == vm().propertyNames->toString.impl()) {
1555 if (m_graph.isWatchingNumberToStringWatchpoint(node)) {
1556 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1557 if (node->child1()->shouldSpeculateInt32()) {
1558 insertCheck<Int32Use>(node->child1().node());
1559 m_graph.convertToConstant(node, m_graph.freeze(globalObject->numberProtoToStringFunction()));
1560 break;
1561 }
1562
1563 if (node->child1()->shouldSpeculateInt52()) {
1564 insertCheck<Int52RepUse>(node->child1().node());
1565 m_graph.convertToConstant(node, m_graph.freeze(globalObject->numberProtoToStringFunction()));
1566 break;
1567 }
1568
1569 ASSERT(node->child1()->shouldSpeculateNumber());
1570 insertCheck<DoubleRepUse>(node->child1().node());
1571 m_graph.convertToConstant(node, m_graph.freeze(globalObject->numberProtoToStringFunction()));
1572 break;
1573 }
1574 }
1575 }
1576
1577 if (node->child1()->shouldSpeculateCell())
1578 fixEdge<CellUse>(node->child1());
1579 break;
1580 }
1581
1582 case GetByIdWithThis: {
1583 if (node->child1()->shouldSpeculateCell() && node->child2()->shouldSpeculateCell()) {
1584 fixEdge<CellUse>(node->child1());
1585 fixEdge<CellUse>(node->child2());
1586 }
1587 break;
1588 }
1589
1590 case PutById:
1591 case PutByIdFlush:
1592 case PutByIdDirect: {
1593 if (node->child1()->shouldSpeculateCellOrOther()
1594 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1595 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1596 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1597 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1598
1599 auto uid = m_graph.identifiers()[node->identifierNumber()];
1600
1601 if (uid == vm().propertyNames->lastIndex.impl()
1602 && node->child1()->shouldSpeculateRegExpObject()) {
1603 node->convertToSetRegExpObjectLastIndex();
1604 fixEdge<RegExpObjectUse>(node->child1());
1605 speculateForBarrier(node->child2());
1606 break;
1607 }
1608 }
1609
1610 fixEdge<CellUse>(node->child1());
1611 break;
1612 }
1613
1614 case PutGetterById:
1615 case PutSetterById: {
1616 fixEdge<KnownCellUse>(node->child1());
1617 fixEdge<KnownCellUse>(node->child2());
1618 break;
1619 }
1620
1621 case PutGetterSetterById: {
1622 fixEdge<KnownCellUse>(node->child1());
1623 break;
1624 }
1625
1626 case PutGetterByVal:
1627 case PutSetterByVal: {
1628 fixEdge<KnownCellUse>(node->child1());
1629 fixEdge<KnownCellUse>(node->child3());
1630 break;
1631 }
1632
1633 case GetExecutable: {
1634 fixEdge<FunctionUse>(node->child1());
1635 break;
1636 }
1637
1638 case OverridesHasInstance:
1639 case CheckStructure:
1640 case CheckCell:
1641 case CreateThis:
1642 case GetButterfly: {
1643 fixEdge<CellUse>(node->child1());
1644 break;
1645 }
1646
1647 case ObjectCreate: {
1648 if (node->child1()->shouldSpeculateObject()) {
1649 fixEdge<ObjectUse>(node->child1());
1650 node->clearFlags(NodeMustGenerate);
1651 break;
1652 }
1653 break;
1654 }
1655
1656 case ObjectKeys: {
1657 if (node->child1()->shouldSpeculateObject()) {
1658 watchHavingABadTime(node);
1659 fixEdge<ObjectUse>(node->child1());
1660 }
1661 break;
1662 }
1663
1664 case CheckStringIdent: {
1665 fixEdge<StringIdentUse>(node->child1());
1666 break;
1667 }
1668
1669 case Arrayify:
1670 case ArrayifyToStructure: {
1671 fixEdge<CellUse>(node->child1());
1672 if (node->child2())
1673 fixEdge<Int32Use>(node->child2());
1674 break;
1675 }
1676
1677 case GetByOffset:
1678 case GetGetterSetterByOffset: {
1679 if (!node->child1()->hasStorageResult())
1680 fixEdge<KnownCellUse>(node->child1());
1681 fixEdge<KnownCellUse>(node->child2());
1682 break;
1683 }
1684
1685 case MultiGetByOffset: {
1686 fixEdge<CellUse>(node->child1());
1687 break;
1688 }
1689
1690 case PutByOffset: {
1691 if (!node->child1()->hasStorageResult())
1692 fixEdge<KnownCellUse>(node->child1());
1693 fixEdge<KnownCellUse>(node->child2());
1694 speculateForBarrier(node->child3());
1695 break;
1696 }
1697
1698 case MultiPutByOffset: {
1699 fixEdge<CellUse>(node->child1());
1700 break;
1701 }
1702
1703 case MatchStructure: {
1704 // FIXME: Introduce a variant of MatchStructure that doesn't do a cell check.
1705 // https://bugs.webkit.org/show_bug.cgi?id=185784
1706 fixEdge<CellUse>(node->child1());
1707 break;
1708 }
1709
1710 case InstanceOf: {
1711 if (node->child1()->shouldSpeculateCell()
1712 && node->child2()->shouldSpeculateCell()
1713 && is64Bit()) {
1714 fixEdge<CellUse>(node->child1());
1715 fixEdge<CellUse>(node->child2());
1716 break;
1717 }
1718 break;
1719 }
1720
1721 case InstanceOfCustom:
1722 fixEdge<CellUse>(node->child2());
1723 break;
1724
1725 case InById: {
1726 fixEdge<CellUse>(node->child1());
1727 break;
1728 }
1729
1730 case InByVal: {
1731 if (node->child2()->shouldSpeculateInt32()) {
1732 convertToHasIndexedProperty(node);
1733 break;
1734 }
1735
1736 fixEdge<CellUse>(node->child1());
1737 break;
1738 }
1739
1740 case HasOwnProperty: {
1741 fixEdge<ObjectUse>(node->child1());
1742#if CPU(X86)
1743 // We don't have enough registers to do anything interesting on x86 and mips.
1744 fixEdge<UntypedUse>(node->child2());
1745#else
1746 if (node->child2()->shouldSpeculateString())
1747 fixEdge<StringUse>(node->child2());
1748 else if (node->child2()->shouldSpeculateSymbol())
1749 fixEdge<SymbolUse>(node->child2());
1750 else
1751 fixEdge<UntypedUse>(node->child2());
1752#endif
1753 break;
1754 }
1755
1756 case CheckVarargs:
1757 case Check: {
1758 m_graph.doToChildren(
1759 node,
1760 [&] (Edge& edge) {
1761 switch (edge.useKind()) {
1762 case NumberUse:
1763 if (edge->shouldSpeculateInt32ForArithmetic())
1764 edge.setUseKind(Int32Use);
1765 break;
1766 default:
1767 break;
1768 }
1769 observeUseKindOnEdge(edge);
1770 });
1771 break;
1772 }
1773
1774 case Phantom:
1775 // Phantoms are meaningless past Fixup. We recreate them on-demand in the backend.
1776 node->remove(m_graph);
1777 break;
1778
1779 case FiatInt52: {
1780 RELEASE_ASSERT(enableInt52());
1781 node->convertToIdentity();
1782 fixEdge<Int52RepUse>(node->child1());
1783 node->setResult(NodeResultInt52);
1784 break;
1785 }
1786
1787 case GetArrayLength: {
1788 fixEdge<KnownCellUse>(node->child1());
1789 break;
1790 }
1791
1792 case GetTypedArrayByteOffset: {
1793 fixEdge<KnownCellUse>(node->child1());
1794 break;
1795 }
1796
1797 case CompareBelow:
1798 case CompareBelowEq: {
1799 fixEdge<Int32Use>(node->child1());
1800 fixEdge<Int32Use>(node->child2());
1801 break;
1802 }
1803
1804 case GetPrototypeOf: {
1805 fixupGetPrototypeOf(node);
1806 break;
1807 }
1808
1809 case Phi:
1810 case Upsilon:
1811 case EntrySwitch:
1812 case GetIndexedPropertyStorage:
1813 case LastNodeType:
1814 case CheckTierUpInLoop:
1815 case CheckTierUpAtReturn:
1816 case CheckTierUpAndOSREnter:
1817 case CheckArray:
1818 case CheckInBounds:
1819 case ConstantStoragePointer:
1820 case DoubleAsInt32:
1821 case ValueToInt32:
1822 case DoubleRep:
1823 case ValueRep:
1824 case Int52Rep:
1825 case Int52Constant:
1826 case Identity: // This should have been cleaned up.
1827 case BooleanToNumber:
1828 case PhantomNewObject:
1829 case PhantomNewFunction:
1830 case PhantomNewGeneratorFunction:
1831 case PhantomNewAsyncGeneratorFunction:
1832 case PhantomNewAsyncFunction:
1833 case PhantomCreateActivation:
1834 case PhantomDirectArguments:
1835 case PhantomCreateRest:
1836 case PhantomSpread:
1837 case PhantomNewArrayWithSpread:
1838 case PhantomNewArrayBuffer:
1839 case PhantomClonedArguments:
1840 case PhantomNewRegexp:
1841 case GetMyArgumentByVal:
1842 case GetMyArgumentByValOutOfBounds:
1843 case GetVectorLength:
1844 case PutHint:
1845 case CheckStructureImmediate:
1846 case CheckStructureOrEmpty:
1847 case MaterializeNewObject:
1848 case MaterializeCreateActivation:
1849 case PutStack:
1850 case KillStack:
1851 case GetStack:
1852 case StoreBarrier:
1853 case FencedStoreBarrier:
1854 case GetRegExpObjectLastIndex:
1855 case SetRegExpObjectLastIndex:
1856 case RecordRegExpCachedResult:
1857 case RegExpExecNonGlobalOrSticky:
1858 case RegExpMatchFastGlobal:
1859 // These are just nodes that we don't currently expect to see during fixup.
1860 // If we ever wanted to insert them prior to fixup, then we just have to create
1861 // fixup rules for them.
1862 DFG_CRASH(m_graph, node, "Unexpected node during fixup");
1863 break;
1864
1865 case PutGlobalVariable: {
1866 fixEdge<CellUse>(node->child1());
1867 speculateForBarrier(node->child2());
1868 break;
1869 }
1870
1871 case IsObject:
1872 if (node->child1()->shouldSpeculateObject()) {
1873 m_insertionSet.insertNode(
1874 m_indexInBlock, SpecNone, Check, node->origin,
1875 Edge(node->child1().node(), ObjectUse));
1876 m_graph.convertToConstant(node, jsBoolean(true));
1877 observeUseKindOnNode<ObjectUse>(node);
1878 }
1879 break;
1880
1881 case IsCellWithType: {
1882 fixupIsCellWithType(node);
1883 break;
1884 }
1885
1886 case GetEnumerableLength: {
1887 fixEdge<CellUse>(node->child1());
1888 break;
1889 }
1890 case HasGenericProperty: {
1891 fixEdge<CellUse>(node->child2());
1892 break;
1893 }
1894 case HasStructureProperty: {
1895 fixEdge<StringUse>(node->child2());
1896 fixEdge<KnownCellUse>(node->child3());
1897 break;
1898 }
1899 case HasIndexedProperty: {
1900 node->setArrayMode(
1901 node->arrayMode().refine(
1902 m_graph, node,
1903 m_graph.varArgChild(node, 0)->prediction(),
1904 m_graph.varArgChild(node, 1)->prediction(),
1905 SpecNone));
1906
1907 blessArrayOperation(m_graph.varArgChild(node, 0), m_graph.varArgChild(node, 1), m_graph.varArgChild(node, 2));
1908 fixEdge<CellUse>(m_graph.varArgChild(node, 0));
1909 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
1910 break;
1911 }
1912 case GetDirectPname: {
1913 Edge& base = m_graph.varArgChild(node, 0);
1914 Edge& property = m_graph.varArgChild(node, 1);
1915 Edge& index = m_graph.varArgChild(node, 2);
1916 Edge& enumerator = m_graph.varArgChild(node, 3);
1917 fixEdge<CellUse>(base);
1918 fixEdge<KnownCellUse>(property);
1919 fixEdge<Int32Use>(index);
1920 fixEdge<KnownCellUse>(enumerator);
1921 break;
1922 }
1923 case GetPropertyEnumerator: {
1924 if (node->child1()->shouldSpeculateCell())
1925 fixEdge<CellUse>(node->child1());
1926 break;
1927 }
1928 case GetEnumeratorStructurePname: {
1929 fixEdge<KnownCellUse>(node->child1());
1930 fixEdge<Int32Use>(node->child2());
1931 break;
1932 }
1933 case GetEnumeratorGenericPname: {
1934 fixEdge<KnownCellUse>(node->child1());
1935 fixEdge<Int32Use>(node->child2());
1936 break;
1937 }
1938 case ToIndexString: {
1939 fixEdge<Int32Use>(node->child1());
1940 break;
1941 }
1942 case ProfileType: {
1943 // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet.
1944 // Because the instructionTypeSet is contained in globalTypeSet, if we produce a type check for
1945 // type T for the instructionTypeSet, the global type set must also have information for type T.
1946 // So if it the type check succeeds for type T in the instructionTypeSet, a type check for type T
1947 // in the globalTypeSet would've also succeeded.
1948 // (The other direction does not hold in general).
1949
1950 RefPtr<TypeSet> typeSet = node->typeLocation()->m_instructionTypeSet;
1951 RuntimeTypeMask seenTypes = typeSet->seenTypes();
1952 if (typeSet->doesTypeConformTo(TypeAnyInt)) {
1953 if (node->child1()->shouldSpeculateInt32()) {
1954 fixEdge<Int32Use>(node->child1());
1955 node->remove(m_graph);
1956 break;
1957 }
1958
1959 if (enableInt52()) {
1960 fixEdge<AnyIntUse>(node->child1());
1961 node->remove(m_graph);
1962 break;
1963 }
1964
1965 // Must not perform fixEdge<NumberUse> here since the type set only includes TypeAnyInt. Double values should be logged.
1966 }
1967
1968 if (typeSet->doesTypeConformTo(TypeNumber | TypeAnyInt)) {
1969 fixEdge<NumberUse>(node->child1());
1970 node->remove(m_graph);
1971 } else if (typeSet->doesTypeConformTo(TypeString)) {
1972 fixEdge<StringUse>(node->child1());
1973 node->remove(m_graph);
1974 } else if (typeSet->doesTypeConformTo(TypeBoolean)) {
1975 fixEdge<BooleanUse>(node->child1());
1976 node->remove(m_graph);
1977 } else if (typeSet->doesTypeConformTo(TypeUndefined | TypeNull) && (seenTypes & TypeUndefined) && (seenTypes & TypeNull)) {
1978 fixEdge<OtherUse>(node->child1());
1979 node->remove(m_graph);
1980 } else if (typeSet->doesTypeConformTo(TypeObject)) {
1981 StructureSet set;
1982 {
1983 ConcurrentJSLocker locker(typeSet->m_lock);
1984 set = typeSet->structureSet(locker);
1985 }
1986 if (!set.isEmpty()) {
1987 fixEdge<CellUse>(node->child1());
1988 node->convertToCheckStructureOrEmpty(m_graph.addStructureSet(set));
1989 }
1990 }
1991
1992 break;
1993 }
1994
1995 case CreateClonedArguments: {
1996 watchHavingABadTime(node);
1997 break;
1998 }
1999
2000 case CreateScopedArguments:
2001 case CreateActivation:
2002 case NewFunction:
2003 case NewGeneratorFunction:
2004 case NewAsyncGeneratorFunction:
2005 case NewAsyncFunction: {
2006 // Child 1 is always the current scope, which is guaranteed to be an object
2007 // FIXME: should be KnownObjectUse once that exists (https://bugs.webkit.org/show_bug.cgi?id=175689)
2008 fixEdge<KnownCellUse>(node->child1());
2009 break;
2010 }
2011
2012 case PushWithScope: {
2013 // Child 1 is always the current scope, which is guaranteed to be an object
2014 // FIXME: should be KnownObjectUse once that exists (https://bugs.webkit.org/show_bug.cgi?id=175689)
2015 fixEdge<KnownCellUse>(node->child1());
2016 if (node->child2()->shouldSpeculateObject())
2017 fixEdge<ObjectUse>(node->child2());
2018 break;
2019 }
2020
2021 case SetFunctionName: {
2022 // The first child is guaranteed to be a cell because op_set_function_name is only used
2023 // on a newly instantiated function object (the first child).
2024 fixEdge<KnownCellUse>(node->child1());
2025 fixEdge<UntypedUse>(node->child2());
2026 break;
2027 }
2028
2029 case CreateRest: {
2030 watchHavingABadTime(node);
2031 fixEdge<Int32Use>(node->child1());
2032 break;
2033 }
2034
2035 case ResolveScopeForHoistingFuncDeclInEval: {
2036 fixEdge<KnownCellUse>(node->child1());
2037 break;
2038 }
2039 case ResolveScope:
2040 case GetDynamicVar:
2041 case PutDynamicVar: {
2042 fixEdge<KnownCellUse>(node->child1());
2043 break;
2044 }
2045
2046 case LogShadowChickenPrologue: {
2047 fixEdge<KnownCellUse>(node->child1());
2048 break;
2049 }
2050 case LogShadowChickenTail: {
2051 fixEdge<UntypedUse>(node->child1());
2052 fixEdge<KnownCellUse>(node->child2());
2053 break;
2054 }
2055
2056 case GetMapBucket:
2057 if (node->child1().useKind() == MapObjectUse)
2058 fixEdge<MapObjectUse>(node->child1());
2059 else if (node->child1().useKind() == SetObjectUse)
2060 fixEdge<SetObjectUse>(node->child1());
2061 else
2062 RELEASE_ASSERT_NOT_REACHED();
2063
2064#if USE(JSVALUE64)
2065 if (node->child2()->shouldSpeculateBoolean())
2066 fixEdge<BooleanUse>(node->child2());
2067 else if (node->child2()->shouldSpeculateInt32())
2068 fixEdge<Int32Use>(node->child2());
2069 else if (node->child2()->shouldSpeculateSymbol())
2070 fixEdge<SymbolUse>(node->child2());
2071 else if (node->child2()->shouldSpeculateObject())
2072 fixEdge<ObjectUse>(node->child2());
2073 else if (node->child2()->shouldSpeculateString())
2074 fixEdge<StringUse>(node->child2());
2075 else if (node->child2()->shouldSpeculateCell())
2076 fixEdge<CellUse>(node->child2());
2077 else
2078 fixEdge<UntypedUse>(node->child2());
2079#else
2080 fixEdge<UntypedUse>(node->child2());
2081#endif // USE(JSVALUE64)
2082
2083 fixEdge<Int32Use>(node->child3());
2084 break;
2085
2086 case GetMapBucketHead:
2087 if (node->child1().useKind() == MapObjectUse)
2088 fixEdge<MapObjectUse>(node->child1());
2089 else if (node->child1().useKind() == SetObjectUse)
2090 fixEdge<SetObjectUse>(node->child1());
2091 else
2092 RELEASE_ASSERT_NOT_REACHED();
2093 break;
2094
2095 case GetMapBucketNext:
2096 case LoadKeyFromMapBucket:
2097 case LoadValueFromMapBucket:
2098 fixEdge<CellUse>(node->child1());
2099 break;
2100
2101 case MapHash: {
2102#if USE(JSVALUE64)
2103 if (node->child1()->shouldSpeculateBoolean()) {
2104 fixEdge<BooleanUse>(node->child1());
2105 break;
2106 }
2107
2108 if (node->child1()->shouldSpeculateInt32()) {
2109 fixEdge<Int32Use>(node->child1());
2110 break;
2111 }
2112
2113 if (node->child1()->shouldSpeculateSymbol()) {
2114 fixEdge<SymbolUse>(node->child1());
2115 break;
2116 }
2117
2118 if (node->child1()->shouldSpeculateObject()) {
2119 fixEdge<ObjectUse>(node->child1());
2120 break;
2121 }
2122
2123 if (node->child1()->shouldSpeculateString()) {
2124 fixEdge<StringUse>(node->child1());
2125 break;
2126 }
2127
2128 if (node->child1()->shouldSpeculateCell()) {
2129 fixEdge<CellUse>(node->child1());
2130 break;
2131 }
2132
2133 fixEdge<UntypedUse>(node->child1());
2134#else
2135 fixEdge<UntypedUse>(node->child1());
2136#endif // USE(JSVALUE64)
2137 break;
2138 }
2139
2140 case NormalizeMapKey: {
2141 fixupNormalizeMapKey(node);
2142 break;
2143 }
2144
2145 case WeakMapGet: {
2146 if (node->child1().useKind() == WeakMapObjectUse)
2147 fixEdge<WeakMapObjectUse>(node->child1());
2148 else if (node->child1().useKind() == WeakSetObjectUse)
2149 fixEdge<WeakSetObjectUse>(node->child1());
2150 else
2151 RELEASE_ASSERT_NOT_REACHED();
2152 fixEdge<ObjectUse>(node->child2());
2153 fixEdge<Int32Use>(node->child3());
2154 break;
2155 }
2156
2157 case SetAdd: {
2158 fixEdge<SetObjectUse>(node->child1());
2159 fixEdge<Int32Use>(node->child3());
2160 break;
2161 }
2162
2163 case MapSet: {
2164 fixEdge<MapObjectUse>(m_graph.varArgChild(node, 0));
2165 fixEdge<Int32Use>(m_graph.varArgChild(node, 3));
2166 break;
2167 }
2168
2169 case WeakSetAdd: {
2170 fixEdge<WeakSetObjectUse>(node->child1());
2171 fixEdge<ObjectUse>(node->child2());
2172 fixEdge<Int32Use>(node->child3());
2173 break;
2174 }
2175
2176 case WeakMapSet: {
2177 fixEdge<WeakMapObjectUse>(m_graph.varArgChild(node, 0));
2178 fixEdge<ObjectUse>(m_graph.varArgChild(node, 1));
2179 fixEdge<Int32Use>(m_graph.varArgChild(node, 3));
2180 break;
2181 }
2182
2183 case DefineDataProperty: {
2184 fixEdge<CellUse>(m_graph.varArgChild(node, 0));
2185 Edge& propertyEdge = m_graph.varArgChild(node, 1);
2186 if (propertyEdge->shouldSpeculateSymbol())
2187 fixEdge<SymbolUse>(propertyEdge);
2188 else if (propertyEdge->shouldSpeculateStringIdent())
2189 fixEdge<StringIdentUse>(propertyEdge);
2190 else if (propertyEdge->shouldSpeculateString())
2191 fixEdge<StringUse>(propertyEdge);
2192 else
2193 fixEdge<UntypedUse>(propertyEdge);
2194 fixEdge<UntypedUse>(m_graph.varArgChild(node, 2));
2195 fixEdge<Int32Use>(m_graph.varArgChild(node, 3));
2196 break;
2197 }
2198
2199 case StringValueOf: {
2200 fixupStringValueOf(node);
2201 break;
2202 }
2203
2204 case StringSlice: {
2205 fixEdge<StringUse>(node->child1());
2206 fixEdge<Int32Use>(node->child2());
2207 if (node->child3())
2208 fixEdge<Int32Use>(node->child3());
2209 break;
2210 }
2211
2212 case ToLowerCase: {
2213 // We currently only support StringUse since that will ensure that
2214 // ToLowerCase is a pure operation. If we decide to update this with
2215 // more types in the future, we need to ensure that the clobberize rules
2216 // are correct.
2217 fixEdge<StringUse>(node->child1());
2218 break;
2219 }
2220
2221 case NumberToStringWithRadix: {
2222 if (node->child1()->shouldSpeculateInt32())
2223 fixEdge<Int32Use>(node->child1());
2224 else if (node->child1()->shouldSpeculateInt52())
2225 fixEdge<Int52RepUse>(node->child1());
2226 else
2227 fixEdge<DoubleRepUse>(node->child1());
2228 fixEdge<Int32Use>(node->child2());
2229 break;
2230 }
2231
2232 case DefineAccessorProperty: {
2233 fixEdge<CellUse>(m_graph.varArgChild(node, 0));
2234 Edge& propertyEdge = m_graph.varArgChild(node, 1);
2235 if (propertyEdge->shouldSpeculateSymbol())
2236 fixEdge<SymbolUse>(propertyEdge);
2237 else if (propertyEdge->shouldSpeculateStringIdent())
2238 fixEdge<StringIdentUse>(propertyEdge);
2239 else if (propertyEdge->shouldSpeculateString())
2240 fixEdge<StringUse>(propertyEdge);
2241 else
2242 fixEdge<UntypedUse>(propertyEdge);
2243 fixEdge<CellUse>(m_graph.varArgChild(node, 2));
2244 fixEdge<CellUse>(m_graph.varArgChild(node, 3));
2245 fixEdge<Int32Use>(m_graph.varArgChild(node, 4));
2246 break;
2247 }
2248
2249 case CheckSubClass: {
2250 fixupCheckSubClass(node);
2251 break;
2252 }
2253
2254 case CallDOMGetter: {
2255 DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
2256 fixEdge<CellUse>(node->child1()); // DOM.
2257 if (snippet && snippet->requireGlobalObject)
2258 fixEdge<KnownCellUse>(node->child2()); // GlobalObject.
2259 break;
2260 }
2261
2262 case CallDOM: {
2263 fixupCallDOM(node);
2264 break;
2265 }
2266
2267 case Call: {
2268 attemptToMakeCallDOM(node);
2269 break;
2270 }
2271
2272 case ParseInt: {
2273 if (node->child1()->shouldSpeculateInt32() && !node->child2()) {
2274 fixEdge<Int32Use>(node->child1());
2275 node->convertToIdentity();
2276 break;
2277 }
2278
2279 if (node->child1()->shouldSpeculateString()) {
2280 fixEdge<StringUse>(node->child1());
2281 node->clearFlags(NodeMustGenerate);
2282 }
2283
2284 if (node->child2())
2285 fixEdge<Int32Use>(node->child2());
2286
2287 break;
2288 }
2289
2290 case IdentityWithProfile: {
2291 node->clearFlags(NodeMustGenerate);
2292 break;
2293 }
2294
2295 case ThrowStaticError:
2296 fixEdge<StringUse>(node->child1());
2297 break;
2298
2299 case NumberIsInteger:
2300 if (node->child1()->shouldSpeculateInt32()) {
2301 m_insertionSet.insertNode(
2302 m_indexInBlock, SpecNone, Check, node->origin,
2303 Edge(node->child1().node(), Int32Use));
2304 m_graph.convertToConstant(node, jsBoolean(true));
2305 break;
2306 }
2307 break;
2308
2309 case SetCallee:
2310 fixEdge<CellUse>(node->child1());
2311 break;
2312
2313 case DataViewGetInt:
2314 case DataViewGetFloat: {
2315 fixEdge<DataViewObjectUse>(node->child1());
2316 fixEdge<Int32Use>(node->child2());
2317 if (node->child3())
2318 fixEdge<BooleanUse>(node->child3());
2319
2320 if (node->op() == DataViewGetInt) {
2321 DataViewData data = node->dataViewData();
2322 switch (data.byteSize) {
2323 case 1:
2324 case 2:
2325 node->setResult(NodeResultInt32);
2326 break;
2327 case 4:
2328 if (data.isSigned)
2329 node->setResult(NodeResultInt32);
2330 else
2331 node->setResult(NodeResultInt52);
2332 break;
2333 default:
2334 RELEASE_ASSERT_NOT_REACHED();
2335 }
2336 }
2337 break;
2338 }
2339
2340 case DataViewSet: {
2341 fixEdge<DataViewObjectUse>(m_graph.varArgChild(node, 0));
2342 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
2343 if (m_graph.varArgChild(node, 3))
2344 fixEdge<BooleanUse>(m_graph.varArgChild(node, 3));
2345
2346 DataViewData data = node->dataViewData();
2347 Edge& valueToStore = m_graph.varArgChild(node, 2);
2348 if (data.isFloatingPoint)
2349 fixEdge<DoubleRepUse>(valueToStore);
2350 else {
2351 switch (data.byteSize) {
2352 case 1:
2353 case 2:
2354 fixEdge<Int32Use>(valueToStore);
2355 break;
2356 case 4:
2357 if (data.isSigned)
2358 fixEdge<Int32Use>(valueToStore);
2359 else
2360 fixEdge<Int52RepUse>(valueToStore);
2361 break;
2362 }
2363 }
2364 break;
2365 }
2366
2367#if !ASSERT_DISABLED
2368 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
2369 case SetArgumentDefinitely:
2370 case SetArgumentMaybe:
2371 case JSConstant:
2372 case LazyJSConstant:
2373 case DoubleConstant:
2374 case GetLocal:
2375 case GetCallee:
2376 case GetArgumentCountIncludingThis:
2377 case SetArgumentCountIncludingThis:
2378 case GetRestLength:
2379 case GetArgument:
2380 case Flush:
2381 case PhantomLocal:
2382 case GetGlobalVar:
2383 case GetGlobalLexicalVariable:
2384 case NotifyWrite:
2385 case DirectCall:
2386 case CheckTypeInfoFlags:
2387 case TailCallInlinedCaller:
2388 case DirectTailCallInlinedCaller:
2389 case Construct:
2390 case DirectConstruct:
2391 case CallVarargs:
2392 case CallEval:
2393 case TailCallVarargsInlinedCaller:
2394 case ConstructVarargs:
2395 case CallForwardVarargs:
2396 case ConstructForwardVarargs:
2397 case TailCallForwardVarargs:
2398 case TailCallForwardVarargsInlinedCaller:
2399 case LoadVarargs:
2400 case ForwardVarargs:
2401 case ProfileControlFlow:
2402 case NewObject:
2403 case NewRegexp:
2404 case DeleteById:
2405 case DeleteByVal:
2406 case IsTypedArrayView:
2407 case IsEmpty:
2408 case IsUndefined:
2409 case IsUndefinedOrNull:
2410 case IsBoolean:
2411 case IsNumber:
2412 case IsObjectOrNull:
2413 case IsFunction:
2414 case CreateDirectArguments:
2415 case Jump:
2416 case Return:
2417 case TailCall:
2418 case DirectTailCall:
2419 case TailCallVarargs:
2420 case Throw:
2421 case CountExecution:
2422 case SuperSamplerBegin:
2423 case SuperSamplerEnd:
2424 case ForceOSRExit:
2425 case CheckBadCell:
2426 case CheckNotEmpty:
2427 case AssertNotEmpty:
2428 case CheckTraps:
2429 case Unreachable:
2430 case ExtractOSREntryLocal:
2431 case ExtractCatchLocal:
2432 case ClearCatchLocals:
2433 case LoopHint:
2434 case MovHint:
2435 case InitializeEntrypointArguments:
2436 case ZombieHint:
2437 case ExitOK:
2438 case BottomValue:
2439 case TypeOf:
2440 case PutByIdWithThis:
2441 case PutByValWithThis:
2442 case GetByValWithThis:
2443 case CompareEqPtr:
2444 case NumberToStringWithValidRadixConstant:
2445 case GetGlobalThis:
2446 case ExtractValueFromWeakMapGet:
2447 case CPUIntrinsic:
2448 case FilterCallLinkStatus:
2449 case FilterGetByIdStatus:
2450 case FilterPutByIdStatus:
2451 case FilterInByIdStatus:
2452 case InvalidationPoint:
2453 break;
2454#else
2455 default:
2456 break;
2457#endif
2458 }
2459 }
2460
2461 void watchHavingABadTime(Node* node)
2462 {
2463 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
2464
2465 // If this global object is not having a bad time, watch it. We go down this path anytime the code
2466 // does an array allocation. The types of array allocations may change if we start to have a bad
2467 // time. It's easier to reason about this if we know that whenever the types change after we start
2468 // optimizing, the code just gets thrown out. Doing this at FixupPhase is just early enough, since
2469 // prior to this point nobody should have been doing optimizations based on the indexing type of
2470 // the allocation.
2471 if (!globalObject->isHavingABadTime()) {
2472 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2473 m_graph.freeze(globalObject);
2474 }
2475 }
2476
2477 template<UseKind useKind>
2478 void createToString(Node* node, Edge& edge)
2479 {
2480 Node* toString = m_insertionSet.insertNode(
2481 m_indexInBlock, SpecString, ToString, node->origin,
2482 Edge(edge.node(), useKind));
2483 switch (useKind) {
2484 case Int32Use:
2485 case Int52RepUse:
2486 case DoubleRepUse:
2487 case NotCellUse:
2488 toString->clearFlags(NodeMustGenerate);
2489 break;
2490 default:
2491 break;
2492 }
2493 edge.setNode(toString);
2494 }
2495
2496 template<UseKind useKind>
2497 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
2498 {
2499 ASSERT(arrayMode == ArrayMode(Array::Generic, Array::Read) || arrayMode == ArrayMode(Array::Generic, Array::OriginalNonArray, Array::Read));
2500
2501 if (!m_graph.canOptimizeStringObjectAccess(node->origin.semantic))
2502 return;
2503
2504 addCheckStructureForOriginalStringObjectUse(useKind, node->origin, node->child1().node());
2505 createToString<useKind>(node, node->child1());
2506 arrayMode = ArrayMode(Array::String, Array::Read);
2507 }
2508
2509 void addCheckStructureForOriginalStringObjectUse(UseKind useKind, const NodeOrigin& origin, Node* node)
2510 {
2511 RELEASE_ASSERT(useKind == StringObjectUse || useKind == StringOrStringObjectUse);
2512
2513 StructureSet set;
2514 set.add(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
2515 if (useKind == StringOrStringObjectUse)
2516 set.add(vm().stringStructure.get());
2517
2518 m_insertionSet.insertNode(
2519 m_indexInBlock, SpecNone, CheckStructure, origin,
2520 OpInfo(m_graph.addStructureSet(set)), Edge(node, CellUse));
2521 }
2522
2523 template<UseKind useKind>
2524 void convertStringAddUse(Node* node, Edge& edge)
2525 {
2526 if (useKind == StringUse) {
2527 observeUseKindOnNode<StringUse>(edge.node());
2528 m_insertionSet.insertNode(
2529 m_indexInBlock, SpecNone, Check, node->origin,
2530 Edge(edge.node(), StringUse));
2531 edge.setUseKind(KnownStringUse);
2532 return;
2533 }
2534
2535 observeUseKindOnNode<useKind>(edge.node());
2536 createToString<useKind>(node, edge);
2537 }
2538
2539 void convertToMakeRope(Node* node)
2540 {
2541 node->setOpAndDefaultFlags(MakeRope);
2542 fixupMakeRope(node);
2543 }
2544
2545 void fixupMakeRope(Node* node)
2546 {
2547 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
2548 Edge& edge = node->children.child(i);
2549 if (!edge)
2550 break;
2551 edge.setUseKind(KnownStringUse);
2552 JSString* string = edge->dynamicCastConstant<JSString*>(vm());
2553 if (!string)
2554 continue;
2555 if (string->length())
2556 continue;
2557
2558 // Don't allow the MakeRope to have zero children.
2559 if (!i && !node->child2())
2560 break;
2561
2562 node->children.removeEdge(i--);
2563 }
2564
2565 if (!node->child2()) {
2566 ASSERT(!node->child3());
2567 node->convertToIdentity();
2568 }
2569 }
2570
2571 void fixupIsCellWithType(Node* node)
2572 {
2573 switch (node->speculatedTypeForQuery()) {
2574 case SpecString:
2575 if (node->child1()->shouldSpeculateString()) {
2576 m_insertionSet.insertNode(
2577 m_indexInBlock, SpecNone, Check, node->origin,
2578 Edge(node->child1().node(), StringUse));
2579 m_graph.convertToConstant(node, jsBoolean(true));
2580 observeUseKindOnNode<StringUse>(node);
2581 return;
2582 }
2583 break;
2584
2585 case SpecProxyObject:
2586 if (node->child1()->shouldSpeculateProxyObject()) {
2587 m_insertionSet.insertNode(
2588 m_indexInBlock, SpecNone, Check, node->origin,
2589 Edge(node->child1().node(), ProxyObjectUse));
2590 m_graph.convertToConstant(node, jsBoolean(true));
2591 observeUseKindOnNode<ProxyObjectUse>(node);
2592 return;
2593 }
2594 break;
2595
2596 case SpecRegExpObject:
2597 if (node->child1()->shouldSpeculateRegExpObject()) {
2598 m_insertionSet.insertNode(
2599 m_indexInBlock, SpecNone, Check, node->origin,
2600 Edge(node->child1().node(), RegExpObjectUse));
2601 m_graph.convertToConstant(node, jsBoolean(true));
2602 observeUseKindOnNode<RegExpObjectUse>(node);
2603 return;
2604 }
2605 break;
2606
2607 case SpecArray:
2608 if (node->child1()->shouldSpeculateArray()) {
2609 m_insertionSet.insertNode(
2610 m_indexInBlock, SpecNone, Check, node->origin,
2611 Edge(node->child1().node(), ArrayUse));
2612 m_graph.convertToConstant(node, jsBoolean(true));
2613 observeUseKindOnNode<ArrayUse>(node);
2614 return;
2615 }
2616 break;
2617
2618 case SpecDerivedArray:
2619 if (node->child1()->shouldSpeculateDerivedArray()) {
2620 m_insertionSet.insertNode(
2621 m_indexInBlock, SpecNone, Check, node->origin,
2622 Edge(node->child1().node(), DerivedArrayUse));
2623 m_graph.convertToConstant(node, jsBoolean(true));
2624 observeUseKindOnNode<DerivedArrayUse>(node);
2625 return;
2626 }
2627 break;
2628 }
2629
2630 if (node->child1()->shouldSpeculateCell()) {
2631 fixEdge<CellUse>(node->child1());
2632 return;
2633 }
2634
2635 if (node->child1()->shouldSpeculateNotCell()) {
2636 m_insertionSet.insertNode(
2637 m_indexInBlock, SpecNone, Check, node->origin,
2638 Edge(node->child1().node(), NotCellUse));
2639 m_graph.convertToConstant(node, jsBoolean(false));
2640 observeUseKindOnNode<NotCellUse>(node);
2641 return;
2642 }
2643 }
2644
2645 void fixupGetPrototypeOf(Node* node)
2646 {
2647 // Reflect.getPrototypeOf only accepts Objects. For Reflect.getPrototypeOf, ByteCodeParser attaches ObjectUse edge filter before fixup phase.
2648 if (node->child1().useKind() != ObjectUse) {
2649 if (node->child1()->shouldSpeculateString()) {
2650 insertCheck<StringUse>(node->child1().node());
2651 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->stringPrototype()));
2652 return;
2653 }
2654 if (node->child1()->shouldSpeculateInt32()) {
2655 insertCheck<Int32Use>(node->child1().node());
2656 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype()));
2657 return;
2658 }
2659 if (node->child1()->shouldSpeculateInt52()) {
2660 insertCheck<Int52RepUse>(node->child1().node());
2661 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype()));
2662 return;
2663 }
2664 if (node->child1()->shouldSpeculateNumber()) {
2665 insertCheck<NumberUse>(node->child1().node());
2666 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype()));
2667 return;
2668 }
2669 if (node->child1()->shouldSpeculateSymbol()) {
2670 insertCheck<SymbolUse>(node->child1().node());
2671 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->symbolPrototype()));
2672 return;
2673 }
2674 if (node->child1()->shouldSpeculateBoolean()) {
2675 insertCheck<BooleanUse>(node->child1().node());
2676 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->booleanPrototype()));
2677 return;
2678 }
2679 }
2680
2681 if (node->child1()->shouldSpeculateFinalObject()) {
2682 fixEdge<FinalObjectUse>(node->child1());
2683 node->clearFlags(NodeMustGenerate);
2684 return;
2685 }
2686 if (node->child1()->shouldSpeculateArray()) {
2687 fixEdge<ArrayUse>(node->child1());
2688 node->clearFlags(NodeMustGenerate);
2689 return;
2690 }
2691 if (node->child1()->shouldSpeculateFunction()) {
2692 fixEdge<FunctionUse>(node->child1());
2693 node->clearFlags(NodeMustGenerate);
2694 return;
2695 }
2696 }
2697
2698 void fixupToThis(Node* node)
2699 {
2700 bool isStrictMode = m_graph.isStrictModeFor(node->origin.semantic);
2701
2702 if (isStrictMode) {
2703 if (node->child1()->shouldSpeculateBoolean()) {
2704 fixEdge<BooleanUse>(node->child1());
2705 node->convertToIdentity();
2706 return;
2707 }
2708
2709 if (node->child1()->shouldSpeculateInt32()) {
2710 fixEdge<Int32Use>(node->child1());
2711 node->convertToIdentity();
2712 return;
2713 }
2714
2715 if (node->child1()->shouldSpeculateInt52()) {
2716 fixEdge<Int52RepUse>(node->child1());
2717 node->convertToIdentity();
2718 node->setResult(NodeResultInt52);
2719 return;
2720 }
2721
2722 if (node->child1()->shouldSpeculateNumber()) {
2723 fixEdge<DoubleRepUse>(node->child1());
2724 node->convertToIdentity();
2725 node->setResult(NodeResultDouble);
2726 return;
2727 }
2728
2729 if (node->child1()->shouldSpeculateSymbol()) {
2730 fixEdge<SymbolUse>(node->child1());
2731 node->convertToIdentity();
2732 return;
2733 }
2734
2735 if (node->child1()->shouldSpeculateStringIdent()) {
2736 fixEdge<StringIdentUse>(node->child1());
2737 node->convertToIdentity();
2738 return;
2739 }
2740
2741 if (node->child1()->shouldSpeculateString()) {
2742 fixEdge<StringUse>(node->child1());
2743 node->convertToIdentity();
2744 return;
2745 }
2746
2747 if (node->child1()->shouldSpeculateBigInt()) {
2748 fixEdge<BigIntUse>(node->child1());
2749 node->convertToIdentity();
2750 return;
2751 }
2752 }
2753
2754 if (node->child1()->shouldSpeculateOther()) {
2755 if (isStrictMode) {
2756 fixEdge<OtherUse>(node->child1());
2757 node->convertToIdentity();
2758 return;
2759 }
2760
2761 m_insertionSet.insertNode(
2762 m_indexInBlock, SpecNone, Check, node->origin,
2763 Edge(node->child1().node(), OtherUse));
2764 observeUseKindOnNode<OtherUse>(node->child1().node());
2765 m_graph.convertToConstant(
2766 node, m_graph.globalThisObjectFor(node->origin.semantic));
2767 return;
2768 }
2769
2770 // FIXME: This should cover other use cases but we don't have use kinds for them. It's not critical,
2771 // however, since we cover all the missing cases in constant folding.
2772 // https://bugs.webkit.org/show_bug.cgi?id=157213
2773 if (node->child1()->shouldSpeculateStringObject()) {
2774 fixEdge<StringObjectUse>(node->child1());
2775 node->convertToIdentity();
2776 return;
2777 }
2778
2779 if (isFinalObjectSpeculation(node->child1()->prediction())) {
2780 fixEdge<FinalObjectUse>(node->child1());
2781 node->convertToIdentity();
2782 return;
2783 }
2784 }
2785
2786 void fixupToPrimitive(Node* node)
2787 {
2788 if (node->child1()->shouldSpeculateInt32()) {
2789 fixEdge<Int32Use>(node->child1());
2790 node->convertToIdentity();
2791 return;
2792 }
2793
2794 if (node->child1()->shouldSpeculateString()) {
2795 fixEdge<StringUse>(node->child1());
2796 node->convertToIdentity();
2797 return;
2798 }
2799
2800 if (node->child1()->shouldSpeculateStringObject()
2801 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2802 addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, node->child1().node());
2803 fixEdge<StringObjectUse>(node->child1());
2804 node->convertToToString();
2805 return;
2806 }
2807
2808 if (node->child1()->shouldSpeculateStringOrStringObject()
2809 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2810 addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, node->child1().node());
2811 fixEdge<StringOrStringObjectUse>(node->child1());
2812 node->convertToToString();
2813 return;
2814 }
2815 }
2816
2817 void fixupToNumber(Node* node)
2818 {
2819 // If the prediction of the child is Number, we attempt to convert ToNumber to Identity.
2820 if (node->child1()->shouldSpeculateNumber()) {
2821 if (isInt32Speculation(node->getHeapPrediction())) {
2822 // If the both predictions of this node and the child is Int32, we just convert ToNumber to Identity, that's simple.
2823 if (node->child1()->shouldSpeculateInt32()) {
2824 fixEdge<Int32Use>(node->child1());
2825 node->convertToIdentity();
2826 return;
2827 }
2828
2829 // The another case is that the predicted type of the child is Int32, but the heap prediction tell the users that this will produce non Int32 values.
2830 // In that case, let's receive the child value as a Double value and convert it to Int32. This case happens in misc-bugs-847389-jpeg2000.
2831 fixEdge<DoubleRepUse>(node->child1());
2832 node->setOp(DoubleAsInt32);
2833 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
2834 node->setArithMode(Arith::CheckOverflow);
2835 else
2836 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
2837 return;
2838 }
2839
2840 fixEdge<DoubleRepUse>(node->child1());
2841 node->convertToIdentity();
2842 node->setResult(NodeResultDouble);
2843 return;
2844 }
2845
2846 fixEdge<UntypedUse>(node->child1());
2847 node->setResult(NodeResultJS);
2848 }
2849
2850 void fixupToObject(Node* node)
2851 {
2852 if (node->child1()->shouldSpeculateObject()) {
2853 fixEdge<ObjectUse>(node->child1());
2854 node->convertToIdentity();
2855 return;
2856 }
2857
2858 // ToObject(Null/Undefined) can throw an error. We can emit filters to convert ToObject to CallObjectConstructor.
2859
2860 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
2861
2862 if (node->child1()->shouldSpeculateString()) {
2863 insertCheck<StringUse>(node->child1().node());
2864 fixEdge<KnownStringUse>(node->child1());
2865 node->convertToNewStringObject(m_graph.registerStructure(globalObject->stringObjectStructure()));
2866 return;
2867 }
2868
2869 if (node->child1()->shouldSpeculateSymbol()) {
2870 insertCheck<SymbolUse>(node->child1().node());
2871 node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
2872 return;
2873 }
2874
2875 if (node->child1()->shouldSpeculateNumber()) {
2876 insertCheck<NumberUse>(node->child1().node());
2877 node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
2878 return;
2879 }
2880
2881 if (node->child1()->shouldSpeculateBoolean()) {
2882 insertCheck<BooleanUse>(node->child1().node());
2883 node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
2884 return;
2885 }
2886
2887 fixEdge<UntypedUse>(node->child1());
2888 }
2889
2890 void fixupCallObjectConstructor(Node* node)
2891 {
2892 if (node->child1()->shouldSpeculateObject()) {
2893 fixEdge<ObjectUse>(node->child1());
2894 node->convertToIdentity();
2895 return;
2896 }
2897
2898 if (node->child1()->shouldSpeculateString()) {
2899 auto* globalObject = jsCast<JSGlobalObject*>(node->cellOperand()->cell());
2900 insertCheck<StringUse>(node->child1().node());
2901 fixEdge<KnownStringUse>(node->child1());
2902 node->convertToNewStringObject(m_graph.registerStructure(globalObject->stringObjectStructure()));
2903 return;
2904 }
2905
2906 // While ToObject(Null/Undefined) throws an error, CallObjectConstructor(Null/Undefined) generates a new empty object.
2907 if (node->child1()->shouldSpeculateOther()) {
2908 insertCheck<OtherUse>(node->child1().node());
2909 node->convertToNewObject(m_graph.registerStructure(jsCast<JSGlobalObject*>(node->cellOperand()->cell())->objectStructureForObjectConstructor()));
2910 return;
2911 }
2912
2913 fixEdge<UntypedUse>(node->child1());
2914 }
2915
2916 void fixupToStringOrCallStringConstructor(Node* node)
2917 {
2918 if (node->child1()->shouldSpeculateString()) {
2919 fixEdge<StringUse>(node->child1());
2920 node->convertToIdentity();
2921 return;
2922 }
2923
2924 if (node->child1()->shouldSpeculateStringObject()
2925 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2926 addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, node->child1().node());
2927 fixEdge<StringObjectUse>(node->child1());
2928 return;
2929 }
2930
2931 if (node->child1()->shouldSpeculateStringOrStringObject()
2932 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2933 addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, node->child1().node());
2934 fixEdge<StringOrStringObjectUse>(node->child1());
2935 return;
2936 }
2937
2938 if (node->child1()->shouldSpeculateCell()) {
2939 fixEdge<CellUse>(node->child1());
2940 return;
2941 }
2942
2943 if (node->child1()->shouldSpeculateInt32()) {
2944 fixEdge<Int32Use>(node->child1());
2945 node->clearFlags(NodeMustGenerate);
2946 return;
2947 }
2948
2949 if (node->child1()->shouldSpeculateInt52()) {
2950 fixEdge<Int52RepUse>(node->child1());
2951 node->clearFlags(NodeMustGenerate);
2952 return;
2953 }
2954
2955 if (node->child1()->shouldSpeculateNumber()) {
2956 fixEdge<DoubleRepUse>(node->child1());
2957 node->clearFlags(NodeMustGenerate);
2958 return;
2959 }
2960
2961 // ToString(Symbol) throws an error. So if the child1 can include Symbols,
2962 // we need to care about it in the clobberize. In the following case,
2963 // since NotCellUse edge filter is used and this edge filters Symbols,
2964 // we can say that ToString never throws an error!
2965 if (node->child1()->shouldSpeculateNotCell()) {
2966 fixEdge<NotCellUse>(node->child1());
2967 node->clearFlags(NodeMustGenerate);
2968 return;
2969 }
2970 }
2971
2972 void fixupStringValueOf(Node* node)
2973 {
2974 if (node->child1()->shouldSpeculateString()) {
2975 fixEdge<StringUse>(node->child1());
2976 node->convertToIdentity();
2977 return;
2978 }
2979
2980 if (node->child1()->shouldSpeculateStringObject()) {
2981 fixEdge<StringObjectUse>(node->child1());
2982 node->convertToToString();
2983 // It does not need to look up a toString property for the StringObject case. So we can clear NodeMustGenerate.
2984 node->clearFlags(NodeMustGenerate);
2985 return;
2986 }
2987
2988 if (node->child1()->shouldSpeculateStringOrStringObject()) {
2989 fixEdge<StringOrStringObjectUse>(node->child1());
2990 node->convertToToString();
2991 // It does not need to look up a toString property for the StringObject case. So we can clear NodeMustGenerate.
2992 node->clearFlags(NodeMustGenerate);
2993 return;
2994 }
2995 }
2996
2997 bool attemptToMakeFastStringAdd(Node* node)
2998 {
2999 bool goodToGo = true;
3000 m_graph.doToChildren(
3001 node,
3002 [&] (Edge& edge) {
3003 if (edge->shouldSpeculateString())
3004 return;
3005 if (m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
3006 if (edge->shouldSpeculateStringObject())
3007 return;
3008 if (edge->shouldSpeculateStringOrStringObject())
3009 return;
3010 }
3011 goodToGo = false;
3012 });
3013 if (!goodToGo)
3014 return false;
3015
3016 m_graph.doToChildren(
3017 node,
3018 [&] (Edge& edge) {
3019 if (edge->shouldSpeculateString()) {
3020 convertStringAddUse<StringUse>(node, edge);
3021 return;
3022 }
3023 if (!Options::useConcurrentJIT())
3024 ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
3025 if (edge->shouldSpeculateStringObject()) {
3026 addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, edge.node());
3027 convertStringAddUse<StringObjectUse>(node, edge);
3028 return;
3029 }
3030 if (edge->shouldSpeculateStringOrStringObject()) {
3031 addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, edge.node());
3032 convertStringAddUse<StringOrStringObjectUse>(node, edge);
3033 return;
3034 }
3035 RELEASE_ASSERT_NOT_REACHED();
3036 });
3037
3038 convertToMakeRope(node);
3039 return true;
3040 }
3041
3042 void fixupGetAndSetLocalsInBlock(BasicBlock* block)
3043 {
3044 if (!block)
3045 return;
3046 ASSERT(block->isReachable);
3047 m_block = block;
3048 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
3049 Node* node = m_currentNode = block->at(m_indexInBlock);
3050 if (node->op() != SetLocal && node->op() != GetLocal)
3051 continue;
3052
3053 VariableAccessData* variable = node->variableAccessData();
3054 switch (node->op()) {
3055 case GetLocal:
3056 switch (variable->flushFormat()) {
3057 case FlushedDouble:
3058 node->setResult(NodeResultDouble);
3059 break;
3060 case FlushedInt52:
3061 node->setResult(NodeResultInt52);
3062 break;
3063 default:
3064 break;
3065 }
3066 break;
3067
3068 case SetLocal:
3069 // NOTE: Any type checks we put here may get hoisted by fixupChecksInBlock(). So, if we
3070 // add new type checking use kind for SetLocals, we need to modify that code as well.
3071
3072 switch (variable->flushFormat()) {
3073 case FlushedJSValue:
3074 break;
3075 case FlushedDouble:
3076 fixEdge<DoubleRepUse>(node->child1());
3077 break;
3078 case FlushedInt32:
3079 fixEdge<Int32Use>(node->child1());
3080 break;
3081 case FlushedInt52:
3082 fixEdge<Int52RepUse>(node->child1());
3083 break;
3084 case FlushedCell:
3085 fixEdge<CellUse>(node->child1());
3086 break;
3087 case FlushedBoolean:
3088 fixEdge<BooleanUse>(node->child1());
3089 break;
3090 default:
3091 RELEASE_ASSERT_NOT_REACHED();
3092 break;
3093 }
3094 break;
3095
3096 default:
3097 RELEASE_ASSERT_NOT_REACHED();
3098 break;
3099 }
3100 }
3101 m_insertionSet.execute(block);
3102 }
3103
3104 void addStringReplacePrimordialChecks(Node* searchRegExp)
3105 {
3106 Node* node = m_currentNode;
3107
3108 // Check that structure of searchRegExp is RegExp object
3109 m_insertionSet.insertNode(
3110 m_indexInBlock, SpecNone, Check, node->origin,
3111 Edge(searchRegExp, RegExpObjectUse));
3112
3113 auto emitPrimordialCheckFor = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
3114 unsigned index = m_graph.identifiers().ensure(propertyUID);
3115
3116 Node* actualProperty = m_insertionSet.insertNode(
3117 m_indexInBlock, SpecNone, TryGetById, node->origin,
3118 OpInfo(index), OpInfo(SpecFunction), Edge(searchRegExp, CellUse));
3119
3120 m_insertionSet.insertNode(
3121 m_indexInBlock, SpecNone, CheckCell, node->origin,
3122 OpInfo(m_graph.freeze(primordialProperty)), Edge(actualProperty, CellUse));
3123 };
3124
3125 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
3126
3127 // Check that searchRegExp.exec is the primordial RegExp.prototype.exec
3128 emitPrimordialCheckFor(globalObject->regExpProtoExecFunction(), vm().propertyNames->exec.impl());
3129 // Check that searchRegExp.global is the primordial RegExp.prototype.global
3130 emitPrimordialCheckFor(globalObject->regExpProtoGlobalGetter(), vm().propertyNames->global.impl());
3131 // Check that searchRegExp.unicode is the primordial RegExp.prototype.unicode
3132 emitPrimordialCheckFor(globalObject->regExpProtoUnicodeGetter(), vm().propertyNames->unicode.impl());
3133 // Check that searchRegExp[Symbol.match] is the primordial RegExp.prototype[Symbol.replace]
3134 emitPrimordialCheckFor(globalObject->regExpProtoSymbolReplaceFunction(), vm().propertyNames->replaceSymbol.impl());
3135 }
3136
3137 Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
3138 {
3139 ASSERT(arrayMode.isSpecific());
3140
3141 if (arrayMode.type() == Array::String) {
3142 m_insertionSet.insertNode(
3143 m_indexInBlock, SpecNone, Check, origin, Edge(array, StringUse));
3144 } else {
3145 // Note that we only need to be using a structure check if we opt for SaneChain, since
3146 // that needs to protect against JSArray's __proto__ being changed.
3147 Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
3148
3149 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
3150
3151 if (arrayMode.doesConversion()) {
3152 if (structure) {
3153 m_insertionSet.insertNode(
3154 m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
3155 OpInfo(m_graph.registerStructure(structure)), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
3156 } else {
3157 m_insertionSet.insertNode(
3158 m_indexInBlock, SpecNone, Arrayify, origin,
3159 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
3160 }
3161 } else {
3162 if (structure) {
3163 m_insertionSet.insertNode(
3164 m_indexInBlock, SpecNone, CheckStructure, origin,
3165 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
3166 } else {
3167 m_insertionSet.insertNode(
3168 m_indexInBlock, SpecNone, CheckArray, origin,
3169 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
3170 }
3171 }
3172 }
3173
3174 if (!storageCheck(arrayMode))
3175 return nullptr;
3176
3177 if (arrayMode.usesButterfly()) {
3178 return m_insertionSet.insertNode(
3179 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
3180 }
3181
3182 return m_insertionSet.insertNode(
3183 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
3184 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
3185 }
3186
3187 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
3188 {
3189 Node* node = m_currentNode;
3190
3191 switch (node->arrayMode().type()) {
3192 case Array::ForceExit: {
3193 m_insertionSet.insertNode(
3194 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
3195 return;
3196 }
3197
3198 case Array::SelectUsingPredictions:
3199 case Array::Unprofiled:
3200 RELEASE_ASSERT_NOT_REACHED();
3201 return;
3202
3203 case Array::Generic:
3204 return;
3205
3206 default: {
3207 Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
3208 if (!storage)
3209 return;
3210
3211 storageChild = Edge(storage);
3212 return;
3213 } }
3214 }
3215
3216 bool alwaysUnboxSimplePrimitives()
3217 {
3218#if USE(JSVALUE64)
3219 return false;
3220#else
3221 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
3222 // reduces traffic.
3223 return true;
3224#endif
3225 }
3226
3227 template<UseKind useKind>
3228 void observeUseKindOnNode(Node* node)
3229 {
3230 if (useKind == UntypedUse)
3231 return;
3232 observeUseKindOnNode(node, useKind);
3233 }
3234
3235 void observeUseKindOnEdge(Edge edge)
3236 {
3237 observeUseKindOnNode(edge.node(), edge.useKind());
3238 }
3239
3240 void observeUseKindOnNode(Node* node, UseKind useKind)
3241 {
3242 if (node->op() != GetLocal)
3243 return;
3244
3245 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
3246 // https://bugs.webkit.org/show_bug.cgi?id=121518
3247
3248 VariableAccessData* variable = node->variableAccessData();
3249 switch (useKind) {
3250 case Int32Use:
3251 case KnownInt32Use:
3252 if (alwaysUnboxSimplePrimitives()
3253 || isInt32Speculation(variable->prediction()))
3254 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
3255 break;
3256 case NumberUse:
3257 case RealNumberUse:
3258 case DoubleRepUse:
3259 case DoubleRepRealUse:
3260 if (variable->doubleFormatState() == UsingDoubleFormat)
3261 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
3262 break;
3263 case BooleanUse:
3264 case KnownBooleanUse:
3265 if (alwaysUnboxSimplePrimitives()
3266 || isBooleanSpeculation(variable->prediction()))
3267 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
3268 break;
3269 case Int52RepUse:
3270 if (!isInt32Speculation(variable->prediction()) && isInt32OrInt52Speculation(variable->prediction()))
3271 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
3272 break;
3273 case CellUse:
3274 case KnownCellUse:
3275 case ObjectUse:
3276 case FunctionUse:
3277 case StringUse:
3278 case KnownStringUse:
3279 case SymbolUse:
3280 case BigIntUse:
3281 case StringObjectUse:
3282 case StringOrStringObjectUse:
3283 if (alwaysUnboxSimplePrimitives()
3284 || isCellSpeculation(variable->prediction()))
3285 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
3286 break;
3287 default:
3288 break;
3289 }
3290 }
3291
3292 template<UseKind useKind>
3293 void fixEdge(Edge& edge)
3294 {
3295 observeUseKindOnNode<useKind>(edge.node());
3296 edge.setUseKind(useKind);
3297 }
3298
3299 unsigned indexForChecks()
3300 {
3301 unsigned index = m_indexInBlock;
3302 while (!m_block->at(index)->origin.exitOK)
3303 index--;
3304 return index;
3305 }
3306
3307 NodeOrigin originForCheck(unsigned index)
3308 {
3309 return m_block->at(index)->origin.withSemantic(m_currentNode->origin.semantic);
3310 }
3311
3312 void speculateForBarrier(Edge value)
3313 {
3314 // Currently, the DFG won't take advantage of this speculation. But, we want to do it in
3315 // the DFG anyway because if such a speculation would be wrong, we want to know before
3316 // we do an expensive compile.
3317
3318 if (value->shouldSpeculateInt32()) {
3319 insertCheck<Int32Use>(value.node());
3320 return;
3321 }
3322
3323 if (value->shouldSpeculateBoolean()) {
3324 insertCheck<BooleanUse>(value.node());
3325 return;
3326 }
3327
3328 if (value->shouldSpeculateOther()) {
3329 insertCheck<OtherUse>(value.node());
3330 return;
3331 }
3332
3333 if (value->shouldSpeculateNumber()) {
3334 insertCheck<NumberUse>(value.node());
3335 return;
3336 }
3337
3338 if (value->shouldSpeculateNotCell()) {
3339 insertCheck<NotCellUse>(value.node());
3340 return;
3341 }
3342 }
3343
3344 template<UseKind useKind>
3345 void insertCheck(Node* node)
3346 {
3347 observeUseKindOnNode<useKind>(node);
3348 unsigned index = indexForChecks();
3349 m_insertionSet.insertNode(index, SpecNone, Check, originForCheck(index), Edge(node, useKind));
3350 }
3351
3352 void fixIntConvertingEdge(Edge& edge)
3353 {
3354 Node* node = edge.node();
3355 if (node->shouldSpeculateInt32OrBoolean()) {
3356 fixIntOrBooleanEdge(edge);
3357 return;
3358 }
3359
3360 UseKind useKind;
3361 if (node->shouldSpeculateInt52())
3362 useKind = Int52RepUse;
3363 else if (node->shouldSpeculateNumber())
3364 useKind = DoubleRepUse;
3365 else
3366 useKind = NotCellUse;
3367 Node* newNode = m_insertionSet.insertNode(
3368 m_indexInBlock, SpecInt32Only, ValueToInt32, m_currentNode->origin,
3369 Edge(node, useKind));
3370 observeUseKindOnNode(node, useKind);
3371
3372 edge = Edge(newNode, KnownInt32Use);
3373 }
3374
3375 void fixIntOrBooleanEdge(Edge& edge)
3376 {
3377 Node* node = edge.node();
3378 if (!node->sawBooleans()) {
3379 fixEdge<Int32Use>(edge);
3380 return;
3381 }
3382
3383 UseKind useKind;
3384 if (node->shouldSpeculateBoolean())
3385 useKind = BooleanUse;
3386 else
3387 useKind = UntypedUse;
3388 Node* newNode = m_insertionSet.insertNode(
3389 m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
3390 Edge(node, useKind));
3391 observeUseKindOnNode(node, useKind);
3392
3393 edge = Edge(newNode, Int32Use);
3394 }
3395
3396 void fixDoubleOrBooleanEdge(Edge& edge)
3397 {
3398 Node* node = edge.node();
3399 if (!node->sawBooleans()) {
3400 fixEdge<DoubleRepUse>(edge);
3401 return;
3402 }
3403
3404 UseKind useKind;
3405 if (node->shouldSpeculateBoolean())
3406 useKind = BooleanUse;
3407 else
3408 useKind = UntypedUse;
3409 Node* newNode = m_insertionSet.insertNode(
3410 m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
3411 Edge(node, useKind));
3412 observeUseKindOnNode(node, useKind);
3413
3414 edge = Edge(newNode, DoubleRepUse);
3415 }
3416
3417 void truncateConstantToInt32(Edge& edge)
3418 {
3419 Node* oldNode = edge.node();
3420
3421 JSValue value = oldNode->asJSValue();
3422 if (value.isInt32())
3423 return;
3424
3425 value = jsNumber(JSC::toInt32(value.asNumber()));
3426 ASSERT(value.isInt32());
3427 edge.setNode(m_insertionSet.insertNode(
3428 m_indexInBlock, SpecInt32Only, JSConstant, m_currentNode->origin,
3429 OpInfo(m_graph.freeze(value))));
3430 }
3431
3432 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
3433 {
3434 if (mode != SpeculateInt32AndTruncateConstants)
3435 return;
3436
3437 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
3438 if (node->child1()->hasConstant())
3439 truncateConstantToInt32(node->child1());
3440 else
3441 truncateConstantToInt32(node->child2());
3442 }
3443
3444 bool attemptToMakeIntegerAdd(Node* node)
3445 {
3446 AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
3447 if (mode != DontSpeculateInt32) {
3448 truncateConstantsIfNecessary(node, mode);
3449 fixIntOrBooleanEdge(node->child1());
3450 fixIntOrBooleanEdge(node->child2());
3451 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
3452 node->setArithMode(Arith::Unchecked);
3453 else
3454 node->setArithMode(Arith::CheckOverflow);
3455 return true;
3456 }
3457
3458 if (m_graph.addShouldSpeculateInt52(node)) {
3459 fixEdge<Int52RepUse>(node->child1());
3460 fixEdge<Int52RepUse>(node->child2());
3461 node->setArithMode(Arith::CheckOverflow);
3462 node->setResult(NodeResultInt52);
3463 return true;
3464 }
3465
3466 return false;
3467 }
3468
3469 bool attemptToMakeGetArrayLength(Node* node)
3470 {
3471 if (!isInt32Speculation(node->prediction()))
3472 return false;
3473 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
3474 ArrayProfile* arrayProfile =
3475 profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex());
3476 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions, Array::Read);
3477 if (arrayProfile) {
3478 ConcurrentJSLocker locker(profiledBlock->m_lock);
3479 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
3480 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
3481 if (arrayMode.type() == Array::Unprofiled) {
3482 // For normal array operations, it makes sense to treat Unprofiled
3483 // accesses as ForceExit and get more data rather than using
3484 // predictions and then possibly ending up with a Generic. But here,
3485 // we treat anything that is Unprofiled as Generic and keep the
3486 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
3487 // profit - from treating the Unprofiled case as
3488 // SelectUsingPredictions.
3489 arrayMode = ArrayMode(Array::SelectUsingPredictions, Array::Read);
3490 }
3491 }
3492
3493 arrayMode = arrayMode.refine(
3494 m_graph, node, node->child1()->prediction(), node->prediction());
3495
3496 if (arrayMode.type() == Array::Generic) {
3497 // Check if the input is something that we can't get array length for, but for which we
3498 // could insert some conversions in order to transform it into something that we can do it
3499 // for.
3500 if (node->child1()->shouldSpeculateStringObject())
3501 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
3502 else if (node->child1()->shouldSpeculateStringOrStringObject())
3503 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
3504 }
3505
3506 if (!arrayMode.supportsSelfLength())
3507 return false;
3508
3509 convertToGetArrayLength(node, arrayMode);
3510 return true;
3511 }
3512
3513 void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
3514 {
3515 node->setOp(GetArrayLength);
3516 node->clearFlags(NodeMustGenerate);
3517 fixEdge<KnownCellUse>(node->child1());
3518 node->setArrayMode(arrayMode);
3519
3520 Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
3521 if (!storage)
3522 return;
3523
3524 node->child2() = Edge(storage);
3525 }
3526
3527 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
3528 {
3529 Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
3530 return m_insertionSet.insertNode(
3531 m_indexInBlock, SpecInt32Only, GetArrayLength, origin,
3532 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
3533 }
3534
3535 void convertToHasIndexedProperty(Node* node)
3536 {
3537 node->setOp(HasIndexedProperty);
3538 node->clearFlags(NodeMustGenerate);
3539
3540 {
3541 unsigned firstChild = m_graph.m_varArgChildren.size();
3542 unsigned numChildren = 3;
3543 m_graph.m_varArgChildren.append(node->child1());
3544 m_graph.m_varArgChildren.append(node->child2());
3545 m_graph.m_varArgChildren.append(Edge());
3546 node->mergeFlags(NodeHasVarArgs);
3547 node->children = AdjacencyList(AdjacencyList::Variable, firstChild, numChildren);
3548 }
3549
3550 node->setArrayMode(
3551 node->arrayMode().refine(
3552 m_graph, node,
3553 m_graph.varArgChild(node, 0)->prediction(),
3554 m_graph.varArgChild(node, 1)->prediction(),
3555 SpecNone));
3556 node->setInternalMethodType(PropertySlot::InternalMethodType::HasProperty);
3557
3558 blessArrayOperation(m_graph.varArgChild(node, 0), m_graph.varArgChild(node, 1), m_graph.varArgChild(node, 2));
3559
3560 fixEdge<CellUse>(m_graph.varArgChild(node, 0));
3561 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
3562 }
3563
3564 void fixupNormalizeMapKey(Node* node)
3565 {
3566 if (node->child1()->shouldSpeculateBoolean()) {
3567 fixEdge<BooleanUse>(node->child1());
3568 node->convertToIdentity();
3569 return;
3570 }
3571
3572 if (node->child1()->shouldSpeculateInt32()) {
3573 fixEdge<Int32Use>(node->child1());
3574 node->convertToIdentity();
3575 return;
3576 }
3577
3578 if (node->child1()->shouldSpeculateSymbol()) {
3579 fixEdge<SymbolUse>(node->child1());
3580 node->convertToIdentity();
3581 return;
3582 }
3583
3584 if (node->child1()->shouldSpeculateObject()) {
3585 fixEdge<ObjectUse>(node->child1());
3586 node->convertToIdentity();
3587 return;
3588 }
3589
3590 if (node->child1()->shouldSpeculateString()) {
3591 fixEdge<StringUse>(node->child1());
3592 node->convertToIdentity();
3593 return;
3594 }
3595
3596 if (node->child1()->shouldSpeculateCell()) {
3597 fixEdge<CellUse>(node->child1());
3598 node->convertToIdentity();
3599 return;
3600 }
3601
3602 fixEdge<UntypedUse>(node->child1());
3603 }
3604
3605 bool attemptToMakeCallDOM(Node* node)
3606 {
3607 if (m_graph.hasExitSite(node->origin.semantic, BadType))
3608 return false;
3609
3610 const DOMJIT::Signature* signature = node->signature();
3611 if (!signature)
3612 return false;
3613
3614 {
3615 unsigned index = 0;
3616 bool shouldConvertToCallDOM = true;
3617 m_graph.doToChildren(node, [&](Edge& edge) {
3618 // Callee. Ignore this. DFGByteCodeParser already emit appropriate checks.
3619 if (!index)
3620 return;
3621
3622 if (index == 1) {
3623 // DOM node case.
3624 if (edge->shouldSpeculateNotCell())
3625 shouldConvertToCallDOM = false;
3626 } else {
3627 switch (signature->arguments[index - 2]) {
3628 case SpecString:
3629 if (edge->shouldSpeculateNotString())
3630 shouldConvertToCallDOM = false;
3631 break;
3632 case SpecInt32Only:
3633 if (edge->shouldSpeculateNotInt32())
3634 shouldConvertToCallDOM = false;
3635 break;
3636 case SpecBoolean:
3637 if (edge->shouldSpeculateNotBoolean())
3638 shouldConvertToCallDOM = false;
3639 break;
3640 default:
3641 RELEASE_ASSERT_NOT_REACHED();
3642 break;
3643 }
3644 }
3645 ++index;
3646 });
3647 if (!shouldConvertToCallDOM)
3648 return false;
3649 }
3650
3651 Node* thisNode = m_graph.varArgChild(node, 1).node();
3652 Node* checkSubClass = m_insertionSet.insertNode(m_indexInBlock, SpecNone, CheckSubClass, node->origin, OpInfo(signature->classInfo), Edge(thisNode));
3653 node->convertToCallDOM(m_graph);
3654 fixupCheckSubClass(checkSubClass);
3655 fixupCallDOM(node);
3656 return true;
3657 }
3658
3659 void fixupCheckSubClass(Node* node)
3660 {
3661 fixEdge<CellUse>(node->child1());
3662 }
3663
3664 void fixupCallDOM(Node* node)
3665 {
3666 const DOMJIT::Signature* signature = node->signature();
3667 auto fixup = [&](Edge& edge, unsigned argumentIndex) {
3668 if (!edge)
3669 return;
3670 switch (signature->arguments[argumentIndex]) {
3671 case SpecString:
3672 fixEdge<StringUse>(edge);
3673 break;
3674 case SpecInt32Only:
3675 fixEdge<Int32Use>(edge);
3676 break;
3677 case SpecBoolean:
3678 fixEdge<BooleanUse>(edge);
3679 break;
3680 default:
3681 RELEASE_ASSERT_NOT_REACHED();
3682 break;
3683 }
3684 };
3685 fixEdge<CellUse>(node->child1()); // DOM.
3686 fixup(node->child2(), 0);
3687 fixup(node->child3(), 1);
3688 }
3689
3690 void fixupArrayIndexOf(Node* node)
3691 {
3692 Edge& array = m_graph.varArgChild(node, 0);
3693 Edge& storage = m_graph.varArgChild(node, node->numChildren() == 3 ? 2 : 3);
3694 blessArrayOperation(array, Edge(), storage);
3695 ASSERT_WITH_MESSAGE(storage.node(), "blessArrayOperation for ArrayIndexOf must set Butterfly for storage edge.");
3696
3697 Edge& searchElement = m_graph.varArgChild(node, 1);
3698
3699 // Constant folding.
3700 switch (node->arrayMode().type()) {
3701 case Array::Double:
3702 case Array::Int32: {
3703 if (searchElement->shouldSpeculateCell()) {
3704 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), CellUse));
3705 m_graph.convertToConstant(node, jsNumber(-1));
3706 observeUseKindOnNode<CellUse>(searchElement.node());
3707 return;
3708 }
3709
3710 if (searchElement->shouldSpeculateOther()) {
3711 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), OtherUse));
3712 m_graph.convertToConstant(node, jsNumber(-1));
3713 observeUseKindOnNode<OtherUse>(searchElement.node());
3714 return;
3715 }
3716
3717 if (searchElement->shouldSpeculateBoolean()) {
3718 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), BooleanUse));
3719 m_graph.convertToConstant(node, jsNumber(-1));
3720 observeUseKindOnNode<BooleanUse>(searchElement.node());
3721 return;
3722 }
3723 break;
3724 }
3725 default:
3726 break;
3727 }
3728
3729 fixEdge<KnownCellUse>(array);
3730 if (node->numChildren() == 4)
3731 fixEdge<Int32Use>(m_graph.varArgChild(node, 2));
3732
3733 switch (node->arrayMode().type()) {
3734 case Array::Double: {
3735 if (searchElement->shouldSpeculateNumber())
3736 fixEdge<DoubleRepUse>(searchElement);
3737 return;
3738 }
3739 case Array::Int32: {
3740 if (searchElement->shouldSpeculateInt32())
3741 fixEdge<Int32Use>(searchElement);
3742 return;
3743 }
3744 case Array::Contiguous: {
3745 if (searchElement->shouldSpeculateString())
3746 fixEdge<StringUse>(searchElement);
3747 else if (searchElement->shouldSpeculateSymbol())
3748 fixEdge<SymbolUse>(searchElement);
3749 else if (searchElement->shouldSpeculateOther())
3750 fixEdge<OtherUse>(searchElement);
3751 else if (searchElement->shouldSpeculateObject())
3752 fixEdge<ObjectUse>(searchElement);
3753 return;
3754 }
3755 default:
3756 RELEASE_ASSERT_NOT_REACHED();
3757 return;
3758 }
3759 }
3760
3761 void fixupCompareStrictEqAndSameValue(Node* node)
3762 {
3763 ASSERT(node->op() == SameValue || node->op() == CompareStrictEq);
3764
3765 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
3766 fixEdge<BooleanUse>(node->child1());
3767 fixEdge<BooleanUse>(node->child2());
3768 node->setOpAndDefaultFlags(CompareStrictEq);
3769 return;
3770 }
3771 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
3772 fixEdge<Int32Use>(node->child1());
3773 fixEdge<Int32Use>(node->child2());
3774 node->setOpAndDefaultFlags(CompareStrictEq);
3775 return;
3776 }
3777 if (Node::shouldSpeculateInt52(node->child1().node(), node->child2().node())) {
3778 fixEdge<Int52RepUse>(node->child1());
3779 fixEdge<Int52RepUse>(node->child2());
3780 node->setOpAndDefaultFlags(CompareStrictEq);
3781 return;
3782 }
3783 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
3784 fixEdge<DoubleRepUse>(node->child1());
3785 fixEdge<DoubleRepUse>(node->child2());
3786 // Do not convert SameValue to CompareStrictEq in this case since SameValue(NaN, NaN) and SameValue(-0, +0)
3787 // are not the same to CompareStrictEq(NaN, NaN) and CompareStrictEq(-0, +0).
3788 return;
3789 }
3790 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
3791 fixEdge<SymbolUse>(node->child1());
3792 fixEdge<SymbolUse>(node->child2());
3793 node->setOpAndDefaultFlags(CompareStrictEq);
3794 return;
3795 }
3796 if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
3797 fixEdge<BigIntUse>(node->child1());
3798 fixEdge<BigIntUse>(node->child2());
3799 node->setOpAndDefaultFlags(CompareStrictEq);
3800 return;
3801 }
3802 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
3803 fixEdge<StringIdentUse>(node->child1());
3804 fixEdge<StringIdentUse>(node->child2());
3805 node->setOpAndDefaultFlags(CompareStrictEq);
3806 return;
3807 }
3808 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 7) || m_graph.m_plan.isFTL())) {
3809 fixEdge<StringUse>(node->child1());
3810 fixEdge<StringUse>(node->child2());
3811 node->setOpAndDefaultFlags(CompareStrictEq);
3812 return;
3813 }
3814
3815 if (node->op() == SameValue) {
3816 if (node->child1()->shouldSpeculateObject()) {
3817 fixEdge<ObjectUse>(node->child1());
3818 node->setOpAndDefaultFlags(CompareStrictEq);
3819 return;
3820 }
3821 if (node->child2()->shouldSpeculateObject()) {
3822 fixEdge<ObjectUse>(node->child2());
3823 node->setOpAndDefaultFlags(CompareStrictEq);
3824 return;
3825 }
3826 } else {
3827 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
3828 if (masqueradesAsUndefinedWatchpoint->isStillValid()) {
3829 if (node->child1()->shouldSpeculateObject()) {
3830 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
3831 fixEdge<ObjectUse>(node->child1());
3832 return;
3833 }
3834 if (node->child2()->shouldSpeculateObject()) {
3835 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
3836 fixEdge<ObjectUse>(node->child2());
3837 return;
3838 }
3839 } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
3840 fixEdge<ObjectUse>(node->child1());
3841 fixEdge<ObjectUse>(node->child2());
3842 return;
3843 }
3844 }
3845
3846 if (node->child1()->shouldSpeculateSymbol()) {
3847 fixEdge<SymbolUse>(node->child1());
3848 node->setOpAndDefaultFlags(CompareStrictEq);
3849 return;
3850 }
3851 if (node->child2()->shouldSpeculateSymbol()) {
3852 fixEdge<SymbolUse>(node->child2());
3853 node->setOpAndDefaultFlags(CompareStrictEq);
3854 return;
3855 }
3856 if (node->child1()->shouldSpeculateMisc()) {
3857 fixEdge<MiscUse>(node->child1());
3858 node->setOpAndDefaultFlags(CompareStrictEq);
3859 return;
3860 }
3861 if (node->child2()->shouldSpeculateMisc()) {
3862 fixEdge<MiscUse>(node->child2());
3863 node->setOpAndDefaultFlags(CompareStrictEq);
3864 return;
3865 }
3866 if (node->child1()->shouldSpeculateStringIdent()
3867 && node->child2()->shouldSpeculateNotStringVar()) {
3868 fixEdge<StringIdentUse>(node->child1());
3869 fixEdge<NotStringVarUse>(node->child2());
3870 node->setOpAndDefaultFlags(CompareStrictEq);
3871 return;
3872 }
3873 if (node->child2()->shouldSpeculateStringIdent()
3874 && node->child1()->shouldSpeculateNotStringVar()) {
3875 fixEdge<StringIdentUse>(node->child2());
3876 fixEdge<NotStringVarUse>(node->child1());
3877 node->setOpAndDefaultFlags(CompareStrictEq);
3878 return;
3879 }
3880 if (node->child1()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || m_graph.m_plan.isFTL())) {
3881 fixEdge<StringUse>(node->child1());
3882 node->setOpAndDefaultFlags(CompareStrictEq);
3883 return;
3884 }
3885 if (node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || m_graph.m_plan.isFTL())) {
3886 fixEdge<StringUse>(node->child2());
3887 node->setOpAndDefaultFlags(CompareStrictEq);
3888 return;
3889 }
3890 }
3891
3892 void fixupChecksInBlock(BasicBlock* block)
3893 {
3894 if (!block)
3895 return;
3896 ASSERT(block->isReachable);
3897 m_block = block;
3898 unsigned indexForChecks = UINT_MAX;
3899 NodeOrigin originForChecks;
3900 for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
3901 Node* node = block->at(indexInBlock);
3902
3903 // If this is a node at which we could exit, then save its index. If nodes after this one
3904 // cannot exit, then we will hoist checks to here.
3905 if (node->origin.exitOK) {
3906 indexForChecks = indexInBlock;
3907 originForChecks = node->origin;
3908 }
3909
3910 originForChecks = originForChecks.withSemantic(node->origin.semantic);
3911
3912 // First, try to relax the representational demands of each node, in order to have
3913 // fewer conversions.
3914 switch (node->op()) {
3915 case MovHint:
3916 case Check:
3917 case CheckVarargs:
3918 m_graph.doToChildren(
3919 node,
3920 [&] (Edge& edge) {
3921 switch (edge.useKind()) {
3922 case DoubleRepUse:
3923 case DoubleRepRealUse:
3924 if (edge->hasDoubleResult())
3925 break;
3926
3927 if (edge->hasInt52Result())
3928 edge.setUseKind(Int52RepUse);
3929 else if (edge.useKind() == DoubleRepUse)
3930 edge.setUseKind(NumberUse);
3931 break;
3932
3933 case Int52RepUse:
3934 // Nothing we can really do.
3935 break;
3936
3937 case UntypedUse:
3938 case NumberUse:
3939 if (edge->hasDoubleResult())
3940 edge.setUseKind(DoubleRepUse);
3941 else if (edge->hasInt52Result())
3942 edge.setUseKind(Int52RepUse);
3943 break;
3944
3945 case RealNumberUse:
3946 if (edge->hasDoubleResult())
3947 edge.setUseKind(DoubleRepRealUse);
3948 else if (edge->hasInt52Result())
3949 edge.setUseKind(Int52RepUse);
3950 break;
3951
3952 default:
3953 break;
3954 }
3955 });
3956 break;
3957
3958 case ValueToInt32:
3959 if (node->child1().useKind() == DoubleRepUse
3960 && !node->child1()->hasDoubleResult()) {
3961 node->child1().setUseKind(NumberUse);
3962 break;
3963 }
3964 break;
3965
3966 default:
3967 break;
3968 }
3969
3970 // Now, insert type conversions if necessary.
3971 m_graph.doToChildren(
3972 node,
3973 [&] (Edge& edge) {
3974 Node* result = nullptr;
3975
3976 switch (edge.useKind()) {
3977 case DoubleRepUse:
3978 case DoubleRepRealUse:
3979 case DoubleRepAnyIntUse: {
3980 if (edge->hasDoubleResult())
3981 break;
3982
3983 ASSERT(indexForChecks != UINT_MAX);
3984 if (edge->isNumberConstant()) {
3985 result = m_insertionSet.insertNode(
3986 indexForChecks, SpecBytecodeDouble, DoubleConstant, originForChecks,
3987 OpInfo(m_graph.freeze(jsDoubleNumber(edge->asNumber()))));
3988 } else if (edge->hasInt52Result()) {
3989 result = m_insertionSet.insertNode(
3990 indexForChecks, SpecAnyIntAsDouble, DoubleRep, originForChecks,
3991 Edge(edge.node(), Int52RepUse));
3992 } else {
3993 UseKind useKind;
3994 if (edge->shouldSpeculateDoubleReal())
3995 useKind = RealNumberUse;
3996 else if (edge->shouldSpeculateNumber())
3997 useKind = NumberUse;
3998 else
3999 useKind = NotCellUse;
4000
4001 result = m_insertionSet.insertNode(
4002 indexForChecks, SpecBytecodeDouble, DoubleRep, originForChecks,
4003 Edge(edge.node(), useKind));
4004 }
4005
4006 edge.setNode(result);
4007 break;
4008 }
4009
4010 case Int52RepUse: {
4011 if (edge->hasInt52Result())
4012 break;
4013
4014 ASSERT(indexForChecks != UINT_MAX);
4015 if (edge->isAnyIntConstant()) {
4016 result = m_insertionSet.insertNode(
4017 indexForChecks, SpecInt52Any, Int52Constant, originForChecks,
4018 OpInfo(edge->constant()));
4019 } else if (edge->hasDoubleResult()) {
4020 result = m_insertionSet.insertNode(
4021 indexForChecks, SpecInt52Any, Int52Rep, originForChecks,
4022 Edge(edge.node(), DoubleRepAnyIntUse));
4023 } else if (edge->shouldSpeculateInt32ForArithmetic()) {
4024 result = m_insertionSet.insertNode(
4025 indexForChecks, SpecInt32Only, Int52Rep, originForChecks,
4026 Edge(edge.node(), Int32Use));
4027 } else {
4028 result = m_insertionSet.insertNode(
4029 indexForChecks, SpecInt52Any, Int52Rep, originForChecks,
4030 Edge(edge.node(), AnyIntUse));
4031 }
4032
4033 edge.setNode(result);
4034 break;
4035 }
4036
4037 default: {
4038 if (!edge->hasDoubleResult() && !edge->hasInt52Result())
4039 break;
4040
4041 ASSERT(indexForChecks != UINT_MAX);
4042 if (edge->hasDoubleResult()) {
4043 result = m_insertionSet.insertNode(
4044 indexForChecks, SpecBytecodeDouble, ValueRep, originForChecks,
4045 Edge(edge.node(), DoubleRepUse));
4046 } else {
4047 result = m_insertionSet.insertNode(
4048 indexForChecks, SpecInt32Only | SpecAnyIntAsDouble, ValueRep,
4049 originForChecks, Edge(edge.node(), Int52RepUse));
4050 }
4051
4052 edge.setNode(result);
4053 break;
4054 } }
4055
4056 // It's remotely possible that this node cannot do type checks, but we now have a
4057 // type check on this node. We don't have to handle the general form of this
4058 // problem. It only arises when ByteCodeParser emits an immediate SetLocal, rather
4059 // than a delayed one. So, we only worry about those checks that we may have put on
4060 // a SetLocal. Note that "indexForChecks != indexInBlock" is just another way of
4061 // saying "!node->origin.exitOK".
4062 if (indexForChecks != indexInBlock && mayHaveTypeCheck(edge.useKind())) {
4063 UseKind knownUseKind;
4064
4065 switch (edge.useKind()) {
4066 case Int32Use:
4067 knownUseKind = KnownInt32Use;
4068 break;
4069 case CellUse:
4070 knownUseKind = KnownCellUse;
4071 break;
4072 case BooleanUse:
4073 knownUseKind = KnownBooleanUse;
4074 break;
4075 default:
4076 // This can only arise if we have a Check node, and in that case, we can
4077 // just remove the original check.
4078 DFG_ASSERT(m_graph, node, node->op() == Check, node->op(), edge.useKind());
4079 knownUseKind = UntypedUse;
4080 break;
4081 }
4082
4083 ASSERT(indexForChecks != UINT_MAX);
4084 m_insertionSet.insertNode(
4085 indexForChecks, SpecNone, Check, originForChecks, edge);
4086
4087 edge.setUseKind(knownUseKind);
4088 }
4089 });
4090 }
4091
4092 m_insertionSet.execute(block);
4093 }
4094
4095 BasicBlock* m_block;
4096 unsigned m_indexInBlock;
4097 Node* m_currentNode;
4098 InsertionSet m_insertionSet;
4099 bool m_profitabilityChanged;
4100};
4101
4102bool performFixup(Graph& graph)
4103{
4104 return runPhase<FixupPhase>(graph);
4105}
4106
4107} } // namespace JSC::DFG
4108
4109#endif // ENABLE(DFG_JIT)
4110
4111