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