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 && m_graph.hasExitSite(node->origin.semantic, BadType)) {
110 fixEdge<UntypedUse>(node->child1());
111 fixEdge<UntypedUse>(node->child2());
114 fixIntConvertingEdge(node->child1());
115 fixIntConvertingEdge(node->child2());
120 fixIntConvertingEdge(node->child1());
121 fixIntConvertingEdge(node->child2());
122 node->setOp(ArithMul);
123 node->setArithMode(Arith::Unchecked);
124 node->child1().setUseKind(Int32Use);
125 node->child2().setUseKind(Int32Use);
130 fixIntConvertingEdge(node->child1());
131 node->setArithMode(Arith::Unchecked);
135 case UInt32ToNumber: {
136 fixIntConvertingEdge(node->child1());
137 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
138 node->convertToIdentity();
139 else if (node->canSpeculateInt32(FixupPass))
140 node->setArithMode(Arith::CheckOverflow);
142 node->setArithMode(Arith::DoOverflow);
143 node->clearFlags(NodeMustGenerate);
144 node->setResult(enableInt52() ? NodeResultInt52 : NodeResultDouble);
150 if (attemptToMakeIntegerAdd(node)) {
151 node->setOp(ArithAdd);
154 if (Node::shouldSpeculateNumberOrBooleanExpectingDefined(node->child1().node(), node->child2().node())) {
155 fixDoubleOrBooleanEdge(node->child1());
156 fixDoubleOrBooleanEdge(node->child2());
157 node->setOp(ArithAdd);
158 node->setResult(NodeResultDouble);
162 if (attemptToMakeFastStringAdd(node))
165 fixEdge<UntypedUse>(node->child1());
166 fixEdge<UntypedUse>(node->child2());
167 node->setResult(NodeResultJS);
172 if (attemptToMakeFastStringAdd(node))
175 // FIXME: Remove empty string arguments and possibly turn this into a ToString operation. That
176 // would require a form of ToString that takes a KnownPrimitiveUse. This is necessary because
177 // the implementation of StrCat doesn't dynamically optimize for empty strings.
178 // https://bugs.webkit.org/show_bug.cgi?id=148540
179 m_graph.doToChildren(
182 fixEdge<KnownPrimitiveUse>(edge);
195 && Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
196 fixEdge<UntypedUse>(node->child1());
197 fixEdge<UntypedUse>(node->child2());
198 node->setResult(NodeResultJS);
201 if (attemptToMakeIntegerAdd(node))
203 fixDoubleOrBooleanEdge(node->child1());
204 fixDoubleOrBooleanEdge(node->child2());
205 node->setResult(NodeResultDouble);
210 if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
211 fixIntOrBooleanEdge(node->child1());
212 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
213 node->setArithMode(Arith::Unchecked);
214 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
215 node->setArithMode(Arith::CheckOverflow);
217 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
220 if (m_graph.unaryArithShouldSpeculateAnyInt(node, FixupPass)) {
221 fixEdge<Int52RepUse>(node->child1());
222 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
223 node->setArithMode(Arith::CheckOverflow);
225 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
226 node->setResult(NodeResultInt52);
229 fixDoubleOrBooleanEdge(node->child1());
230 node->setResult(NodeResultDouble);
235 Edge& leftChild = node->child1();
236 Edge& rightChild = node->child2();
237 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) {
238 fixEdge<UntypedUse>(leftChild);
239 fixEdge<UntypedUse>(rightChild);
240 node->setResult(NodeResultJS);
243 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
244 fixIntOrBooleanEdge(leftChild);
245 fixIntOrBooleanEdge(rightChild);
246 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
247 node->setArithMode(Arith::Unchecked);
248 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())
249 || leftChild.node() == rightChild.node())
250 node->setArithMode(Arith::CheckOverflow);
252 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
255 if (m_graph.binaryArithShouldSpeculateAnyInt(node, FixupPass)) {
256 fixEdge<Int52RepUse>(leftChild);
257 fixEdge<Int52RepUse>(rightChild);
258 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())
259 || leftChild.node() == rightChild.node())
260 node->setArithMode(Arith::CheckOverflow);
262 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
263 node->setResult(NodeResultInt52);
266 fixDoubleOrBooleanEdge(leftChild);
267 fixDoubleOrBooleanEdge(rightChild);
268 node->setResult(NodeResultDouble);
274 Edge& leftChild = node->child1();
275 Edge& rightChild = node->child2();
277 && Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())
278 && m_graph.hasExitSite(node->origin.semantic, BadType)) {
279 fixEdge<UntypedUse>(leftChild);
280 fixEdge<UntypedUse>(rightChild);
281 node->setResult(NodeResultJS);
284 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
285 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) {
286 fixIntOrBooleanEdge(leftChild);
287 fixIntOrBooleanEdge(rightChild);
288 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
289 node->setArithMode(Arith::Unchecked);
290 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
291 node->setArithMode(Arith::CheckOverflow);
293 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
297 // This will cause conversion nodes to be inserted later.
298 fixDoubleOrBooleanEdge(leftChild);
299 fixDoubleOrBooleanEdge(rightChild);
301 // We don't need to do ref'ing on the children because we're stealing them from
302 // the original division.
303 Node* newDivision = m_insertionSet.insertNode(
304 m_indexInBlock, SpecBytecodeDouble, *node);
305 newDivision->setResult(NodeResultDouble);
307 node->setOp(DoubleAsInt32);
308 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
309 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
310 node->setArithMode(Arith::CheckOverflow);
312 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
315 fixDoubleOrBooleanEdge(leftChild);
316 fixDoubleOrBooleanEdge(rightChild);
317 node->setResult(NodeResultDouble);
323 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
324 fixIntOrBooleanEdge(node->child1());
325 fixIntOrBooleanEdge(node->child2());
328 fixDoubleOrBooleanEdge(node->child1());
329 fixDoubleOrBooleanEdge(node->child2());
330 node->setResult(NodeResultDouble);
335 if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
336 fixIntOrBooleanEdge(node->child1());
337 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
338 node->setArithMode(Arith::Unchecked);
340 node->setArithMode(Arith::CheckOverflow);
343 fixDoubleOrBooleanEdge(node->child1());
344 node->setResult(NodeResultDouble);
349 if (node->child2()->shouldSpeculateInt32OrBooleanForArithmetic()) {
350 fixDoubleOrBooleanEdge(node->child1());
351 fixIntOrBooleanEdge(node->child2());
355 fixDoubleOrBooleanEdge(node->child1());
356 fixDoubleOrBooleanEdge(node->child2());
361 node->setResult(NodeResultDouble);
369 if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
370 fixIntOrBooleanEdge(node->child1());
371 insertCheck<Int32Use>(m_indexInBlock, node->child1().node());
372 node->convertToIdentity();
375 fixDoubleOrBooleanEdge(node->child1());
377 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
378 node->setResult(NodeResultInt32);
379 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
380 node->setArithRoundingMode(Arith::RoundingMode::Int32);
382 node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
384 node->setResult(NodeResultDouble);
385 node->setArithRoundingMode(Arith::RoundingMode::Double);
395 fixDoubleOrBooleanEdge(node->child1());
396 node->setResult(NodeResultDouble);
401 if (node->child1()->shouldSpeculateBoolean()) {
402 if (node->child1()->result() == NodeResultBoolean) {
403 // This is necessary in case we have a bytecode instruction implemented by:
408 // In that case, CompareEq might have a side-effect. Then, we need to make
409 // sure that we know that Branch does not exit.
410 fixEdge<KnownBooleanUse>(node->child1());
412 fixEdge<BooleanUse>(node->child1());
413 } else if (node->child1()->shouldSpeculateObjectOrOther())
414 fixEdge<ObjectOrOtherUse>(node->child1());
415 else if (node->child1()->shouldSpeculateInt32OrBoolean())
416 fixIntOrBooleanEdge(node->child1());
417 else if (node->child1()->shouldSpeculateNumber())
418 fixEdge<DoubleRepUse>(node->child1());
419 else if (node->child1()->shouldSpeculateString())
420 fixEdge<StringUse>(node->child1());
421 else if (node->child1()->shouldSpeculateStringOrOther())
422 fixEdge<StringOrOtherUse>(node->child1());
430 case CompareGreaterEq: {
431 if (node->op() == CompareEq
432 && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
433 fixEdge<BooleanUse>(node->child1());
434 fixEdge<BooleanUse>(node->child2());
435 node->clearFlags(NodeMustGenerate);
438 if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
439 fixIntOrBooleanEdge(node->child1());
440 fixIntOrBooleanEdge(node->child2());
441 node->clearFlags(NodeMustGenerate);
445 && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
446 fixEdge<Int52RepUse>(node->child1());
447 fixEdge<Int52RepUse>(node->child2());
448 node->clearFlags(NodeMustGenerate);
451 if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
452 fixDoubleOrBooleanEdge(node->child1());
453 fixDoubleOrBooleanEdge(node->child2());
455 if (node->op() != CompareEq
456 && node->child1()->shouldSpeculateNotCell()
457 && node->child2()->shouldSpeculateNotCell()) {
458 if (node->child1()->shouldSpeculateNumberOrBoolean())
459 fixDoubleOrBooleanEdge(node->child1());
461 fixEdge<DoubleRepUse>(node->child1());
462 if (node->child2()->shouldSpeculateNumberOrBoolean())
463 fixDoubleOrBooleanEdge(node->child2());
465 fixEdge<DoubleRepUse>(node->child2());
466 node->clearFlags(NodeMustGenerate);
469 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
470 fixEdge<StringIdentUse>(node->child1());
471 fixEdge<StringIdentUse>(node->child2());
472 node->clearFlags(NodeMustGenerate);
475 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
476 fixEdge<StringUse>(node->child1());
477 fixEdge<StringUse>(node->child2());
478 node->clearFlags(NodeMustGenerate);
482 if (node->op() != CompareEq)
484 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
485 fixEdge<SymbolUse>(node->child1());
486 fixEdge<SymbolUse>(node->child2());
487 node->clearFlags(NodeMustGenerate);
490 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
491 fixEdge<ObjectUse>(node->child1());
492 fixEdge<ObjectUse>(node->child2());
493 node->clearFlags(NodeMustGenerate);
497 // If either child can be proved to be Null or Undefined, comparing them is greatly simplified.
498 bool oneArgumentIsUsedAsSpecOther = false;
499 if (node->child1()->isUndefinedOrNullConstant()) {
500 fixEdge<OtherUse>(node->child1());
501 oneArgumentIsUsedAsSpecOther = true;
502 } else if (node->child1()->shouldSpeculateOther()) {
503 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
504 Edge(node->child1().node(), OtherUse));
505 fixEdge<OtherUse>(node->child1());
506 oneArgumentIsUsedAsSpecOther = true;
508 if (node->child2()->isUndefinedOrNullConstant()) {
509 fixEdge<OtherUse>(node->child2());
510 oneArgumentIsUsedAsSpecOther = true;
511 } else if (node->child2()->shouldSpeculateOther()) {
512 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
513 Edge(node->child2().node(), OtherUse));
514 fixEdge<OtherUse>(node->child2());
515 oneArgumentIsUsedAsSpecOther = true;
517 if (oneArgumentIsUsedAsSpecOther) {
518 node->clearFlags(NodeMustGenerate);
522 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
523 fixEdge<ObjectUse>(node->child1());
524 fixEdge<ObjectOrOtherUse>(node->child2());
525 node->clearFlags(NodeMustGenerate);
528 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
529 fixEdge<ObjectOrOtherUse>(node->child1());
530 fixEdge<ObjectUse>(node->child2());
531 node->clearFlags(NodeMustGenerate);
538 case CompareStrictEq: {
539 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
540 fixEdge<BooleanUse>(node->child1());
541 fixEdge<BooleanUse>(node->child2());
544 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
545 fixEdge<Int32Use>(node->child1());
546 fixEdge<Int32Use>(node->child2());
550 && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
551 fixEdge<Int52RepUse>(node->child1());
552 fixEdge<Int52RepUse>(node->child2());
555 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
556 fixEdge<DoubleRepUse>(node->child1());
557 fixEdge<DoubleRepUse>(node->child2());
560 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
561 fixEdge<SymbolUse>(node->child1());
562 fixEdge<SymbolUse>(node->child2());
565 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
566 fixEdge<StringIdentUse>(node->child1());
567 fixEdge<StringIdentUse>(node->child2());
570 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 7) || isFTL(m_graph.m_plan.mode))) {
571 fixEdge<StringUse>(node->child1());
572 fixEdge<StringUse>(node->child2());
575 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
576 if (masqueradesAsUndefinedWatchpoint->isStillValid()) {
578 if (node->child1()->shouldSpeculateObject()) {
579 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
580 fixEdge<ObjectUse>(node->child1());
583 if (node->child2()->shouldSpeculateObject()) {
584 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
585 fixEdge<ObjectUse>(node->child2());
589 } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
590 fixEdge<ObjectUse>(node->child1());
591 fixEdge<ObjectUse>(node->child2());
594 if (node->child1()->shouldSpeculateMisc()) {
595 fixEdge<MiscUse>(node->child1());
598 if (node->child2()->shouldSpeculateMisc()) {
599 fixEdge<MiscUse>(node->child2());
602 if (node->child1()->shouldSpeculateStringIdent()
603 && node->child2()->shouldSpeculateNotStringVar()) {
604 fixEdge<StringIdentUse>(node->child1());
605 fixEdge<NotStringVarUse>(node->child2());
608 if (node->child2()->shouldSpeculateStringIdent()
609 && node->child1()->shouldSpeculateNotStringVar()) {
610 fixEdge<StringIdentUse>(node->child2());
611 fixEdge<NotStringVarUse>(node->child1());
614 if (node->child1()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
615 fixEdge<StringUse>(node->child1());
618 if (node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
619 fixEdge<StringUse>(node->child2());
625 case StringFromCharCode:
626 if (node->child1()->shouldSpeculateInt32())
627 fixEdge<Int32Use>(node->child1());
629 fixEdge<UntypedUse>(node->child1());
633 case StringCharCodeAt: {
634 // Currently we have no good way of refining these.
635 ASSERT(node->arrayMode() == ArrayMode(Array::String));
636 blessArrayOperation(node->child1(), node->child2(), node->child3());
637 fixEdge<KnownCellUse>(node->child1());
638 fixEdge<Int32Use>(node->child2());
643 if (!node->prediction()) {
644 m_insertionSet.insertNode(
645 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
649 node->arrayMode().refine(
651 node->child1()->prediction(),
652 node->child2()->prediction(),
655 blessArrayOperation(node->child1(), node->child2(), node->child3());
657 ArrayMode arrayMode = node->arrayMode();
658 switch (arrayMode.type()) {
659 case Array::Contiguous:
661 if (arrayMode.arrayClass() == Array::OriginalArray
662 && arrayMode.speculation() == Array::InBounds) {
663 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
664 if (globalObject->arrayPrototypeChainIsSane()) {
665 // Check if SaneChain will work on a per-type basis. Note that:
667 // 1) We don't want double arrays to sometimes return undefined, since
668 // that would require a change to the return type and it would pessimise
669 // things a lot. So, we'd only want to do that if we actually had
670 // evidence that we could read from a hole. That's pretty annoying.
671 // Likely the best way to handle that case is with an equivalent of
672 // SaneChain for OutOfBounds. For now we just detect when Undefined and
673 // NaN are indistinguishable according to backwards propagation, and just
674 // use SaneChain in that case. This happens to catch a lot of cases.
676 // 2) We don't want int32 array loads to have to do a hole check just to
677 // coerce to Undefined, since that would mean twice the checks.
679 // This has two implications. First, we have to do more checks than we'd
680 // like. It's unfortunate that we have to do the hole check. Second,
681 // some accesses that hit a hole will now need to take the full-blown
682 // out-of-bounds slow path. We can fix that with:
683 // https://bugs.webkit.org/show_bug.cgi?id=144668
685 bool canDoSaneChain = false;
686 switch (arrayMode.type()) {
687 case Array::Contiguous:
688 // This is happens to be entirely natural. We already would have
689 // returned any JSValue, and now we'll return Undefined. We still do
690 // the check but it doesn't require taking any kind of slow path.
691 canDoSaneChain = true;
695 if (!(node->flags() & NodeBytecodeUsesAsOther)) {
696 // Holes look like NaN already, so if the user doesn't care
697 // about the difference between Undefined and NaN then we can
699 canDoSaneChain = true;
707 if (canDoSaneChain) {
708 m_graph.watchpoints().addLazily(
709 globalObject->arrayPrototype()->structure()->transitionWatchpointSet());
710 m_graph.watchpoints().addLazily(
711 globalObject->objectPrototype()->structure()->transitionWatchpointSet());
712 if (globalObject->arrayPrototypeChainIsSane())
713 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
720 if ((node->prediction() & ~SpecString)
721 || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
722 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
729 arrayMode = node->arrayMode();
730 switch (arrayMode.type()) {
731 case Array::SelectUsingPredictions:
732 case Array::Unprofiled:
733 RELEASE_ASSERT_NOT_REACHED();
736 #if USE(JSVALUE32_64)
737 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
740 case Array::ForceExit:
743 fixEdge<KnownCellUse>(node->child1());
744 fixEdge<Int32Use>(node->child2());
748 switch (arrayMode.type()) {
750 if (!arrayMode.isOutOfBounds())
751 node->setResult(NodeResultDouble);
754 case Array::Float32Array:
755 case Array::Float64Array:
756 node->setResult(NodeResultDouble);
759 case Array::Uint32Array:
760 if (node->shouldSpeculateInt32())
762 if (node->shouldSpeculateAnyInt() && enableInt52())
763 node->setResult(NodeResultInt52);
765 node->setResult(NodeResultDouble);
777 case PutByValAlias: {
778 Edge& child1 = m_graph.varArgChild(node, 0);
779 Edge& child2 = m_graph.varArgChild(node, 1);
780 Edge& child3 = m_graph.varArgChild(node, 2);
783 node->arrayMode().refine(
785 child1->prediction(),
786 child2->prediction(),
787 child3->prediction()));
789 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
791 switch (node->arrayMode().modeForPut().type()) {
792 case Array::SelectUsingPredictions:
793 case Array::SelectUsingArguments:
794 case Array::Unprofiled:
795 case Array::Undecided:
796 RELEASE_ASSERT_NOT_REACHED();
798 case Array::ForceExit:
800 #if USE(JSVALUE32_64)
801 // Due to register pressure on 32-bit, we speculate cell and
802 // ignore the base-is-not-cell case entirely by letting the
803 // baseline JIT handle it.
804 fixEdge<CellUse>(child1);
808 fixEdge<KnownCellUse>(child1);
809 fixEdge<Int32Use>(child2);
810 fixEdge<Int32Use>(child3);
813 fixEdge<KnownCellUse>(child1);
814 fixEdge<Int32Use>(child2);
815 fixEdge<DoubleRepRealUse>(child3);
817 case Array::Int8Array:
818 case Array::Int16Array:
819 case Array::Int32Array:
820 case Array::Uint8Array:
821 case Array::Uint8ClampedArray:
822 case Array::Uint16Array:
823 case Array::Uint32Array:
824 fixEdge<KnownCellUse>(child1);
825 fixEdge<Int32Use>(child2);
826 if (child3->shouldSpeculateInt32())
827 fixIntOrBooleanEdge(child3);
828 else if (child3->shouldSpeculateAnyInt())
829 fixEdge<Int52RepUse>(child3);
831 fixDoubleOrBooleanEdge(child3);
833 case Array::Float32Array:
834 case Array::Float64Array:
835 fixEdge<KnownCellUse>(child1);
836 fixEdge<Int32Use>(child2);
837 fixDoubleOrBooleanEdge(child3);
839 case Array::Contiguous:
840 case Array::ArrayStorage:
841 case Array::SlowPutArrayStorage:
842 fixEdge<KnownCellUse>(child1);
843 fixEdge<Int32Use>(child2);
844 speculateForBarrier(child3);
847 fixEdge<KnownCellUse>(child1);
848 fixEdge<Int32Use>(child2);
855 // May need to refine the array mode in case the value prediction contravenes
856 // the array prediction. For example, we may have evidence showing that the
857 // array is in Int32 mode, but the value we're storing is likely to be a double.
858 // Then we should turn this into a conversion to Double array followed by the
859 // push. On the other hand, we absolutely don't want to refine based on the
860 // base prediction. If it has non-cell garbage in it, then we want that to be
861 // ignored. That's because ArrayPush can't handle any array modes that aren't
862 // array-related - so if refine() turned this into a "Generic" ArrayPush then
863 // that would break things.
865 node->arrayMode().refine(
867 node->child1()->prediction() & SpecCell,
869 node->child2()->prediction()));
870 blessArrayOperation(node->child1(), Edge(), node->child3());
871 fixEdge<KnownCellUse>(node->child1());
873 switch (node->arrayMode().type()) {
875 fixEdge<Int32Use>(node->child2());
878 fixEdge<DoubleRepRealUse>(node->child2());
880 case Array::Contiguous:
881 case Array::ArrayStorage:
882 speculateForBarrier(node->child2());
891 blessArrayOperation(node->child1(), Edge(), node->child2());
892 fixEdge<KnownCellUse>(node->child1());
898 fixEdge<KnownCellUse>(node->child1());
900 if (node->child2()->shouldSpeculateRegExpObject()) {
901 fixEdge<RegExpObjectUse>(node->child2());
903 if (node->child3()->shouldSpeculateString())
904 fixEdge<StringUse>(node->child3());
910 case StringReplaceRegExp: {
911 if (node->child2()->shouldSpeculateString()) {
912 m_insertionSet.insertNode(
913 m_indexInBlock, SpecNone, Check, node->origin,
914 Edge(node->child2().node(), StringUse));
915 fixEdge<StringUse>(node->child2());
916 } else if (op == StringReplace) {
917 if (node->child2()->shouldSpeculateRegExpObject())
918 addStringReplacePrimordialChecks(node->child2().node());
920 m_insertionSet.insertNode(
921 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
924 if (node->child1()->shouldSpeculateString()
925 && node->child2()->shouldSpeculateRegExpObject()
926 && node->child3()->shouldSpeculateString()) {
928 fixEdge<StringUse>(node->child1());
929 fixEdge<RegExpObjectUse>(node->child2());
930 fixEdge<StringUse>(node->child3());
937 if (node->child1()->shouldSpeculateBoolean()) {
938 if (node->child1()->result() == NodeResultBoolean) {
939 // This is necessary in case we have a bytecode instruction implemented by:
944 // In that case, CompareEq might have a side-effect. Then, we need to make
945 // sure that we know that Branch does not exit.
946 fixEdge<KnownBooleanUse>(node->child1());
948 fixEdge<BooleanUse>(node->child1());
949 } else if (node->child1()->shouldSpeculateObjectOrOther())
950 fixEdge<ObjectOrOtherUse>(node->child1());
951 else if (node->child1()->shouldSpeculateInt32OrBoolean())
952 fixIntOrBooleanEdge(node->child1());
953 else if (node->child1()->shouldSpeculateNumber())
954 fixEdge<DoubleRepUse>(node->child1());
955 else if (node->child1()->shouldSpeculateString())
956 fixEdge<StringUse>(node->child1());
957 else if (node->child1()->shouldSpeculateStringOrOther())
958 fixEdge<StringOrOtherUse>(node->child1());
963 SwitchData* data = node->switchData();
964 switch (data->kind) {
966 if (node->child1()->shouldSpeculateInt32())
967 fixEdge<Int32Use>(node->child1());
970 if (node->child1()->shouldSpeculateString())
971 fixEdge<StringUse>(node->child1());
974 if (node->child1()->shouldSpeculateStringIdent())
975 fixEdge<StringIdentUse>(node->child1());
976 else if (node->child1()->shouldSpeculateString())
977 fixEdge<StringUse>(node->child1());
980 if (node->child1()->shouldSpeculateCell())
981 fixEdge<CellUse>(node->child1());
982 // else it's fine for this to have UntypedUse; we will handle this by just making
983 // non-cells take the default case.
990 fixupToPrimitive(node);
995 case CallStringConstructor: {
996 fixupToStringOrCallStringConstructor(node);
1000 case NewStringObject: {
1001 fixEdge<KnownStringUse>(node->child1());
1006 watchHavingABadTime(node);
1008 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
1009 node->setIndexingType(
1010 leastUpperBoundOfIndexingTypeAndType(
1011 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
1013 switch (node->indexingType()) {
1014 case ALL_BLANK_INDEXING_TYPES:
1017 case ALL_UNDECIDED_INDEXING_TYPES:
1018 if (node->numChildren()) {
1019 // This will only happen if the children have no type predictions. We
1020 // would have already exited by now, but insert a forced exit just to
1022 m_insertionSet.insertNode(
1023 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
1026 case ALL_INT32_INDEXING_TYPES:
1027 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1028 fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1030 case ALL_DOUBLE_INDEXING_TYPES:
1031 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1032 fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1034 case ALL_CONTIGUOUS_INDEXING_TYPES:
1035 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
1044 case NewTypedArray: {
1045 watchHavingABadTime(node);
1047 if (node->child1()->shouldSpeculateInt32()) {
1048 fixEdge<Int32Use>(node->child1());
1049 node->clearFlags(NodeMustGenerate);
1055 case NewArrayWithSize: {
1056 watchHavingABadTime(node);
1057 fixEdge<Int32Use>(node->child1());
1061 case CallObjectConstructor: {
1062 if (node->child1()->shouldSpeculateObject()) {
1063 fixEdge<ObjectUse>(node->child1());
1064 node->convertToIdentity();
1068 fixEdge<UntypedUse>(node->child1());
1077 case PutStructure: {
1078 fixEdge<KnownCellUse>(node->child1());
1083 case GetFromArguments: {
1084 fixEdge<KnownCellUse>(node->child1());
1089 case PutToArguments: {
1090 fixEdge<KnownCellUse>(node->child1());
1091 speculateForBarrier(node->child2());
1099 case GetGlobalObject: {
1100 fixEdge<KnownCellUse>(node->child1());
1104 case AllocatePropertyStorage:
1105 case ReallocatePropertyStorage: {
1106 fixEdge<KnownCellUse>(node->child1());
1111 if (node->child1()->shouldSpeculateCell())
1112 fixEdge<CellUse>(node->child1());
1117 case GetByIdFlush: {
1118 // FIXME: This should be done in the ByteCodeParser based on reading the
1119 // PolymorphicAccess, which will surely tell us that this is a AccessCase::ArrayLength.
1120 // https://bugs.webkit.org/show_bug.cgi?id=154990
1121 if (node->child1()->shouldSpeculateCellOrOther()
1122 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1123 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1124 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1125 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1127 auto uid = m_graph.identifiers()[node->identifierNumber()];
1129 if (uid == vm().propertyNames->length.impl()) {
1130 attemptToMakeGetArrayLength(node);
1134 if (uid == vm().propertyNames->lastIndex.impl()
1135 && node->child1()->shouldSpeculateRegExpObject()) {
1136 node->setOp(GetRegExpObjectLastIndex);
1137 node->clearFlags(NodeMustGenerate);
1138 fixEdge<RegExpObjectUse>(node->child1());
1143 if (node->child1()->shouldSpeculateCell())
1144 fixEdge<CellUse>(node->child1());
1150 case PutByIdDirect: {
1151 if (node->child1()->shouldSpeculateCellOrOther()
1152 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1153 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1154 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1155 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1157 auto uid = m_graph.identifiers()[node->identifierNumber()];
1159 if (uid == vm().propertyNames->lastIndex.impl()
1160 && node->child1()->shouldSpeculateRegExpObject()) {
1161 node->setOp(SetRegExpObjectLastIndex);
1162 fixEdge<RegExpObjectUse>(node->child1());
1163 speculateForBarrier(node->child2());
1168 fixEdge<CellUse>(node->child1());
1173 case PutSetterById: {
1174 fixEdge<KnownCellUse>(node->child1());
1175 fixEdge<KnownCellUse>(node->child2());
1179 case PutGetterSetterById: {
1180 fixEdge<KnownCellUse>(node->child1());
1184 case PutGetterByVal:
1185 case PutSetterByVal: {
1186 fixEdge<KnownCellUse>(node->child1());
1187 fixEdge<KnownCellUse>(node->child3());
1191 case GetExecutable: {
1192 fixEdge<FunctionUse>(node->child1());
1196 case OverridesHasInstance:
1197 case CheckStructure:
1200 case GetButterfly: {
1201 fixEdge<CellUse>(node->child1());
1206 UniquedStringImpl* uid = node->uidOperand();
1207 if (uid->isSymbol())
1208 fixEdge<SymbolUse>(node->child1());
1210 fixEdge<StringIdentUse>(node->child1());
1215 case ArrayifyToStructure: {
1216 fixEdge<CellUse>(node->child1());
1218 fixEdge<Int32Use>(node->child2());
1223 case GetGetterSetterByOffset: {
1224 if (!node->child1()->hasStorageResult())
1225 fixEdge<KnownCellUse>(node->child1());
1226 fixEdge<KnownCellUse>(node->child2());
1230 case MultiGetByOffset: {
1231 fixEdge<CellUse>(node->child1());
1236 if (!node->child1()->hasStorageResult())
1237 fixEdge<KnownCellUse>(node->child1());
1238 fixEdge<KnownCellUse>(node->child2());
1239 insertInferredTypeCheck(
1240 m_insertionSet, m_indexInBlock, node->origin, node->child3().node(),
1241 node->storageAccessData().inferredType);
1242 speculateForBarrier(node->child3());
1246 case MultiPutByOffset: {
1247 fixEdge<CellUse>(node->child1());
1248 speculateForBarrier(node->child2());
1253 if (!(node->child1()->prediction() & ~SpecCell))
1254 fixEdge<CellUse>(node->child1());
1255 fixEdge<CellUse>(node->child2());
1259 case InstanceOfCustom:
1260 fixEdge<CellUse>(node->child2());
1264 // FIXME: We should at some point have array profiling on op_in, in which
1265 // case we would be able to turn this into a kind of GetByVal.
1267 fixEdge<CellUse>(node->child2());
1272 m_graph.doToChildren(
1275 switch (edge.useKind()) {
1277 if (edge->shouldSpeculateInt32ForArithmetic())
1278 edge.setUseKind(Int32Use);
1283 observeUseKindOnEdge(edge);
1289 // Phantoms are meaningless past Fixup. We recreate them on-demand in the backend.
1294 RELEASE_ASSERT(enableInt52());
1295 node->convertToIdentity();
1296 fixEdge<Int52RepUse>(node->child1());
1297 node->setResult(NodeResultInt52);
1301 case GetArrayLength: {
1302 fixEdge<KnownCellUse>(node->child1());
1306 case GetTypedArrayByteOffset: {
1307 fixEdge<KnownCellUse>(node->child1());
1313 case GetIndexedPropertyStorage:
1315 case CheckTierUpInLoop:
1316 case CheckTierUpAtReturn:
1317 case CheckTierUpAndOSREnter:
1318 case InvalidationPoint:
1321 case ConstantStoragePointer:
1328 case Identity: // This should have been cleaned up.
1329 case BooleanToNumber:
1330 case PhantomNewObject:
1331 case PhantomNewFunction:
1332 case PhantomNewGeneratorFunction:
1333 case PhantomCreateActivation:
1334 case PhantomDirectArguments:
1335 case PhantomClonedArguments:
1336 case ForwardVarargs:
1337 case GetMyArgumentByVal:
1338 case GetMyArgumentByValOutOfBounds:
1340 case CheckStructureImmediate:
1341 case MaterializeNewObject:
1342 case MaterializeCreateActivation:
1347 case GetRegExpObjectLastIndex:
1348 case SetRegExpObjectLastIndex:
1349 case RecordRegExpCachedResult:
1350 // These are just nodes that we don't currently expect to see during fixup.
1351 // If we ever wanted to insert them prior to fixup, then we just have to create
1352 // fixup rules for them.
1353 DFG_CRASH(m_graph, node, "Unexpected node during fixup");
1356 case PutGlobalVariable: {
1357 fixEdge<CellUse>(node->child1());
1358 speculateForBarrier(node->child2());
1363 if (node->child1()->shouldSpeculateString()) {
1364 m_insertionSet.insertNode(
1365 m_indexInBlock, SpecNone, Check, node->origin,
1366 Edge(node->child1().node(), StringUse));
1367 m_graph.convertToConstant(node, jsBoolean(true));
1368 observeUseKindOnNode<StringUse>(node);
1373 if (node->child1()->shouldSpeculateObject()) {
1374 m_insertionSet.insertNode(
1375 m_indexInBlock, SpecNone, Check, node->origin,
1376 Edge(node->child1().node(), ObjectUse));
1377 m_graph.convertToConstant(node, jsBoolean(true));
1378 observeUseKindOnNode<ObjectUse>(node);
1382 case GetEnumerableLength: {
1383 fixEdge<CellUse>(node->child1());
1386 case HasGenericProperty: {
1387 fixEdge<CellUse>(node->child2());
1390 case HasStructureProperty: {
1391 fixEdge<StringUse>(node->child2());
1392 fixEdge<KnownCellUse>(node->child3());
1395 case HasIndexedProperty: {
1397 node->arrayMode().refine(
1399 node->child1()->prediction(),
1400 node->child2()->prediction(),
1403 blessArrayOperation(node->child1(), node->child2(), node->child3());
1404 fixEdge<CellUse>(node->child1());
1405 fixEdge<KnownInt32Use>(node->child2());
1408 case GetDirectPname: {
1409 Edge& base = m_graph.varArgChild(node, 0);
1410 Edge& property = m_graph.varArgChild(node, 1);
1411 Edge& index = m_graph.varArgChild(node, 2);
1412 Edge& enumerator = m_graph.varArgChild(node, 3);
1413 fixEdge<CellUse>(base);
1414 fixEdge<KnownCellUse>(property);
1415 fixEdge<KnownInt32Use>(index);
1416 fixEdge<KnownCellUse>(enumerator);
1419 case GetPropertyEnumerator: {
1420 fixEdge<CellUse>(node->child1());
1423 case GetEnumeratorStructurePname: {
1424 fixEdge<KnownCellUse>(node->child1());
1425 fixEdge<KnownInt32Use>(node->child2());
1428 case GetEnumeratorGenericPname: {
1429 fixEdge<KnownCellUse>(node->child1());
1430 fixEdge<KnownInt32Use>(node->child2());
1433 case ToIndexString: {
1434 fixEdge<KnownInt32Use>(node->child1());
1438 // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet.
1439 // Because the instructionTypeSet is contained in globalTypeSet, if we produce a type check for
1440 // type T for the instructionTypeSet, the global type set must also have information for type T.
1441 // So if it the type check succeeds for type T in the instructionTypeSet, a type check for type T
1442 // in the globalTypeSet would've also succeeded.
1443 // (The other direction does not hold in general).
1445 RefPtr<TypeSet> typeSet = node->typeLocation()->m_instructionTypeSet;
1446 RuntimeTypeMask seenTypes = typeSet->seenTypes();
1447 if (typeSet->doesTypeConformTo(TypeAnyInt)) {
1448 if (node->child1()->shouldSpeculateInt32())
1449 fixEdge<Int32Use>(node->child1());
1451 fixEdge<AnyIntUse>(node->child1());
1453 } else if (typeSet->doesTypeConformTo(TypeNumber | TypeAnyInt)) {
1454 fixEdge<NumberUse>(node->child1());
1456 } else if (typeSet->doesTypeConformTo(TypeString)) {
1457 fixEdge<StringUse>(node->child1());
1459 } else if (typeSet->doesTypeConformTo(TypeBoolean)) {
1460 fixEdge<BooleanUse>(node->child1());
1462 } else if (typeSet->doesTypeConformTo(TypeUndefined | TypeNull) && (seenTypes & TypeUndefined) && (seenTypes & TypeNull)) {
1463 fixEdge<OtherUse>(node->child1());
1465 } else if (typeSet->doesTypeConformTo(TypeObject)) {
1466 StructureSet set = typeSet->structureSet();
1467 if (!set.isEmpty()) {
1468 fixEdge<CellUse>(node->child1());
1469 node->convertToCheckStructure(m_graph.addStructureSet(set));
1476 case CreateScopedArguments:
1477 case CreateActivation:
1479 case NewGeneratorFunction: {
1480 fixEdge<CellUse>(node->child1());
1484 case SetFunctionName: {
1485 // The first child is guaranteed to be a cell because op_set_function_name is only used
1486 // on a newly instantiated function object (the first child).
1487 fixEdge<KnownCellUse>(node->child1());
1488 fixEdge<UntypedUse>(node->child2());
1493 fixEdge<KnownCellUse>(node->child1());
1494 fixEdge<KnownInt32Use>(node->child2());
1500 case PutDynamicVar: {
1501 fixEdge<KnownCellUse>(node->child1());
1505 #if !ASSERT_DISABLED
1506 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
1509 case LazyJSConstant:
1510 case DoubleConstant:
1513 case GetArgumentCount:
1517 case GetLocalUnlinked:
1519 case GetGlobalLexicalVariable:
1521 case VarInjectionWatchpoint:
1523 case CheckTypeInfoFlags:
1524 case TailCallInlinedCaller:
1527 case TailCallVarargsInlinedCaller:
1528 case ConstructVarargs:
1529 case CallForwardVarargs:
1530 case ConstructForwardVarargs:
1531 case TailCallForwardVarargs:
1532 case TailCallForwardVarargsInlinedCaller:
1534 case ProfileControlFlow:
1536 case NewArrayBuffer:
1542 case IsArrayConstructor:
1547 case IsObjectOrNull:
1549 case IsRegExpObject:
1550 case CreateDirectArguments:
1551 case CreateClonedArguments:
1555 case TailCallVarargs:
1557 case ThrowReferenceError:
1558 case CountExecution:
1562 case CheckWatchdogTimer:
1563 case LogShadowChickenPrologue:
1564 case LogShadowChickenTail:
1566 case ExtractOSREntryLocal:
1573 case GetByIdWithThis:
1574 case PutByIdWithThis:
1575 case PutByValWithThis:
1576 case GetByValWithThis:
1587 void watchHavingABadTime(Node* node)
1589 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1591 // If this global object is not having a bad time, watch it. We go down this path anytime the code
1592 // does an array allocation. The types of array allocations may change if we start to have a bad
1593 // time. It's easier to reason about this if we know that whenever the types change after we start
1594 // optimizing, the code just gets thrown out. Doing this at FixupPhase is just early enough, since
1595 // prior to this point nobody should have been doing optimizations based on the indexing type of
1597 if (!globalObject->isHavingABadTime())
1598 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1601 template<UseKind useKind>
1602 void createToString(Node* node, Edge& edge)
1604 edge.setNode(m_insertionSet.insertNode(
1605 m_indexInBlock, SpecString, ToString, node->origin,
1606 Edge(edge.node(), useKind)));
1609 template<UseKind useKind>
1610 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
1612 ASSERT(arrayMode == ArrayMode(Array::Generic));
1614 if (!m_graph.canOptimizeStringObjectAccess(node->origin.semantic))
1617 createToString<useKind>(node, node->child1());
1618 arrayMode = ArrayMode(Array::String);
1621 template<UseKind useKind>
1622 bool isStringObjectUse()
1625 case StringObjectUse:
1626 case StringOrStringObjectUse:
1633 template<UseKind useKind>
1634 void convertStringAddUse(Node* node, Edge& edge)
1636 if (useKind == StringUse) {
1637 observeUseKindOnNode<StringUse>(edge.node());
1638 m_insertionSet.insertNode(
1639 m_indexInBlock, SpecNone, Check, node->origin,
1640 Edge(edge.node(), StringUse));
1641 edge.setUseKind(KnownStringUse);
1645 observeUseKindOnNode<useKind>(edge.node());
1646 createToString<useKind>(node, edge);
1649 void convertToMakeRope(Node* node)
1651 node->setOpAndDefaultFlags(MakeRope);
1652 fixupMakeRope(node);
1655 void fixupMakeRope(Node* node)
1657 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1658 Edge& edge = node->children.child(i);
1661 edge.setUseKind(KnownStringUse);
1662 JSString* string = edge->dynamicCastConstant<JSString*>();
1665 if (string->length())
1668 // Don't allow the MakeRope to have zero children.
1669 if (!i && !node->child2())
1672 node->children.removeEdge(i--);
1675 if (!node->child2()) {
1676 ASSERT(!node->child3());
1677 node->convertToIdentity();
1681 void fixupToThis(Node* node)
1683 ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
1685 if (ecmaMode == StrictMode) {
1686 if (node->child1()->shouldSpeculateBoolean()) {
1687 fixEdge<BooleanUse>(node->child1());
1688 node->convertToIdentity();
1692 if (node->child1()->shouldSpeculateInt32()) {
1693 fixEdge<Int32Use>(node->child1());
1694 node->convertToIdentity();
1698 if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
1699 fixEdge<Int52RepUse>(node->child1());
1700 node->convertToIdentity();
1701 node->setResult(NodeResultInt52);
1705 if (node->child1()->shouldSpeculateNumber()) {
1706 fixEdge<DoubleRepUse>(node->child1());
1707 node->convertToIdentity();
1708 node->setResult(NodeResultDouble);
1712 if (node->child1()->shouldSpeculateSymbol()) {
1713 fixEdge<SymbolUse>(node->child1());
1714 node->convertToIdentity();
1718 if (node->child1()->shouldSpeculateStringIdent()) {
1719 fixEdge<StringIdentUse>(node->child1());
1720 node->convertToIdentity();
1724 if (node->child1()->shouldSpeculateString()) {
1725 fixEdge<StringUse>(node->child1());
1726 node->convertToIdentity();
1731 if (node->child1()->shouldSpeculateOther()) {
1732 if (ecmaMode == StrictMode) {
1733 fixEdge<OtherUse>(node->child1());
1734 node->convertToIdentity();
1738 m_insertionSet.insertNode(
1739 m_indexInBlock, SpecNone, Check, node->origin,
1740 Edge(node->child1().node(), OtherUse));
1741 observeUseKindOnNode<OtherUse>(node->child1().node());
1742 m_graph.convertToConstant(
1743 node, m_graph.globalThisObjectFor(node->origin.semantic));
1747 // FIXME: This should cover other use cases but we don't have use kinds for them. It's not critical,
1748 // however, since we cover all the missing cases in constant folding.
1749 // https://bugs.webkit.org/show_bug.cgi?id=157213
1750 if (node->child1()->shouldSpeculateStringObject()) {
1751 fixEdge<StringObjectUse>(node->child1());
1752 node->convertToIdentity();
1756 if (isFinalObjectSpeculation(node->child1()->prediction())) {
1757 fixEdge<FinalObjectUse>(node->child1());
1758 node->convertToIdentity();
1763 void fixupToPrimitive(Node* node)
1765 if (node->child1()->shouldSpeculateInt32()) {
1766 fixEdge<Int32Use>(node->child1());
1767 node->convertToIdentity();
1771 if (node->child1()->shouldSpeculateString()) {
1772 fixEdge<StringUse>(node->child1());
1773 node->convertToIdentity();
1777 if (node->child1()->shouldSpeculateStringObject()
1778 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1779 fixEdge<StringObjectUse>(node->child1());
1780 node->convertToToString();
1784 if (node->child1()->shouldSpeculateStringOrStringObject()
1785 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1786 fixEdge<StringOrStringObjectUse>(node->child1());
1787 node->convertToToString();
1792 void fixupToStringOrCallStringConstructor(Node* node)
1794 if (node->child1()->shouldSpeculateString()) {
1795 fixEdge<StringUse>(node->child1());
1796 node->convertToIdentity();
1800 if (node->child1()->shouldSpeculateStringObject()
1801 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1802 fixEdge<StringObjectUse>(node->child1());
1806 if (node->child1()->shouldSpeculateStringOrStringObject()
1807 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1808 fixEdge<StringOrStringObjectUse>(node->child1());
1812 if (node->child1()->shouldSpeculateCell()) {
1813 fixEdge<CellUse>(node->child1());
1818 bool attemptToMakeFastStringAdd(Node* node)
1820 bool goodToGo = true;
1821 m_graph.doToChildren(
1824 if (edge->shouldSpeculateString())
1826 if (m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1827 if (edge->shouldSpeculateStringObject())
1829 if (edge->shouldSpeculateStringOrStringObject())
1837 m_graph.doToChildren(
1840 if (edge->shouldSpeculateString()) {
1841 convertStringAddUse<StringUse>(node, edge);
1844 ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
1845 if (edge->shouldSpeculateStringObject()) {
1846 convertStringAddUse<StringObjectUse>(node, edge);
1849 if (edge->shouldSpeculateStringOrStringObject()) {
1850 convertStringAddUse<StringOrStringObjectUse>(node, edge);
1853 RELEASE_ASSERT_NOT_REACHED();
1856 convertToMakeRope(node);
1860 void fixupGetAndSetLocalsInBlock(BasicBlock* block)
1864 ASSERT(block->isReachable);
1866 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1867 Node* node = m_currentNode = block->at(m_indexInBlock);
1868 if (node->op() != SetLocal && node->op() != GetLocal)
1871 VariableAccessData* variable = node->variableAccessData();
1872 switch (node->op()) {
1874 switch (variable->flushFormat()) {
1876 node->setResult(NodeResultDouble);
1879 node->setResult(NodeResultInt52);
1887 // NOTE: Any type checks we put here may get hoisted by fixupChecksInBlock(). So, if we
1888 // add new type checking use kind for SetLocals, we need to modify that code as well.
1890 switch (variable->flushFormat()) {
1891 case FlushedJSValue:
1894 fixEdge<DoubleRepUse>(node->child1());
1897 fixEdge<Int32Use>(node->child1());
1900 fixEdge<Int52RepUse>(node->child1());
1903 fixEdge<CellUse>(node->child1());
1905 case FlushedBoolean:
1906 fixEdge<BooleanUse>(node->child1());
1909 RELEASE_ASSERT_NOT_REACHED();
1915 RELEASE_ASSERT_NOT_REACHED();
1919 m_insertionSet.execute(block);
1922 void addStringReplacePrimordialChecks(Node* searchRegExp)
1924 Node* node = m_currentNode;
1926 // Check that structure of searchRegExp is RegExp object
1927 m_insertionSet.insertNode(
1928 m_indexInBlock, SpecNone, Check, node->origin,
1929 Edge(searchRegExp, RegExpObjectUse));
1931 auto emitPrimordialCheckFor = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
1932 unsigned index = m_graph.identifiers().ensure(propertyUID);
1934 Node* actualProperty = m_insertionSet.insertNode(
1935 m_indexInBlock, SpecNone, TryGetById, node->origin,
1936 OpInfo(index), OpInfo(SpecFunction), Edge(searchRegExp, CellUse));
1938 m_insertionSet.insertNode(
1939 m_indexInBlock, SpecNone, CheckCell, node->origin,
1940 OpInfo(m_graph.freeze(primordialProperty)), Edge(actualProperty, CellUse));
1943 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1945 // Check that searchRegExp.exec is the primordial RegExp.prototype.exec
1946 emitPrimordialCheckFor(globalObject->regExpProtoExecFunction(), vm().propertyNames->exec.impl());
1947 // Check that searchRegExp.global is the primordial RegExp.prototype.global
1948 emitPrimordialCheckFor(globalObject->regExpProtoGlobalGetter(), vm().propertyNames->global.impl());
1949 // Check that searchRegExp.unicode is the primordial RegExp.prototype.unicode
1950 emitPrimordialCheckFor(globalObject->regExpProtoUnicodeGetter(), vm().propertyNames->unicode.impl());
1951 // Check that searchRegExp[Symbol.match] is the primordial RegExp.prototype[Symbol.replace]
1952 emitPrimordialCheckFor(globalObject->regExpProtoSymbolReplaceFunction(), vm().propertyNames->replaceSymbol.impl());
1955 Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
1957 ASSERT(arrayMode.isSpecific());
1959 if (arrayMode.type() == Array::String) {
1960 m_insertionSet.insertNode(
1961 m_indexInBlock, SpecNone, Check, origin, Edge(array, StringUse));
1963 // Note that we only need to be using a structure check if we opt for SaneChain, since
1964 // that needs to protect against JSArray's __proto__ being changed.
1965 Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
1967 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1969 if (arrayMode.doesConversion()) {
1971 m_insertionSet.insertNode(
1972 m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
1973 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1975 m_insertionSet.insertNode(
1976 m_indexInBlock, SpecNone, Arrayify, origin,
1977 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1981 m_insertionSet.insertNode(
1982 m_indexInBlock, SpecNone, CheckStructure, origin,
1983 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1985 m_insertionSet.insertNode(
1986 m_indexInBlock, SpecNone, CheckArray, origin,
1987 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1992 if (!storageCheck(arrayMode))
1995 if (arrayMode.usesButterfly()) {
1996 return m_insertionSet.insertNode(
1997 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
2000 return m_insertionSet.insertNode(
2001 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
2002 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
2005 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
2007 Node* node = m_currentNode;
2009 switch (node->arrayMode().type()) {
2010 case Array::ForceExit: {
2011 m_insertionSet.insertNode(
2012 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
2016 case Array::SelectUsingPredictions:
2017 case Array::Unprofiled:
2018 RELEASE_ASSERT_NOT_REACHED();
2021 case Array::Generic:
2025 Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
2029 storageChild = Edge(storage);
2034 bool alwaysUnboxSimplePrimitives()
2039 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
2045 template<UseKind useKind>
2046 void observeUseKindOnNode(Node* node)
2048 if (useKind == UntypedUse)
2050 observeUseKindOnNode(node, useKind);
2053 void observeUseKindOnEdge(Edge edge)
2055 observeUseKindOnNode(edge.node(), edge.useKind());
2058 void observeUseKindOnNode(Node* node, UseKind useKind)
2060 if (node->op() != GetLocal)
2063 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
2064 // https://bugs.webkit.org/show_bug.cgi?id=121518
2066 VariableAccessData* variable = node->variableAccessData();
2070 if (alwaysUnboxSimplePrimitives()
2071 || isInt32Speculation(variable->prediction()))
2072 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2077 case DoubleRepRealUse:
2078 if (variable->doubleFormatState() == UsingDoubleFormat)
2079 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2082 case KnownBooleanUse:
2083 if (alwaysUnboxSimplePrimitives()
2084 || isBooleanSpeculation(variable->prediction()))
2085 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2088 if (isAnyIntSpeculation(variable->prediction()))
2089 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2096 case KnownStringUse:
2098 case StringObjectUse:
2099 case StringOrStringObjectUse:
2100 if (alwaysUnboxSimplePrimitives()
2101 || isCellSpeculation(variable->prediction()))
2102 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2109 template<UseKind useKind>
2110 void fixEdge(Edge& edge)
2112 observeUseKindOnNode<useKind>(edge.node());
2113 edge.setUseKind(useKind);
2116 void speculateForBarrier(Edge value)
2118 // Currently, the DFG won't take advantage of this speculation. But, we want to do it in
2119 // the DFG anyway because if such a speculation would be wrong, we want to know before
2120 // we do an expensive compile.
2122 if (value->shouldSpeculateInt32()) {
2123 insertCheck<Int32Use>(m_indexInBlock, value.node());
2127 if (value->shouldSpeculateBoolean()) {
2128 insertCheck<BooleanUse>(m_indexInBlock, value.node());
2132 if (value->shouldSpeculateOther()) {
2133 insertCheck<OtherUse>(m_indexInBlock, value.node());
2137 if (value->shouldSpeculateNumber()) {
2138 insertCheck<NumberUse>(m_indexInBlock, value.node());
2142 if (value->shouldSpeculateNotCell()) {
2143 insertCheck<NotCellUse>(m_indexInBlock, value.node());
2148 template<UseKind useKind>
2149 void insertCheck(unsigned indexInBlock, Node* node)
2151 observeUseKindOnNode<useKind>(node);
2152 m_insertionSet.insertNode(
2153 indexInBlock, SpecNone, Check, m_currentNode->origin, Edge(node, useKind));
2156 void fixIntConvertingEdge(Edge& edge)
2158 Node* node = edge.node();
2159 if (node->shouldSpeculateInt32OrBoolean()) {
2160 fixIntOrBooleanEdge(edge);
2165 if (node->shouldSpeculateAnyInt())
2166 useKind = Int52RepUse;
2167 else if (node->shouldSpeculateNumber())
2168 useKind = DoubleRepUse;
2170 useKind = NotCellUse;
2171 Node* newNode = m_insertionSet.insertNode(
2172 m_indexInBlock, SpecInt32Only, ValueToInt32, m_currentNode->origin,
2173 Edge(node, useKind));
2174 observeUseKindOnNode(node, useKind);
2176 edge = Edge(newNode, KnownInt32Use);
2179 void fixIntOrBooleanEdge(Edge& edge)
2181 Node* node = edge.node();
2182 if (!node->sawBooleans()) {
2183 fixEdge<Int32Use>(edge);
2188 if (node->shouldSpeculateBoolean())
2189 useKind = BooleanUse;
2191 useKind = UntypedUse;
2192 Node* newNode = m_insertionSet.insertNode(
2193 m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
2194 Edge(node, useKind));
2195 observeUseKindOnNode(node, useKind);
2197 edge = Edge(newNode, Int32Use);
2200 void fixDoubleOrBooleanEdge(Edge& edge)
2202 Node* node = edge.node();
2203 if (!node->sawBooleans()) {
2204 fixEdge<DoubleRepUse>(edge);
2209 if (node->shouldSpeculateBoolean())
2210 useKind = BooleanUse;
2212 useKind = UntypedUse;
2213 Node* newNode = m_insertionSet.insertNode(
2214 m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
2215 Edge(node, useKind));
2216 observeUseKindOnNode(node, useKind);
2218 edge = Edge(newNode, DoubleRepUse);
2221 void truncateConstantToInt32(Edge& edge)
2223 Node* oldNode = edge.node();
2225 JSValue value = oldNode->asJSValue();
2226 if (value.isInt32())
2229 value = jsNumber(JSC::toInt32(value.asNumber()));
2230 ASSERT(value.isInt32());
2231 edge.setNode(m_insertionSet.insertNode(
2232 m_indexInBlock, SpecInt32Only, JSConstant, m_currentNode->origin,
2233 OpInfo(m_graph.freeze(value))));
2236 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
2238 if (mode != SpeculateInt32AndTruncateConstants)
2241 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
2242 if (node->child1()->hasConstant())
2243 truncateConstantToInt32(node->child1());
2245 truncateConstantToInt32(node->child2());
2248 bool attemptToMakeIntegerAdd(Node* node)
2250 AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
2251 if (mode != DontSpeculateInt32) {
2252 truncateConstantsIfNecessary(node, mode);
2253 fixIntOrBooleanEdge(node->child1());
2254 fixIntOrBooleanEdge(node->child2());
2255 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
2256 node->setArithMode(Arith::Unchecked);
2258 node->setArithMode(Arith::CheckOverflow);
2262 if (m_graph.addShouldSpeculateAnyInt(node)) {
2263 fixEdge<Int52RepUse>(node->child1());
2264 fixEdge<Int52RepUse>(node->child2());
2265 node->setArithMode(Arith::CheckOverflow);
2266 node->setResult(NodeResultInt52);
2273 bool attemptToMakeGetArrayLength(Node* node)
2275 if (!isInt32Speculation(node->prediction()))
2277 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
2278 ArrayProfile* arrayProfile =
2279 profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex);
2280 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
2282 ConcurrentJITLocker locker(profiledBlock->m_lock);
2283 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
2284 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
2285 if (arrayMode.type() == Array::Unprofiled) {
2286 // For normal array operations, it makes sense to treat Unprofiled
2287 // accesses as ForceExit and get more data rather than using
2288 // predictions and then possibly ending up with a Generic. But here,
2289 // we treat anything that is Unprofiled as Generic and keep the
2290 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
2291 // profit - from treating the Unprofiled case as
2292 // SelectUsingPredictions.
2293 arrayMode = ArrayMode(Array::SelectUsingPredictions);
2297 arrayMode = arrayMode.refine(
2298 m_graph, node, node->child1()->prediction(), node->prediction());
2300 if (arrayMode.type() == Array::Generic) {
2301 // Check if the input is something that we can't get array length for, but for which we
2302 // could insert some conversions in order to transform it into something that we can do it
2304 if (node->child1()->shouldSpeculateStringObject())
2305 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
2306 else if (node->child1()->shouldSpeculateStringOrStringObject())
2307 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
2310 if (!arrayMode.supportsSelfLength())
2313 convertToGetArrayLength(node, arrayMode);
2317 void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
2319 node->setOp(GetArrayLength);
2320 node->clearFlags(NodeMustGenerate);
2321 fixEdge<KnownCellUse>(node->child1());
2322 node->setArrayMode(arrayMode);
2324 Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
2328 node->child2() = Edge(storage);
2331 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
2333 Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
2334 return m_insertionSet.insertNode(
2335 m_indexInBlock, SpecInt32Only, GetArrayLength, origin,
2336 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
2339 void fixupChecksInBlock(BasicBlock* block)
2343 ASSERT(block->isReachable);
2345 unsigned indexForChecks = UINT_MAX;
2346 NodeOrigin originForChecks;
2347 for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
2348 Node* node = block->at(indexInBlock);
2350 // If this is a node at which we could exit, then save its index. If nodes after this one
2351 // cannot exit, then we will hoist checks to here.
2352 if (node->origin.exitOK) {
2353 indexForChecks = indexInBlock;
2354 originForChecks = node->origin;
2357 originForChecks = originForChecks.withSemantic(node->origin.semantic);
2359 // First, try to relax the representational demands of each node, in order to have
2360 // fewer conversions.
2361 switch (node->op()) {
2364 m_graph.doToChildren(
2367 switch (edge.useKind()) {
2369 case DoubleRepRealUse:
2370 if (edge->hasDoubleResult())
2373 if (edge->hasInt52Result())
2374 edge.setUseKind(Int52RepUse);
2375 else if (edge.useKind() == DoubleRepUse)
2376 edge.setUseKind(NumberUse);
2380 // Nothing we can really do.
2385 if (edge->hasDoubleResult())
2386 edge.setUseKind(DoubleRepUse);
2387 else if (edge->hasInt52Result())
2388 edge.setUseKind(Int52RepUse);
2392 if (edge->hasDoubleResult())
2393 edge.setUseKind(DoubleRepRealUse);
2394 else if (edge->hasInt52Result())
2395 edge.setUseKind(Int52RepUse);
2405 if (node->child1().useKind() == DoubleRepUse
2406 && !node->child1()->hasDoubleResult()) {
2407 node->child1().setUseKind(NumberUse);
2416 // Now, insert type conversions if necessary.
2417 m_graph.doToChildren(
2420 Node* result = nullptr;
2422 switch (edge.useKind()) {
2424 case DoubleRepRealUse:
2425 case DoubleRepAnyIntUse: {
2426 if (edge->hasDoubleResult())
2429 if (edge->isNumberConstant()) {
2430 result = m_insertionSet.insertNode(
2431 indexForChecks, SpecBytecodeDouble, DoubleConstant, originForChecks,
2432 OpInfo(m_graph.freeze(jsDoubleNumber(edge->asNumber()))));
2433 } else if (edge->hasInt52Result()) {
2434 result = m_insertionSet.insertNode(
2435 indexForChecks, SpecAnyIntAsDouble, DoubleRep, originForChecks,
2436 Edge(edge.node(), Int52RepUse));
2439 if (edge->shouldSpeculateDoubleReal())
2440 useKind = RealNumberUse;
2441 else if (edge->shouldSpeculateNumber())
2442 useKind = NumberUse;
2444 useKind = NotCellUse;
2446 result = m_insertionSet.insertNode(
2447 indexForChecks, SpecBytecodeDouble, DoubleRep, originForChecks,
2448 Edge(edge.node(), useKind));
2451 edge.setNode(result);
2456 if (edge->hasInt52Result())
2459 if (edge->isAnyIntConstant()) {
2460 result = m_insertionSet.insertNode(
2461 indexForChecks, SpecAnyInt, Int52Constant, originForChecks,
2462 OpInfo(edge->constant()));
2463 } else if (edge->hasDoubleResult()) {
2464 result = m_insertionSet.insertNode(
2465 indexForChecks, SpecAnyInt, Int52Rep, originForChecks,
2466 Edge(edge.node(), DoubleRepAnyIntUse));
2467 } else if (edge->shouldSpeculateInt32ForArithmetic()) {
2468 result = m_insertionSet.insertNode(
2469 indexForChecks, SpecInt32Only, Int52Rep, originForChecks,
2470 Edge(edge.node(), Int32Use));
2472 result = m_insertionSet.insertNode(
2473 indexForChecks, SpecAnyInt, Int52Rep, originForChecks,
2474 Edge(edge.node(), AnyIntUse));
2477 edge.setNode(result);
2482 if (!edge->hasDoubleResult() && !edge->hasInt52Result())
2485 if (edge->hasDoubleResult()) {
2486 result = m_insertionSet.insertNode(
2487 indexForChecks, SpecBytecodeDouble, ValueRep, originForChecks,
2488 Edge(edge.node(), DoubleRepUse));
2490 result = m_insertionSet.insertNode(
2491 indexForChecks, SpecInt32Only | SpecAnyIntAsDouble, ValueRep,
2492 originForChecks, Edge(edge.node(), Int52RepUse));
2495 edge.setNode(result);
2499 // It's remotely possible that this node cannot do type checks, but we now have a
2500 // type check on this node. We don't have to handle the general form of this
2501 // problem. It only arises when ByteCodeParser emits an immediate SetLocal, rather
2502 // than a delayed one. So, we only worry about those checks that we may have put on
2503 // a SetLocal. Note that "indexForChecks != indexInBlock" is just another way of
2504 // saying "!node->origin.exitOK".
2505 if (indexForChecks != indexInBlock && mayHaveTypeCheck(edge.useKind())) {
2506 UseKind knownUseKind;
2508 switch (edge.useKind()) {
2510 knownUseKind = KnownInt32Use;
2513 knownUseKind = KnownCellUse;
2516 knownUseKind = KnownBooleanUse;
2519 // This can only arise if we have a Check node, and in that case, we can
2520 // just remove the original check.
2521 DFG_ASSERT(m_graph, node, node->op() == Check);
2522 knownUseKind = UntypedUse;
2526 m_insertionSet.insertNode(
2527 indexForChecks, SpecNone, Check, originForChecks, edge);
2529 edge.setUseKind(knownUseKind);
2534 m_insertionSet.execute(block);
2537 BasicBlock* m_block;
2538 unsigned m_indexInBlock;
2539 Node* m_currentNode;
2540 InsertionSet m_insertionSet;
2541 bool m_profitabilityChanged;
2544 bool performFixup(Graph& graph)
2546 return runPhase<FixupPhase>(graph);
2549 } } // namespace JSC::DFG
2551 #endif // ENABLE(DFG_JIT)