2 * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGFixupPhase.h"
31 #include "ArrayPrototype.h"
33 #include "DFGInferredTypeCheck.h"
34 #include "DFGInsertionSet.h"
36 #include "DFGPredictionPropagationPhase.h"
37 #include "DFGVariableAccessDataDump.h"
38 #include "JSCInlines.h"
39 #include "TypeLocation.h"
41 namespace JSC { namespace DFG {
43 class FixupPhase : public Phase {
45 FixupPhase(Graph& graph)
46 : Phase(graph, "fixup")
47 , m_insertionSet(graph)
53 ASSERT(m_graph.m_fixpointState == BeforeFixpoint);
54 ASSERT(m_graph.m_form == ThreadedCPS);
56 m_profitabilityChanged = false;
57 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
58 fixupBlock(m_graph.block(blockIndex));
60 while (m_profitabilityChanged) {
61 m_profitabilityChanged = false;
63 for (unsigned i = m_graph.m_argumentPositions.size(); i--;)
64 m_graph.m_argumentPositions[i].mergeArgumentUnboxingAwareness();
66 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
67 fixupGetAndSetLocalsInBlock(m_graph.block(blockIndex));
70 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
71 fixupChecksInBlock(m_graph.block(blockIndex));
73 m_graph.m_planStage = PlanStage::AfterFixup;
79 void fixupBlock(BasicBlock* block)
83 ASSERT(block->isReachable);
85 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
86 m_currentNode = block->at(m_indexInBlock);
87 fixupNode(m_currentNode);
89 m_insertionSet.execute(block);
92 void fixupNode(Node* node)
94 NodeType op = node->op();
98 // This gets handled by fixupGetAndSetLocalsInBlock().
108 if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())) {
109 fixEdge<UntypedUse>(node->child1());
110 fixEdge<UntypedUse>(node->child2());
113 fixIntConvertingEdge(node->child1());
114 fixIntConvertingEdge(node->child2());
119 fixIntConvertingEdge(node->child1());
120 fixIntConvertingEdge(node->child2());
121 node->setOp(ArithMul);
122 node->setArithMode(Arith::Unchecked);
123 node->child1().setUseKind(Int32Use);
124 node->child2().setUseKind(Int32Use);
129 if (node->child1()->shouldSpeculateNotCell()) {
130 fixIntConvertingEdge(node->child1());
131 node->clearFlags(NodeMustGenerate);
133 fixEdge<UntypedUse>(node->child1());
137 case UInt32ToNumber: {
138 fixIntConvertingEdge(node->child1());
139 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
140 node->convertToIdentity();
141 else if (node->canSpeculateInt32(FixupPass))
142 node->setArithMode(Arith::CheckOverflow);
144 node->setArithMode(Arith::DoOverflow);
145 node->clearFlags(NodeMustGenerate);
146 node->setResult(enableInt52() ? NodeResultInt52 : NodeResultDouble);
152 if (attemptToMakeIntegerAdd(node)) {
153 node->setOp(ArithAdd);
156 if (Node::shouldSpeculateNumberOrBooleanExpectingDefined(node->child1().node(), node->child2().node())) {
157 fixDoubleOrBooleanEdge(node->child1());
158 fixDoubleOrBooleanEdge(node->child2());
159 node->setOp(ArithAdd);
160 node->setResult(NodeResultDouble);
164 if (attemptToMakeFastStringAdd(node))
167 fixEdge<UntypedUse>(node->child1());
168 fixEdge<UntypedUse>(node->child2());
169 node->setResult(NodeResultJS);
174 if (attemptToMakeFastStringAdd(node))
177 // FIXME: Remove empty string arguments and possibly turn this into a ToString operation. That
178 // would require a form of ToString that takes a KnownPrimitiveUse. This is necessary because
179 // the implementation of StrCat doesn't dynamically optimize for empty strings.
180 // https://bugs.webkit.org/show_bug.cgi?id=148540
181 m_graph.doToChildren(
184 fixEdge<KnownPrimitiveUse>(edge);
197 && Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
198 fixEdge<UntypedUse>(node->child1());
199 fixEdge<UntypedUse>(node->child2());
200 node->setResult(NodeResultJS);
203 if (attemptToMakeIntegerAdd(node))
205 fixDoubleOrBooleanEdge(node->child1());
206 fixDoubleOrBooleanEdge(node->child2());
207 node->setResult(NodeResultDouble);
212 if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
213 fixIntOrBooleanEdge(node->child1());
214 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
215 node->setArithMode(Arith::Unchecked);
216 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
217 node->setArithMode(Arith::CheckOverflow);
219 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
222 if (m_graph.unaryArithShouldSpeculateAnyInt(node, FixupPass)) {
223 fixEdge<Int52RepUse>(node->child1());
224 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
225 node->setArithMode(Arith::CheckOverflow);
227 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
228 node->setResult(NodeResultInt52);
231 fixDoubleOrBooleanEdge(node->child1());
232 node->setResult(NodeResultDouble);
237 Edge& leftChild = node->child1();
238 Edge& rightChild = node->child2();
239 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) {
240 fixEdge<UntypedUse>(leftChild);
241 fixEdge<UntypedUse>(rightChild);
242 node->setResult(NodeResultJS);
245 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
246 fixIntOrBooleanEdge(leftChild);
247 fixIntOrBooleanEdge(rightChild);
248 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
249 node->setArithMode(Arith::Unchecked);
250 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())
251 || leftChild.node() == rightChild.node())
252 node->setArithMode(Arith::CheckOverflow);
254 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
257 if (m_graph.binaryArithShouldSpeculateAnyInt(node, FixupPass)) {
258 fixEdge<Int52RepUse>(leftChild);
259 fixEdge<Int52RepUse>(rightChild);
260 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())
261 || leftChild.node() == rightChild.node())
262 node->setArithMode(Arith::CheckOverflow);
264 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
265 node->setResult(NodeResultInt52);
268 fixDoubleOrBooleanEdge(leftChild);
269 fixDoubleOrBooleanEdge(rightChild);
270 node->setResult(NodeResultDouble);
276 Edge& leftChild = node->child1();
277 Edge& rightChild = node->child2();
279 && Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())
280 && m_graph.hasExitSite(node->origin.semantic, BadType)) {
281 fixEdge<UntypedUse>(leftChild);
282 fixEdge<UntypedUse>(rightChild);
283 node->setResult(NodeResultJS);
286 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
287 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) {
288 fixIntOrBooleanEdge(leftChild);
289 fixIntOrBooleanEdge(rightChild);
290 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
291 node->setArithMode(Arith::Unchecked);
292 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
293 node->setArithMode(Arith::CheckOverflow);
295 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
299 // This will cause conversion nodes to be inserted later.
300 fixDoubleOrBooleanEdge(leftChild);
301 fixDoubleOrBooleanEdge(rightChild);
303 // We don't need to do ref'ing on the children because we're stealing them from
304 // the original division.
305 Node* newDivision = m_insertionSet.insertNode(
306 m_indexInBlock, SpecBytecodeDouble, *node);
307 newDivision->setResult(NodeResultDouble);
309 node->setOp(DoubleAsInt32);
310 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
311 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
312 node->setArithMode(Arith::CheckOverflow);
314 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
317 fixDoubleOrBooleanEdge(leftChild);
318 fixDoubleOrBooleanEdge(rightChild);
319 node->setResult(NodeResultDouble);
325 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
326 fixIntOrBooleanEdge(node->child1());
327 fixIntOrBooleanEdge(node->child2());
330 fixDoubleOrBooleanEdge(node->child1());
331 fixDoubleOrBooleanEdge(node->child2());
332 node->setResult(NodeResultDouble);
337 if (node->child1()->shouldSpeculateInt32OrBoolean()
338 && node->canSpeculateInt32(FixupPass)) {
339 fixIntOrBooleanEdge(node->child1());
340 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
341 node->setArithMode(Arith::Unchecked);
343 node->setArithMode(Arith::CheckOverflow);
344 node->clearFlags(NodeMustGenerate);
345 node->setResult(NodeResultInt32);
349 if (node->child1()->shouldSpeculateNotCell()) {
350 fixDoubleOrBooleanEdge(node->child1());
351 node->clearFlags(NodeMustGenerate);
353 fixEdge<UntypedUse>(node->child1());
354 node->setResult(NodeResultDouble);
359 if (node->child2()->shouldSpeculateInt32OrBooleanForArithmetic()) {
360 fixDoubleOrBooleanEdge(node->child1());
361 fixIntOrBooleanEdge(node->child2());
365 fixDoubleOrBooleanEdge(node->child1());
366 fixDoubleOrBooleanEdge(node->child2());
371 node->setResult(NodeResultDouble);
379 if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
380 fixIntOrBooleanEdge(node->child1());
381 insertCheck<Int32Use>(m_indexInBlock, node->child1().node());
382 node->convertToIdentity();
385 fixDoubleOrBooleanEdge(node->child1());
387 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
388 node->setResult(NodeResultInt32);
389 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
390 node->setArithRoundingMode(Arith::RoundingMode::Int32);
392 node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
394 node->setResult(NodeResultDouble);
395 node->setArithRoundingMode(Arith::RoundingMode::Double);
405 Edge& child1 = node->child1();
406 if (child1->shouldSpeculateNotCell()) {
407 fixDoubleOrBooleanEdge(child1);
408 node->clearFlags(NodeMustGenerate);
410 fixEdge<UntypedUse>(child1);
415 if (node->child1()->shouldSpeculateBoolean()) {
416 if (node->child1()->result() == NodeResultBoolean) {
417 // This is necessary in case we have a bytecode instruction implemented by:
422 // In that case, CompareEq might have a side-effect. Then, we need to make
423 // sure that we know that Branch does not exit.
424 fixEdge<KnownBooleanUse>(node->child1());
426 fixEdge<BooleanUse>(node->child1());
427 } else if (node->child1()->shouldSpeculateObjectOrOther())
428 fixEdge<ObjectOrOtherUse>(node->child1());
429 else if (node->child1()->shouldSpeculateInt32OrBoolean())
430 fixIntOrBooleanEdge(node->child1());
431 else if (node->child1()->shouldSpeculateNumber())
432 fixEdge<DoubleRepUse>(node->child1());
433 else if (node->child1()->shouldSpeculateString())
434 fixEdge<StringUse>(node->child1());
435 else if (node->child1()->shouldSpeculateStringOrOther())
436 fixEdge<StringOrOtherUse>(node->child1());
444 case CompareGreaterEq: {
445 if (node->op() == CompareEq
446 && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
447 fixEdge<BooleanUse>(node->child1());
448 fixEdge<BooleanUse>(node->child2());
449 node->clearFlags(NodeMustGenerate);
452 if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
453 fixIntOrBooleanEdge(node->child1());
454 fixIntOrBooleanEdge(node->child2());
455 node->clearFlags(NodeMustGenerate);
459 && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
460 fixEdge<Int52RepUse>(node->child1());
461 fixEdge<Int52RepUse>(node->child2());
462 node->clearFlags(NodeMustGenerate);
465 if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
466 fixDoubleOrBooleanEdge(node->child1());
467 fixDoubleOrBooleanEdge(node->child2());
469 if (node->op() != CompareEq
470 && node->child1()->shouldSpeculateNotCell()
471 && node->child2()->shouldSpeculateNotCell()) {
472 if (node->child1()->shouldSpeculateNumberOrBoolean())
473 fixDoubleOrBooleanEdge(node->child1());
475 fixEdge<DoubleRepUse>(node->child1());
476 if (node->child2()->shouldSpeculateNumberOrBoolean())
477 fixDoubleOrBooleanEdge(node->child2());
479 fixEdge<DoubleRepUse>(node->child2());
480 node->clearFlags(NodeMustGenerate);
483 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
484 fixEdge<StringIdentUse>(node->child1());
485 fixEdge<StringIdentUse>(node->child2());
486 node->clearFlags(NodeMustGenerate);
489 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
490 fixEdge<StringUse>(node->child1());
491 fixEdge<StringUse>(node->child2());
492 node->clearFlags(NodeMustGenerate);
496 if (node->op() != CompareEq)
498 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
499 fixEdge<SymbolUse>(node->child1());
500 fixEdge<SymbolUse>(node->child2());
501 node->clearFlags(NodeMustGenerate);
504 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
505 fixEdge<ObjectUse>(node->child1());
506 fixEdge<ObjectUse>(node->child2());
507 node->clearFlags(NodeMustGenerate);
511 // If either child can be proved to be Null or Undefined, comparing them is greatly simplified.
512 bool oneArgumentIsUsedAsSpecOther = false;
513 if (node->child1()->isUndefinedOrNullConstant()) {
514 fixEdge<OtherUse>(node->child1());
515 oneArgumentIsUsedAsSpecOther = true;
516 } else if (node->child1()->shouldSpeculateOther()) {
517 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
518 Edge(node->child1().node(), OtherUse));
519 fixEdge<OtherUse>(node->child1());
520 oneArgumentIsUsedAsSpecOther = true;
522 if (node->child2()->isUndefinedOrNullConstant()) {
523 fixEdge<OtherUse>(node->child2());
524 oneArgumentIsUsedAsSpecOther = true;
525 } else if (node->child2()->shouldSpeculateOther()) {
526 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
527 Edge(node->child2().node(), OtherUse));
528 fixEdge<OtherUse>(node->child2());
529 oneArgumentIsUsedAsSpecOther = true;
531 if (oneArgumentIsUsedAsSpecOther) {
532 node->clearFlags(NodeMustGenerate);
536 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
537 fixEdge<ObjectUse>(node->child1());
538 fixEdge<ObjectOrOtherUse>(node->child2());
539 node->clearFlags(NodeMustGenerate);
542 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
543 fixEdge<ObjectOrOtherUse>(node->child1());
544 fixEdge<ObjectUse>(node->child2());
545 node->clearFlags(NodeMustGenerate);
552 case CompareStrictEq: {
553 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
554 fixEdge<BooleanUse>(node->child1());
555 fixEdge<BooleanUse>(node->child2());
558 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
559 fixEdge<Int32Use>(node->child1());
560 fixEdge<Int32Use>(node->child2());
564 && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
565 fixEdge<Int52RepUse>(node->child1());
566 fixEdge<Int52RepUse>(node->child2());
569 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
570 fixEdge<DoubleRepUse>(node->child1());
571 fixEdge<DoubleRepUse>(node->child2());
574 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
575 fixEdge<SymbolUse>(node->child1());
576 fixEdge<SymbolUse>(node->child2());
579 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
580 fixEdge<StringIdentUse>(node->child1());
581 fixEdge<StringIdentUse>(node->child2());
584 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 7) || isFTL(m_graph.m_plan.mode))) {
585 fixEdge<StringUse>(node->child1());
586 fixEdge<StringUse>(node->child2());
589 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
590 if (masqueradesAsUndefinedWatchpoint->isStillValid()) {
592 if (node->child1()->shouldSpeculateObject()) {
593 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
594 fixEdge<ObjectUse>(node->child1());
597 if (node->child2()->shouldSpeculateObject()) {
598 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
599 fixEdge<ObjectUse>(node->child2());
603 } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
604 fixEdge<ObjectUse>(node->child1());
605 fixEdge<ObjectUse>(node->child2());
608 if (node->child1()->shouldSpeculateSymbol()) {
609 fixEdge<SymbolUse>(node->child1());
612 if (node->child2()->shouldSpeculateSymbol()) {
613 fixEdge<SymbolUse>(node->child2());
616 if (node->child1()->shouldSpeculateMisc()) {
617 fixEdge<MiscUse>(node->child1());
620 if (node->child2()->shouldSpeculateMisc()) {
621 fixEdge<MiscUse>(node->child2());
624 if (node->child1()->shouldSpeculateStringIdent()
625 && node->child2()->shouldSpeculateNotStringVar()) {
626 fixEdge<StringIdentUse>(node->child1());
627 fixEdge<NotStringVarUse>(node->child2());
630 if (node->child2()->shouldSpeculateStringIdent()
631 && node->child1()->shouldSpeculateNotStringVar()) {
632 fixEdge<StringIdentUse>(node->child2());
633 fixEdge<NotStringVarUse>(node->child1());
636 if (node->child1()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
637 fixEdge<StringUse>(node->child1());
640 if (node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
641 fixEdge<StringUse>(node->child2());
647 case StringFromCharCode:
648 if (node->child1()->shouldSpeculateInt32())
649 fixEdge<Int32Use>(node->child1());
651 fixEdge<UntypedUse>(node->child1());
655 case StringCharCodeAt: {
656 // Currently we have no good way of refining these.
657 ASSERT(node->arrayMode() == ArrayMode(Array::String));
658 blessArrayOperation(node->child1(), node->child2(), node->child3());
659 fixEdge<KnownCellUse>(node->child1());
660 fixEdge<Int32Use>(node->child2());
665 if (!node->prediction()) {
666 m_insertionSet.insertNode(
667 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
671 node->arrayMode().refine(
673 node->child1()->prediction(),
674 node->child2()->prediction(),
677 blessArrayOperation(node->child1(), node->child2(), node->child3());
679 ArrayMode arrayMode = node->arrayMode();
680 switch (arrayMode.type()) {
681 case Array::Contiguous:
683 if (arrayMode.arrayClass() == Array::OriginalArray
684 && arrayMode.speculation() == Array::InBounds) {
685 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
686 if (globalObject->arrayPrototypeChainIsSane()) {
687 // Check if SaneChain will work on a per-type basis. Note that:
689 // 1) We don't want double arrays to sometimes return undefined, since
690 // that would require a change to the return type and it would pessimise
691 // things a lot. So, we'd only want to do that if we actually had
692 // evidence that we could read from a hole. That's pretty annoying.
693 // Likely the best way to handle that case is with an equivalent of
694 // SaneChain for OutOfBounds. For now we just detect when Undefined and
695 // NaN are indistinguishable according to backwards propagation, and just
696 // use SaneChain in that case. This happens to catch a lot of cases.
698 // 2) We don't want int32 array loads to have to do a hole check just to
699 // coerce to Undefined, since that would mean twice the checks.
701 // This has two implications. First, we have to do more checks than we'd
702 // like. It's unfortunate that we have to do the hole check. Second,
703 // some accesses that hit a hole will now need to take the full-blown
704 // out-of-bounds slow path. We can fix that with:
705 // https://bugs.webkit.org/show_bug.cgi?id=144668
707 bool canDoSaneChain = false;
708 switch (arrayMode.type()) {
709 case Array::Contiguous:
710 // This is happens to be entirely natural. We already would have
711 // returned any JSValue, and now we'll return Undefined. We still do
712 // the check but it doesn't require taking any kind of slow path.
713 canDoSaneChain = true;
717 if (!(node->flags() & NodeBytecodeUsesAsOther)) {
718 // Holes look like NaN already, so if the user doesn't care
719 // about the difference between Undefined and NaN then we can
721 canDoSaneChain = true;
729 if (canDoSaneChain) {
730 m_graph.watchpoints().addLazily(
731 globalObject->arrayPrototype()->structure()->transitionWatchpointSet());
732 m_graph.watchpoints().addLazily(
733 globalObject->objectPrototype()->structure()->transitionWatchpointSet());
734 if (globalObject->arrayPrototypeChainIsSane())
735 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
742 if ((node->prediction() & ~SpecString)
743 || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
744 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
751 arrayMode = node->arrayMode();
752 switch (arrayMode.type()) {
753 case Array::SelectUsingPredictions:
754 case Array::Unprofiled:
755 RELEASE_ASSERT_NOT_REACHED();
758 #if USE(JSVALUE32_64)
759 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
762 case Array::ForceExit:
765 fixEdge<KnownCellUse>(node->child1());
766 fixEdge<Int32Use>(node->child2());
770 switch (arrayMode.type()) {
772 if (!arrayMode.isOutOfBounds())
773 node->setResult(NodeResultDouble);
776 case Array::Float32Array:
777 case Array::Float64Array:
778 node->setResult(NodeResultDouble);
781 case Array::Uint32Array:
782 if (node->shouldSpeculateInt32())
784 if (node->shouldSpeculateAnyInt() && enableInt52())
785 node->setResult(NodeResultInt52);
787 node->setResult(NodeResultDouble);
799 case PutByValAlias: {
800 Edge& child1 = m_graph.varArgChild(node, 0);
801 Edge& child2 = m_graph.varArgChild(node, 1);
802 Edge& child3 = m_graph.varArgChild(node, 2);
805 node->arrayMode().refine(
807 child1->prediction(),
808 child2->prediction(),
809 child3->prediction()));
811 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
813 switch (node->arrayMode().modeForPut().type()) {
814 case Array::SelectUsingPredictions:
815 case Array::SelectUsingArguments:
816 case Array::Unprofiled:
817 case Array::Undecided:
818 RELEASE_ASSERT_NOT_REACHED();
820 case Array::ForceExit:
822 #if USE(JSVALUE32_64)
823 // Due to register pressure on 32-bit, we speculate cell and
824 // ignore the base-is-not-cell case entirely by letting the
825 // baseline JIT handle it.
826 fixEdge<CellUse>(child1);
830 fixEdge<KnownCellUse>(child1);
831 fixEdge<Int32Use>(child2);
832 fixEdge<Int32Use>(child3);
835 fixEdge<KnownCellUse>(child1);
836 fixEdge<Int32Use>(child2);
837 fixEdge<DoubleRepRealUse>(child3);
839 case Array::Int8Array:
840 case Array::Int16Array:
841 case Array::Int32Array:
842 case Array::Uint8Array:
843 case Array::Uint8ClampedArray:
844 case Array::Uint16Array:
845 case Array::Uint32Array:
846 fixEdge<KnownCellUse>(child1);
847 fixEdge<Int32Use>(child2);
848 if (child3->shouldSpeculateInt32())
849 fixIntOrBooleanEdge(child3);
850 else if (child3->shouldSpeculateAnyInt())
851 fixEdge<Int52RepUse>(child3);
853 fixDoubleOrBooleanEdge(child3);
855 case Array::Float32Array:
856 case Array::Float64Array:
857 fixEdge<KnownCellUse>(child1);
858 fixEdge<Int32Use>(child2);
859 fixDoubleOrBooleanEdge(child3);
861 case Array::Contiguous:
862 case Array::ArrayStorage:
863 case Array::SlowPutArrayStorage:
864 fixEdge<KnownCellUse>(child1);
865 fixEdge<Int32Use>(child2);
866 speculateForBarrier(child3);
869 fixEdge<KnownCellUse>(child1);
870 fixEdge<Int32Use>(child2);
877 // May need to refine the array mode in case the value prediction contravenes
878 // the array prediction. For example, we may have evidence showing that the
879 // array is in Int32 mode, but the value we're storing is likely to be a double.
880 // Then we should turn this into a conversion to Double array followed by the
881 // push. On the other hand, we absolutely don't want to refine based on the
882 // base prediction. If it has non-cell garbage in it, then we want that to be
883 // ignored. That's because ArrayPush can't handle any array modes that aren't
884 // array-related - so if refine() turned this into a "Generic" ArrayPush then
885 // that would break things.
887 node->arrayMode().refine(
889 node->child1()->prediction() & SpecCell,
891 node->child2()->prediction()));
892 blessArrayOperation(node->child1(), Edge(), node->child3());
893 fixEdge<KnownCellUse>(node->child1());
895 switch (node->arrayMode().type()) {
897 fixEdge<Int32Use>(node->child2());
900 fixEdge<DoubleRepRealUse>(node->child2());
902 case Array::Contiguous:
903 case Array::ArrayStorage:
904 speculateForBarrier(node->child2());
913 blessArrayOperation(node->child1(), Edge(), node->child2());
914 fixEdge<KnownCellUse>(node->child1());
920 fixEdge<KnownCellUse>(node->child1());
922 if (node->child2()->shouldSpeculateRegExpObject()) {
923 fixEdge<RegExpObjectUse>(node->child2());
925 if (node->child3()->shouldSpeculateString())
926 fixEdge<StringUse>(node->child3());
932 case StringReplaceRegExp: {
933 if (node->child2()->shouldSpeculateString()) {
934 m_insertionSet.insertNode(
935 m_indexInBlock, SpecNone, Check, node->origin,
936 Edge(node->child2().node(), StringUse));
937 fixEdge<StringUse>(node->child2());
938 } else if (op == StringReplace) {
939 if (node->child2()->shouldSpeculateRegExpObject())
940 addStringReplacePrimordialChecks(node->child2().node());
942 m_insertionSet.insertNode(
943 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
946 if (node->child1()->shouldSpeculateString()
947 && node->child2()->shouldSpeculateRegExpObject()
948 && node->child3()->shouldSpeculateString()) {
950 fixEdge<StringUse>(node->child1());
951 fixEdge<RegExpObjectUse>(node->child2());
952 fixEdge<StringUse>(node->child3());
959 if (node->child1()->shouldSpeculateBoolean()) {
960 if (node->child1()->result() == NodeResultBoolean) {
961 // This is necessary in case we have a bytecode instruction implemented by:
966 // In that case, CompareEq might have a side-effect. Then, we need to make
967 // sure that we know that Branch does not exit.
968 fixEdge<KnownBooleanUse>(node->child1());
970 fixEdge<BooleanUse>(node->child1());
971 } else if (node->child1()->shouldSpeculateObjectOrOther())
972 fixEdge<ObjectOrOtherUse>(node->child1());
973 else if (node->child1()->shouldSpeculateInt32OrBoolean())
974 fixIntOrBooleanEdge(node->child1());
975 else if (node->child1()->shouldSpeculateNumber())
976 fixEdge<DoubleRepUse>(node->child1());
977 else if (node->child1()->shouldSpeculateString())
978 fixEdge<StringUse>(node->child1());
979 else if (node->child1()->shouldSpeculateStringOrOther())
980 fixEdge<StringOrOtherUse>(node->child1());
985 SwitchData* data = node->switchData();
986 switch (data->kind) {
988 if (node->child1()->shouldSpeculateInt32())
989 fixEdge<Int32Use>(node->child1());
992 if (node->child1()->shouldSpeculateString())
993 fixEdge<StringUse>(node->child1());
996 if (node->child1()->shouldSpeculateStringIdent())
997 fixEdge<StringIdentUse>(node->child1());
998 else if (node->child1()->shouldSpeculateString())
999 fixEdge<StringUse>(node->child1());
1002 if (node->child1()->shouldSpeculateCell())
1003 fixEdge<CellUse>(node->child1());
1004 // else it's fine for this to have UntypedUse; we will handle this by just making
1005 // non-cells take the default case.
1012 fixupToPrimitive(node);
1017 fixupToNumber(node);
1022 case CallStringConstructor: {
1023 fixupToStringOrCallStringConstructor(node);
1027 case NewStringObject: {
1028 fixEdge<KnownStringUse>(node->child1());
1033 watchHavingABadTime(node);
1035 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
1036 node->setIndexingType(
1037 leastUpperBoundOfIndexingTypeAndType(
1038 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
1040 switch (node->indexingType()) {
1041 case ALL_BLANK_INDEXING_TYPES:
1044 case ALL_UNDECIDED_INDEXING_TYPES:
1045 if (node->numChildren()) {
1046 // This will only happen if the children have no type predictions. We
1047 // would have already exited by now, but insert a forced exit just to
1049 m_insertionSet.insertNode(
1050 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
1053 case ALL_INT32_INDEXING_TYPES:
1054 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1055 fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1057 case ALL_DOUBLE_INDEXING_TYPES:
1058 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1059 fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1061 case ALL_CONTIGUOUS_INDEXING_TYPES:
1062 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
1071 case NewTypedArray: {
1072 watchHavingABadTime(node);
1074 if (node->child1()->shouldSpeculateInt32()) {
1075 fixEdge<Int32Use>(node->child1());
1076 node->clearFlags(NodeMustGenerate);
1082 case NewArrayWithSize: {
1083 watchHavingABadTime(node);
1084 fixEdge<Int32Use>(node->child1());
1088 case CallObjectConstructor: {
1089 if (node->child1()->shouldSpeculateObject()) {
1090 fixEdge<ObjectUse>(node->child1());
1091 node->convertToIdentity();
1095 fixEdge<UntypedUse>(node->child1());
1104 case PutStructure: {
1105 fixEdge<KnownCellUse>(node->child1());
1110 case GetFromArguments: {
1111 fixEdge<KnownCellUse>(node->child1());
1116 case PutToArguments: {
1117 fixEdge<KnownCellUse>(node->child1());
1118 speculateForBarrier(node->child2());
1126 case GetGlobalObject: {
1127 fixEdge<KnownCellUse>(node->child1());
1131 case AllocatePropertyStorage:
1132 case ReallocatePropertyStorage: {
1133 fixEdge<KnownCellUse>(node->child1());
1138 if (node->child1()->shouldSpeculateCell())
1139 fixEdge<CellUse>(node->child1());
1144 case GetByIdFlush: {
1145 // FIXME: This should be done in the ByteCodeParser based on reading the
1146 // PolymorphicAccess, which will surely tell us that this is a AccessCase::ArrayLength.
1147 // https://bugs.webkit.org/show_bug.cgi?id=154990
1148 if (node->child1()->shouldSpeculateCellOrOther()
1149 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1150 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1151 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1152 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1154 auto uid = m_graph.identifiers()[node->identifierNumber()];
1156 if (uid == vm().propertyNames->length.impl()) {
1157 attemptToMakeGetArrayLength(node);
1161 if (uid == vm().propertyNames->lastIndex.impl()
1162 && node->child1()->shouldSpeculateRegExpObject()) {
1163 node->setOp(GetRegExpObjectLastIndex);
1164 node->clearFlags(NodeMustGenerate);
1165 fixEdge<RegExpObjectUse>(node->child1());
1170 if (node->child1()->shouldSpeculateCell())
1171 fixEdge<CellUse>(node->child1());
1177 case PutByIdDirect: {
1178 if (node->child1()->shouldSpeculateCellOrOther()
1179 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1180 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1181 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1182 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1184 auto uid = m_graph.identifiers()[node->identifierNumber()];
1186 if (uid == vm().propertyNames->lastIndex.impl()
1187 && node->child1()->shouldSpeculateRegExpObject()) {
1188 node->setOp(SetRegExpObjectLastIndex);
1189 fixEdge<RegExpObjectUse>(node->child1());
1190 speculateForBarrier(node->child2());
1195 fixEdge<CellUse>(node->child1());
1200 case PutSetterById: {
1201 fixEdge<KnownCellUse>(node->child1());
1202 fixEdge<KnownCellUse>(node->child2());
1206 case PutGetterSetterById: {
1207 fixEdge<KnownCellUse>(node->child1());
1211 case PutGetterByVal:
1212 case PutSetterByVal: {
1213 fixEdge<KnownCellUse>(node->child1());
1214 fixEdge<KnownCellUse>(node->child3());
1218 case GetExecutable: {
1219 fixEdge<FunctionUse>(node->child1());
1223 case OverridesHasInstance:
1224 case CheckStructure:
1227 case GetButterfly: {
1228 fixEdge<CellUse>(node->child1());
1232 case CheckStringIdent: {
1233 fixEdge<StringIdentUse>(node->child1());
1238 case ArrayifyToStructure: {
1239 fixEdge<CellUse>(node->child1());
1241 fixEdge<Int32Use>(node->child2());
1246 case GetGetterSetterByOffset: {
1247 if (!node->child1()->hasStorageResult())
1248 fixEdge<KnownCellUse>(node->child1());
1249 fixEdge<KnownCellUse>(node->child2());
1253 case MultiGetByOffset: {
1254 fixEdge<CellUse>(node->child1());
1259 if (!node->child1()->hasStorageResult())
1260 fixEdge<KnownCellUse>(node->child1());
1261 fixEdge<KnownCellUse>(node->child2());
1262 insertInferredTypeCheck(
1263 m_insertionSet, m_indexInBlock, node->origin, node->child3().node(),
1264 node->storageAccessData().inferredType);
1265 speculateForBarrier(node->child3());
1269 case MultiPutByOffset: {
1270 fixEdge<CellUse>(node->child1());
1271 speculateForBarrier(node->child2());
1276 if (!(node->child1()->prediction() & ~SpecCell))
1277 fixEdge<CellUse>(node->child1());
1278 fixEdge<CellUse>(node->child2());
1282 case InstanceOfCustom:
1283 fixEdge<CellUse>(node->child2());
1287 // FIXME: We should at some point have array profiling on op_in, in which
1288 // case we would be able to turn this into a kind of GetByVal.
1290 fixEdge<CellUse>(node->child2());
1295 m_graph.doToChildren(
1298 switch (edge.useKind()) {
1300 if (edge->shouldSpeculateInt32ForArithmetic())
1301 edge.setUseKind(Int32Use);
1306 observeUseKindOnEdge(edge);
1312 // Phantoms are meaningless past Fixup. We recreate them on-demand in the backend.
1317 RELEASE_ASSERT(enableInt52());
1318 node->convertToIdentity();
1319 fixEdge<Int52RepUse>(node->child1());
1320 node->setResult(NodeResultInt52);
1324 case GetArrayLength: {
1325 fixEdge<KnownCellUse>(node->child1());
1329 case GetTypedArrayByteOffset: {
1330 fixEdge<KnownCellUse>(node->child1());
1336 case GetIndexedPropertyStorage:
1338 case CheckTierUpInLoop:
1339 case CheckTierUpAtReturn:
1340 case CheckTierUpAndOSREnter:
1341 case InvalidationPoint:
1344 case ConstantStoragePointer:
1351 case Identity: // This should have been cleaned up.
1352 case BooleanToNumber:
1353 case PhantomNewObject:
1354 case PhantomNewFunction:
1355 case PhantomNewGeneratorFunction:
1356 case PhantomCreateActivation:
1357 case PhantomDirectArguments:
1358 case PhantomClonedArguments:
1359 case GetMyArgumentByVal:
1360 case GetMyArgumentByValOutOfBounds:
1362 case CheckStructureImmediate:
1363 case MaterializeNewObject:
1364 case MaterializeCreateActivation:
1369 case GetRegExpObjectLastIndex:
1370 case SetRegExpObjectLastIndex:
1371 case RecordRegExpCachedResult:
1372 // These are just nodes that we don't currently expect to see during fixup.
1373 // If we ever wanted to insert them prior to fixup, then we just have to create
1374 // fixup rules for them.
1375 DFG_CRASH(m_graph, node, "Unexpected node during fixup");
1378 case PutGlobalVariable: {
1379 fixEdge<CellUse>(node->child1());
1380 speculateForBarrier(node->child2());
1385 if (node->child1()->shouldSpeculateString()) {
1386 m_insertionSet.insertNode(
1387 m_indexInBlock, SpecNone, Check, node->origin,
1388 Edge(node->child1().node(), StringUse));
1389 m_graph.convertToConstant(node, jsBoolean(true));
1390 observeUseKindOnNode<StringUse>(node);
1395 if (node->child1()->shouldSpeculateObject()) {
1396 m_insertionSet.insertNode(
1397 m_indexInBlock, SpecNone, Check, node->origin,
1398 Edge(node->child1().node(), ObjectUse));
1399 m_graph.convertToConstant(node, jsBoolean(true));
1400 observeUseKindOnNode<ObjectUse>(node);
1404 case GetEnumerableLength: {
1405 fixEdge<CellUse>(node->child1());
1408 case HasGenericProperty: {
1409 fixEdge<CellUse>(node->child2());
1412 case HasStructureProperty: {
1413 fixEdge<StringUse>(node->child2());
1414 fixEdge<KnownCellUse>(node->child3());
1417 case HasIndexedProperty: {
1419 node->arrayMode().refine(
1421 node->child1()->prediction(),
1422 node->child2()->prediction(),
1425 blessArrayOperation(node->child1(), node->child2(), node->child3());
1426 fixEdge<CellUse>(node->child1());
1427 fixEdge<KnownInt32Use>(node->child2());
1430 case GetDirectPname: {
1431 Edge& base = m_graph.varArgChild(node, 0);
1432 Edge& property = m_graph.varArgChild(node, 1);
1433 Edge& index = m_graph.varArgChild(node, 2);
1434 Edge& enumerator = m_graph.varArgChild(node, 3);
1435 fixEdge<CellUse>(base);
1436 fixEdge<KnownCellUse>(property);
1437 fixEdge<KnownInt32Use>(index);
1438 fixEdge<KnownCellUse>(enumerator);
1441 case GetPropertyEnumerator: {
1442 fixEdge<CellUse>(node->child1());
1445 case GetEnumeratorStructurePname: {
1446 fixEdge<KnownCellUse>(node->child1());
1447 fixEdge<KnownInt32Use>(node->child2());
1450 case GetEnumeratorGenericPname: {
1451 fixEdge<KnownCellUse>(node->child1());
1452 fixEdge<KnownInt32Use>(node->child2());
1455 case ToIndexString: {
1456 fixEdge<KnownInt32Use>(node->child1());
1460 // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet.
1461 // Because the instructionTypeSet is contained in globalTypeSet, if we produce a type check for
1462 // type T for the instructionTypeSet, the global type set must also have information for type T.
1463 // So if it the type check succeeds for type T in the instructionTypeSet, a type check for type T
1464 // in the globalTypeSet would've also succeeded.
1465 // (The other direction does not hold in general).
1467 RefPtr<TypeSet> typeSet = node->typeLocation()->m_instructionTypeSet;
1468 RuntimeTypeMask seenTypes = typeSet->seenTypes();
1469 if (typeSet->doesTypeConformTo(TypeAnyInt)) {
1470 if (node->child1()->shouldSpeculateInt32()) {
1471 fixEdge<Int32Use>(node->child1());
1476 if (enableInt52()) {
1477 fixEdge<AnyIntUse>(node->child1());
1482 // Must not perform fixEdge<NumberUse> here since the type set only includes TypeAnyInt. Double values should be logged.
1485 if (typeSet->doesTypeConformTo(TypeNumber | TypeAnyInt)) {
1486 fixEdge<NumberUse>(node->child1());
1488 } else if (typeSet->doesTypeConformTo(TypeString)) {
1489 fixEdge<StringUse>(node->child1());
1491 } else if (typeSet->doesTypeConformTo(TypeBoolean)) {
1492 fixEdge<BooleanUse>(node->child1());
1494 } else if (typeSet->doesTypeConformTo(TypeUndefined | TypeNull) && (seenTypes & TypeUndefined) && (seenTypes & TypeNull)) {
1495 fixEdge<OtherUse>(node->child1());
1497 } else if (typeSet->doesTypeConformTo(TypeObject)) {
1500 ConcurrentJITLocker locker(typeSet->m_lock);
1501 set = typeSet->structureSet(locker);
1503 if (!set.isEmpty()) {
1504 fixEdge<CellUse>(node->child1());
1505 node->convertToCheckStructure(m_graph.addStructureSet(set));
1512 case CreateScopedArguments:
1513 case CreateActivation:
1515 case NewGeneratorFunction: {
1516 fixEdge<CellUse>(node->child1());
1520 case SetFunctionName: {
1521 // The first child is guaranteed to be a cell because op_set_function_name is only used
1522 // on a newly instantiated function object (the first child).
1523 fixEdge<KnownCellUse>(node->child1());
1524 fixEdge<UntypedUse>(node->child2());
1529 watchHavingABadTime(node);
1530 fixEdge<KnownInt32Use>(node->child1());
1536 case PutDynamicVar: {
1537 fixEdge<KnownCellUse>(node->child1());
1541 case LogShadowChickenPrologue: {
1542 fixEdge<KnownCellUse>(node->child1());
1545 case LogShadowChickenTail: {
1546 fixEdge<UntypedUse>(node->child1());
1547 fixEdge<KnownCellUse>(node->child2());
1551 #if !ASSERT_DISABLED
1552 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
1555 case LazyJSConstant:
1556 case DoubleConstant:
1559 case GetArgumentCountIncludingThis:
1563 case GetLocalUnlinked:
1565 case GetGlobalLexicalVariable:
1568 case CheckTypeInfoFlags:
1569 case TailCallInlinedCaller:
1573 case TailCallVarargsInlinedCaller:
1574 case ConstructVarargs:
1575 case CallForwardVarargs:
1576 case ConstructForwardVarargs:
1577 case TailCallForwardVarargs:
1578 case TailCallForwardVarargsInlinedCaller:
1580 case ForwardVarargs:
1581 case ProfileControlFlow:
1583 case NewArrayBuffer:
1588 case IsTypedArrayView:
1593 case IsObjectOrNull:
1595 case IsRegExpObject:
1596 case CreateDirectArguments:
1597 case CreateClonedArguments:
1601 case TailCallVarargs:
1603 case ThrowReferenceError:
1604 case CountExecution:
1608 case CheckWatchdogTimer:
1610 case ExtractOSREntryLocal:
1617 case GetByIdWithThis:
1618 case PutByIdWithThis:
1619 case PutByValWithThis:
1620 case GetByValWithThis:
1632 void watchHavingABadTime(Node* node)
1634 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1636 // If this global object is not having a bad time, watch it. We go down this path anytime the code
1637 // does an array allocation. The types of array allocations may change if we start to have a bad
1638 // time. It's easier to reason about this if we know that whenever the types change after we start
1639 // optimizing, the code just gets thrown out. Doing this at FixupPhase is just early enough, since
1640 // prior to this point nobody should have been doing optimizations based on the indexing type of
1642 if (!globalObject->isHavingABadTime())
1643 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1646 template<UseKind useKind>
1647 void createToString(Node* node, Edge& edge)
1649 edge.setNode(m_insertionSet.insertNode(
1650 m_indexInBlock, SpecString, ToString, node->origin,
1651 Edge(edge.node(), useKind)));
1654 template<UseKind useKind>
1655 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
1657 ASSERT(arrayMode == ArrayMode(Array::Generic));
1659 if (!m_graph.canOptimizeStringObjectAccess(node->origin.semantic))
1662 createToString<useKind>(node, node->child1());
1663 arrayMode = ArrayMode(Array::String);
1666 template<UseKind useKind>
1667 bool isStringObjectUse()
1670 case StringObjectUse:
1671 case StringOrStringObjectUse:
1678 template<UseKind useKind>
1679 void convertStringAddUse(Node* node, Edge& edge)
1681 if (useKind == StringUse) {
1682 observeUseKindOnNode<StringUse>(edge.node());
1683 m_insertionSet.insertNode(
1684 m_indexInBlock, SpecNone, Check, node->origin,
1685 Edge(edge.node(), StringUse));
1686 edge.setUseKind(KnownStringUse);
1690 observeUseKindOnNode<useKind>(edge.node());
1691 createToString<useKind>(node, edge);
1694 void convertToMakeRope(Node* node)
1696 node->setOpAndDefaultFlags(MakeRope);
1697 fixupMakeRope(node);
1700 void fixupMakeRope(Node* node)
1702 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1703 Edge& edge = node->children.child(i);
1706 edge.setUseKind(KnownStringUse);
1707 JSString* string = edge->dynamicCastConstant<JSString*>();
1710 if (string->length())
1713 // Don't allow the MakeRope to have zero children.
1714 if (!i && !node->child2())
1717 node->children.removeEdge(i--);
1720 if (!node->child2()) {
1721 ASSERT(!node->child3());
1722 node->convertToIdentity();
1726 void fixupToThis(Node* node)
1728 ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
1730 if (ecmaMode == StrictMode) {
1731 if (node->child1()->shouldSpeculateBoolean()) {
1732 fixEdge<BooleanUse>(node->child1());
1733 node->convertToIdentity();
1737 if (node->child1()->shouldSpeculateInt32()) {
1738 fixEdge<Int32Use>(node->child1());
1739 node->convertToIdentity();
1743 if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
1744 fixEdge<Int52RepUse>(node->child1());
1745 node->convertToIdentity();
1746 node->setResult(NodeResultInt52);
1750 if (node->child1()->shouldSpeculateNumber()) {
1751 fixEdge<DoubleRepUse>(node->child1());
1752 node->convertToIdentity();
1753 node->setResult(NodeResultDouble);
1757 if (node->child1()->shouldSpeculateSymbol()) {
1758 fixEdge<SymbolUse>(node->child1());
1759 node->convertToIdentity();
1763 if (node->child1()->shouldSpeculateStringIdent()) {
1764 fixEdge<StringIdentUse>(node->child1());
1765 node->convertToIdentity();
1769 if (node->child1()->shouldSpeculateString()) {
1770 fixEdge<StringUse>(node->child1());
1771 node->convertToIdentity();
1776 if (node->child1()->shouldSpeculateOther()) {
1777 if (ecmaMode == StrictMode) {
1778 fixEdge<OtherUse>(node->child1());
1779 node->convertToIdentity();
1783 m_insertionSet.insertNode(
1784 m_indexInBlock, SpecNone, Check, node->origin,
1785 Edge(node->child1().node(), OtherUse));
1786 observeUseKindOnNode<OtherUse>(node->child1().node());
1787 m_graph.convertToConstant(
1788 node, m_graph.globalThisObjectFor(node->origin.semantic));
1792 // FIXME: This should cover other use cases but we don't have use kinds for them. It's not critical,
1793 // however, since we cover all the missing cases in constant folding.
1794 // https://bugs.webkit.org/show_bug.cgi?id=157213
1795 if (node->child1()->shouldSpeculateStringObject()) {
1796 fixEdge<StringObjectUse>(node->child1());
1797 node->convertToIdentity();
1801 if (isFinalObjectSpeculation(node->child1()->prediction())) {
1802 fixEdge<FinalObjectUse>(node->child1());
1803 node->convertToIdentity();
1808 void fixupToPrimitive(Node* node)
1810 if (node->child1()->shouldSpeculateInt32()) {
1811 fixEdge<Int32Use>(node->child1());
1812 node->convertToIdentity();
1816 if (node->child1()->shouldSpeculateString()) {
1817 fixEdge<StringUse>(node->child1());
1818 node->convertToIdentity();
1822 if (node->child1()->shouldSpeculateStringObject()
1823 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1824 fixEdge<StringObjectUse>(node->child1());
1825 node->convertToToString();
1829 if (node->child1()->shouldSpeculateStringOrStringObject()
1830 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1831 fixEdge<StringOrStringObjectUse>(node->child1());
1832 node->convertToToString();
1837 void fixupToNumber(Node* node)
1839 // If the prediction of the child is Number, we attempt to convert ToNumber to Identity.
1840 if (node->child1()->shouldSpeculateNumber()) {
1841 if (isInt32Speculation(node->getHeapPrediction())) {
1842 // If the both predictions of this node and the child is Int32, we just convert ToNumber to Identity, that's simple.
1843 if (node->child1()->shouldSpeculateInt32()) {
1844 fixEdge<Int32Use>(node->child1());
1845 node->convertToIdentity();
1849 // 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.
1850 // 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.
1851 fixEdge<DoubleRepUse>(node->child1());
1852 node->setOp(DoubleAsInt32);
1853 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
1854 node->setArithMode(Arith::CheckOverflow);
1856 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
1860 fixEdge<DoubleRepUse>(node->child1());
1861 node->convertToIdentity();
1862 node->setResult(NodeResultDouble);
1866 fixEdge<UntypedUse>(node->child1());
1867 node->setResult(NodeResultJS);
1870 void fixupToStringOrCallStringConstructor(Node* node)
1872 if (node->child1()->shouldSpeculateString()) {
1873 fixEdge<StringUse>(node->child1());
1874 node->convertToIdentity();
1878 if (node->child1()->shouldSpeculateStringObject()
1879 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1880 fixEdge<StringObjectUse>(node->child1());
1884 if (node->child1()->shouldSpeculateStringOrStringObject()
1885 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1886 fixEdge<StringOrStringObjectUse>(node->child1());
1890 if (node->child1()->shouldSpeculateCell()) {
1891 fixEdge<CellUse>(node->child1());
1896 bool attemptToMakeFastStringAdd(Node* node)
1898 bool goodToGo = true;
1899 m_graph.doToChildren(
1902 if (edge->shouldSpeculateString())
1904 if (m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1905 if (edge->shouldSpeculateStringObject())
1907 if (edge->shouldSpeculateStringOrStringObject())
1915 m_graph.doToChildren(
1918 if (edge->shouldSpeculateString()) {
1919 convertStringAddUse<StringUse>(node, edge);
1922 ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
1923 if (edge->shouldSpeculateStringObject()) {
1924 convertStringAddUse<StringObjectUse>(node, edge);
1927 if (edge->shouldSpeculateStringOrStringObject()) {
1928 convertStringAddUse<StringOrStringObjectUse>(node, edge);
1931 RELEASE_ASSERT_NOT_REACHED();
1934 convertToMakeRope(node);
1938 void fixupGetAndSetLocalsInBlock(BasicBlock* block)
1942 ASSERT(block->isReachable);
1944 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1945 Node* node = m_currentNode = block->at(m_indexInBlock);
1946 if (node->op() != SetLocal && node->op() != GetLocal)
1949 VariableAccessData* variable = node->variableAccessData();
1950 switch (node->op()) {
1952 switch (variable->flushFormat()) {
1954 node->setResult(NodeResultDouble);
1957 node->setResult(NodeResultInt52);
1965 // NOTE: Any type checks we put here may get hoisted by fixupChecksInBlock(). So, if we
1966 // add new type checking use kind for SetLocals, we need to modify that code as well.
1968 switch (variable->flushFormat()) {
1969 case FlushedJSValue:
1972 fixEdge<DoubleRepUse>(node->child1());
1975 fixEdge<Int32Use>(node->child1());
1978 fixEdge<Int52RepUse>(node->child1());
1981 fixEdge<CellUse>(node->child1());
1983 case FlushedBoolean:
1984 fixEdge<BooleanUse>(node->child1());
1987 RELEASE_ASSERT_NOT_REACHED();
1993 RELEASE_ASSERT_NOT_REACHED();
1997 m_insertionSet.execute(block);
2000 void addStringReplacePrimordialChecks(Node* searchRegExp)
2002 Node* node = m_currentNode;
2004 // Check that structure of searchRegExp is RegExp object
2005 m_insertionSet.insertNode(
2006 m_indexInBlock, SpecNone, Check, node->origin,
2007 Edge(searchRegExp, RegExpObjectUse));
2009 auto emitPrimordialCheckFor = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2010 unsigned index = m_graph.identifiers().ensure(propertyUID);
2012 Node* actualProperty = m_insertionSet.insertNode(
2013 m_indexInBlock, SpecNone, TryGetById, node->origin,
2014 OpInfo(index), OpInfo(SpecFunction), Edge(searchRegExp, CellUse));
2016 m_insertionSet.insertNode(
2017 m_indexInBlock, SpecNone, CheckCell, node->origin,
2018 OpInfo(m_graph.freeze(primordialProperty)), Edge(actualProperty, CellUse));
2021 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
2023 // Check that searchRegExp.exec is the primordial RegExp.prototype.exec
2024 emitPrimordialCheckFor(globalObject->regExpProtoExecFunction(), vm().propertyNames->exec.impl());
2025 // Check that searchRegExp.global is the primordial RegExp.prototype.global
2026 emitPrimordialCheckFor(globalObject->regExpProtoGlobalGetter(), vm().propertyNames->global.impl());
2027 // Check that searchRegExp.unicode is the primordial RegExp.prototype.unicode
2028 emitPrimordialCheckFor(globalObject->regExpProtoUnicodeGetter(), vm().propertyNames->unicode.impl());
2029 // Check that searchRegExp[Symbol.match] is the primordial RegExp.prototype[Symbol.replace]
2030 emitPrimordialCheckFor(globalObject->regExpProtoSymbolReplaceFunction(), vm().propertyNames->replaceSymbol.impl());
2033 Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
2035 ASSERT(arrayMode.isSpecific());
2037 if (arrayMode.type() == Array::String) {
2038 m_insertionSet.insertNode(
2039 m_indexInBlock, SpecNone, Check, origin, Edge(array, StringUse));
2041 // Note that we only need to be using a structure check if we opt for SaneChain, since
2042 // that needs to protect against JSArray's __proto__ being changed.
2043 Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
2045 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
2047 if (arrayMode.doesConversion()) {
2049 m_insertionSet.insertNode(
2050 m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
2051 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
2053 m_insertionSet.insertNode(
2054 m_indexInBlock, SpecNone, Arrayify, origin,
2055 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
2059 m_insertionSet.insertNode(
2060 m_indexInBlock, SpecNone, CheckStructure, origin,
2061 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
2063 m_insertionSet.insertNode(
2064 m_indexInBlock, SpecNone, CheckArray, origin,
2065 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
2070 if (!storageCheck(arrayMode))
2073 if (arrayMode.usesButterfly()) {
2074 return m_insertionSet.insertNode(
2075 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
2078 return m_insertionSet.insertNode(
2079 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
2080 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
2083 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
2085 Node* node = m_currentNode;
2087 switch (node->arrayMode().type()) {
2088 case Array::ForceExit: {
2089 m_insertionSet.insertNode(
2090 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
2094 case Array::SelectUsingPredictions:
2095 case Array::Unprofiled:
2096 RELEASE_ASSERT_NOT_REACHED();
2099 case Array::Generic:
2103 Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
2107 storageChild = Edge(storage);
2112 bool alwaysUnboxSimplePrimitives()
2117 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
2123 template<UseKind useKind>
2124 void observeUseKindOnNode(Node* node)
2126 if (useKind == UntypedUse)
2128 observeUseKindOnNode(node, useKind);
2131 void observeUseKindOnEdge(Edge edge)
2133 observeUseKindOnNode(edge.node(), edge.useKind());
2136 void observeUseKindOnNode(Node* node, UseKind useKind)
2138 if (node->op() != GetLocal)
2141 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
2142 // https://bugs.webkit.org/show_bug.cgi?id=121518
2144 VariableAccessData* variable = node->variableAccessData();
2148 if (alwaysUnboxSimplePrimitives()
2149 || isInt32Speculation(variable->prediction()))
2150 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2155 case DoubleRepRealUse:
2156 if (variable->doubleFormatState() == UsingDoubleFormat)
2157 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2160 case KnownBooleanUse:
2161 if (alwaysUnboxSimplePrimitives()
2162 || isBooleanSpeculation(variable->prediction()))
2163 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2166 if (isAnyIntSpeculation(variable->prediction()))
2167 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2174 case KnownStringUse:
2176 case StringObjectUse:
2177 case StringOrStringObjectUse:
2178 if (alwaysUnboxSimplePrimitives()
2179 || isCellSpeculation(variable->prediction()))
2180 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2187 template<UseKind useKind>
2188 void fixEdge(Edge& edge)
2190 observeUseKindOnNode<useKind>(edge.node());
2191 edge.setUseKind(useKind);
2194 void speculateForBarrier(Edge value)
2196 // Currently, the DFG won't take advantage of this speculation. But, we want to do it in
2197 // the DFG anyway because if such a speculation would be wrong, we want to know before
2198 // we do an expensive compile.
2200 if (value->shouldSpeculateInt32()) {
2201 insertCheck<Int32Use>(m_indexInBlock, value.node());
2205 if (value->shouldSpeculateBoolean()) {
2206 insertCheck<BooleanUse>(m_indexInBlock, value.node());
2210 if (value->shouldSpeculateOther()) {
2211 insertCheck<OtherUse>(m_indexInBlock, value.node());
2215 if (value->shouldSpeculateNumber()) {
2216 insertCheck<NumberUse>(m_indexInBlock, value.node());
2220 if (value->shouldSpeculateNotCell()) {
2221 insertCheck<NotCellUse>(m_indexInBlock, value.node());
2226 template<UseKind useKind>
2227 void insertCheck(unsigned indexInBlock, Node* node)
2229 observeUseKindOnNode<useKind>(node);
2230 m_insertionSet.insertNode(
2231 indexInBlock, SpecNone, Check, m_currentNode->origin, Edge(node, useKind));
2234 void fixIntConvertingEdge(Edge& edge)
2236 Node* node = edge.node();
2237 if (node->shouldSpeculateInt32OrBoolean()) {
2238 fixIntOrBooleanEdge(edge);
2243 if (node->shouldSpeculateAnyInt())
2244 useKind = Int52RepUse;
2245 else if (node->shouldSpeculateNumber())
2246 useKind = DoubleRepUse;
2248 useKind = NotCellUse;
2249 Node* newNode = m_insertionSet.insertNode(
2250 m_indexInBlock, SpecInt32Only, ValueToInt32, m_currentNode->origin,
2251 Edge(node, useKind));
2252 observeUseKindOnNode(node, useKind);
2254 edge = Edge(newNode, KnownInt32Use);
2257 void fixIntOrBooleanEdge(Edge& edge)
2259 Node* node = edge.node();
2260 if (!node->sawBooleans()) {
2261 fixEdge<Int32Use>(edge);
2266 if (node->shouldSpeculateBoolean())
2267 useKind = BooleanUse;
2269 useKind = UntypedUse;
2270 Node* newNode = m_insertionSet.insertNode(
2271 m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
2272 Edge(node, useKind));
2273 observeUseKindOnNode(node, useKind);
2275 edge = Edge(newNode, Int32Use);
2278 void fixDoubleOrBooleanEdge(Edge& edge)
2280 Node* node = edge.node();
2281 if (!node->sawBooleans()) {
2282 fixEdge<DoubleRepUse>(edge);
2287 if (node->shouldSpeculateBoolean())
2288 useKind = BooleanUse;
2290 useKind = UntypedUse;
2291 Node* newNode = m_insertionSet.insertNode(
2292 m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
2293 Edge(node, useKind));
2294 observeUseKindOnNode(node, useKind);
2296 edge = Edge(newNode, DoubleRepUse);
2299 void truncateConstantToInt32(Edge& edge)
2301 Node* oldNode = edge.node();
2303 JSValue value = oldNode->asJSValue();
2304 if (value.isInt32())
2307 value = jsNumber(JSC::toInt32(value.asNumber()));
2308 ASSERT(value.isInt32());
2309 edge.setNode(m_insertionSet.insertNode(
2310 m_indexInBlock, SpecInt32Only, JSConstant, m_currentNode->origin,
2311 OpInfo(m_graph.freeze(value))));
2314 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
2316 if (mode != SpeculateInt32AndTruncateConstants)
2319 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
2320 if (node->child1()->hasConstant())
2321 truncateConstantToInt32(node->child1());
2323 truncateConstantToInt32(node->child2());
2326 bool attemptToMakeIntegerAdd(Node* node)
2328 AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
2329 if (mode != DontSpeculateInt32) {
2330 truncateConstantsIfNecessary(node, mode);
2331 fixIntOrBooleanEdge(node->child1());
2332 fixIntOrBooleanEdge(node->child2());
2333 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
2334 node->setArithMode(Arith::Unchecked);
2336 node->setArithMode(Arith::CheckOverflow);
2340 if (m_graph.addShouldSpeculateAnyInt(node)) {
2341 fixEdge<Int52RepUse>(node->child1());
2342 fixEdge<Int52RepUse>(node->child2());
2343 node->setArithMode(Arith::CheckOverflow);
2344 node->setResult(NodeResultInt52);
2351 bool attemptToMakeGetArrayLength(Node* node)
2353 if (!isInt32Speculation(node->prediction()))
2355 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
2356 ArrayProfile* arrayProfile =
2357 profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex);
2358 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
2360 ConcurrentJITLocker locker(profiledBlock->m_lock);
2361 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
2362 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
2363 if (arrayMode.type() == Array::Unprofiled) {
2364 // For normal array operations, it makes sense to treat Unprofiled
2365 // accesses as ForceExit and get more data rather than using
2366 // predictions and then possibly ending up with a Generic. But here,
2367 // we treat anything that is Unprofiled as Generic and keep the
2368 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
2369 // profit - from treating the Unprofiled case as
2370 // SelectUsingPredictions.
2371 arrayMode = ArrayMode(Array::SelectUsingPredictions);
2375 arrayMode = arrayMode.refine(
2376 m_graph, node, node->child1()->prediction(), node->prediction());
2378 if (arrayMode.type() == Array::Generic) {
2379 // Check if the input is something that we can't get array length for, but for which we
2380 // could insert some conversions in order to transform it into something that we can do it
2382 if (node->child1()->shouldSpeculateStringObject())
2383 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
2384 else if (node->child1()->shouldSpeculateStringOrStringObject())
2385 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
2388 if (!arrayMode.supportsSelfLength())
2391 convertToGetArrayLength(node, arrayMode);
2395 void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
2397 node->setOp(GetArrayLength);
2398 node->clearFlags(NodeMustGenerate);
2399 fixEdge<KnownCellUse>(node->child1());
2400 node->setArrayMode(arrayMode);
2402 Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
2406 node->child2() = Edge(storage);
2409 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
2411 Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
2412 return m_insertionSet.insertNode(
2413 m_indexInBlock, SpecInt32Only, GetArrayLength, origin,
2414 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
2417 void fixupChecksInBlock(BasicBlock* block)
2421 ASSERT(block->isReachable);
2423 unsigned indexForChecks = UINT_MAX;
2424 NodeOrigin originForChecks;
2425 for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
2426 Node* node = block->at(indexInBlock);
2428 // If this is a node at which we could exit, then save its index. If nodes after this one
2429 // cannot exit, then we will hoist checks to here.
2430 if (node->origin.exitOK) {
2431 indexForChecks = indexInBlock;
2432 originForChecks = node->origin;
2435 originForChecks = originForChecks.withSemantic(node->origin.semantic);
2437 // First, try to relax the representational demands of each node, in order to have
2438 // fewer conversions.
2439 switch (node->op()) {
2442 m_graph.doToChildren(
2445 switch (edge.useKind()) {
2447 case DoubleRepRealUse:
2448 if (edge->hasDoubleResult())
2451 if (edge->hasInt52Result())
2452 edge.setUseKind(Int52RepUse);
2453 else if (edge.useKind() == DoubleRepUse)
2454 edge.setUseKind(NumberUse);
2458 // Nothing we can really do.
2463 if (edge->hasDoubleResult())
2464 edge.setUseKind(DoubleRepUse);
2465 else if (edge->hasInt52Result())
2466 edge.setUseKind(Int52RepUse);
2470 if (edge->hasDoubleResult())
2471 edge.setUseKind(DoubleRepRealUse);
2472 else if (edge->hasInt52Result())
2473 edge.setUseKind(Int52RepUse);
2483 if (node->child1().useKind() == DoubleRepUse
2484 && !node->child1()->hasDoubleResult()) {
2485 node->child1().setUseKind(NumberUse);
2494 // Now, insert type conversions if necessary.
2495 m_graph.doToChildren(
2498 Node* result = nullptr;
2500 switch (edge.useKind()) {
2502 case DoubleRepRealUse:
2503 case DoubleRepAnyIntUse: {
2504 if (edge->hasDoubleResult())
2507 if (edge->isNumberConstant()) {
2508 result = m_insertionSet.insertNode(
2509 indexForChecks, SpecBytecodeDouble, DoubleConstant, originForChecks,
2510 OpInfo(m_graph.freeze(jsDoubleNumber(edge->asNumber()))));
2511 } else if (edge->hasInt52Result()) {
2512 result = m_insertionSet.insertNode(
2513 indexForChecks, SpecAnyIntAsDouble, DoubleRep, originForChecks,
2514 Edge(edge.node(), Int52RepUse));
2517 if (edge->shouldSpeculateDoubleReal())
2518 useKind = RealNumberUse;
2519 else if (edge->shouldSpeculateNumber())
2520 useKind = NumberUse;
2522 useKind = NotCellUse;
2524 result = m_insertionSet.insertNode(
2525 indexForChecks, SpecBytecodeDouble, DoubleRep, originForChecks,
2526 Edge(edge.node(), useKind));
2529 edge.setNode(result);
2534 if (edge->hasInt52Result())
2537 if (edge->isAnyIntConstant()) {
2538 result = m_insertionSet.insertNode(
2539 indexForChecks, SpecAnyInt, Int52Constant, originForChecks,
2540 OpInfo(edge->constant()));
2541 } else if (edge->hasDoubleResult()) {
2542 result = m_insertionSet.insertNode(
2543 indexForChecks, SpecAnyInt, Int52Rep, originForChecks,
2544 Edge(edge.node(), DoubleRepAnyIntUse));
2545 } else if (edge->shouldSpeculateInt32ForArithmetic()) {
2546 result = m_insertionSet.insertNode(
2547 indexForChecks, SpecInt32Only, Int52Rep, originForChecks,
2548 Edge(edge.node(), Int32Use));
2550 result = m_insertionSet.insertNode(
2551 indexForChecks, SpecAnyInt, Int52Rep, originForChecks,
2552 Edge(edge.node(), AnyIntUse));
2555 edge.setNode(result);
2560 if (!edge->hasDoubleResult() && !edge->hasInt52Result())
2563 if (edge->hasDoubleResult()) {
2564 result = m_insertionSet.insertNode(
2565 indexForChecks, SpecBytecodeDouble, ValueRep, originForChecks,
2566 Edge(edge.node(), DoubleRepUse));
2568 result = m_insertionSet.insertNode(
2569 indexForChecks, SpecInt32Only | SpecAnyIntAsDouble, ValueRep,
2570 originForChecks, Edge(edge.node(), Int52RepUse));
2573 edge.setNode(result);
2577 // It's remotely possible that this node cannot do type checks, but we now have a
2578 // type check on this node. We don't have to handle the general form of this
2579 // problem. It only arises when ByteCodeParser emits an immediate SetLocal, rather
2580 // than a delayed one. So, we only worry about those checks that we may have put on
2581 // a SetLocal. Note that "indexForChecks != indexInBlock" is just another way of
2582 // saying "!node->origin.exitOK".
2583 if (indexForChecks != indexInBlock && mayHaveTypeCheck(edge.useKind())) {
2584 UseKind knownUseKind;
2586 switch (edge.useKind()) {
2588 knownUseKind = KnownInt32Use;
2591 knownUseKind = KnownCellUse;
2594 knownUseKind = KnownBooleanUse;
2597 // This can only arise if we have a Check node, and in that case, we can
2598 // just remove the original check.
2599 DFG_ASSERT(m_graph, node, node->op() == Check);
2600 knownUseKind = UntypedUse;
2604 m_insertionSet.insertNode(
2605 indexForChecks, SpecNone, Check, originForChecks, edge);
2607 edge.setUseKind(knownUseKind);
2612 m_insertionSet.execute(block);
2615 BasicBlock* m_block;
2616 unsigned m_indexInBlock;
2617 Node* m_currentNode;
2618 InsertionSet m_insertionSet;
2619 bool m_profitabilityChanged;
2622 bool performFixup(Graph& graph)
2624 return runPhase<FixupPhase>(graph);
2627 } } // namespace JSC::DFG
2629 #endif // ENABLE(DFG_JIT)