2 * Copyright (C) 2012-2017 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 (node->child1()->shouldSpeculateInt32OrBoolean() && node->canSpeculateInt32(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);
220 node->setResult(NodeResultInt32);
221 node->clearFlags(NodeMustGenerate);
224 if (m_graph.unaryArithShouldSpeculateAnyInt(node, FixupPass)) {
225 fixEdge<Int52RepUse>(node->child1());
226 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
227 node->setArithMode(Arith::CheckOverflow);
229 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
230 node->setResult(NodeResultInt52);
231 node->clearFlags(NodeMustGenerate);
234 if (node->child1()->shouldSpeculateNotCell()) {
235 fixDoubleOrBooleanEdge(node->child1());
236 node->setResult(NodeResultDouble);
237 node->clearFlags(NodeMustGenerate);
239 fixEdge<UntypedUse>(node->child1());
244 Edge& leftChild = node->child1();
245 Edge& rightChild = node->child2();
246 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) {
247 fixEdge<UntypedUse>(leftChild);
248 fixEdge<UntypedUse>(rightChild);
249 node->setResult(NodeResultJS);
252 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
253 fixIntOrBooleanEdge(leftChild);
254 fixIntOrBooleanEdge(rightChild);
255 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
256 node->setArithMode(Arith::Unchecked);
257 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())
258 || leftChild.node() == rightChild.node())
259 node->setArithMode(Arith::CheckOverflow);
261 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
264 if (m_graph.binaryArithShouldSpeculateAnyInt(node, FixupPass)) {
265 fixEdge<Int52RepUse>(leftChild);
266 fixEdge<Int52RepUse>(rightChild);
267 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())
268 || leftChild.node() == rightChild.node())
269 node->setArithMode(Arith::CheckOverflow);
271 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
272 node->setResult(NodeResultInt52);
275 fixDoubleOrBooleanEdge(leftChild);
276 fixDoubleOrBooleanEdge(rightChild);
277 node->setResult(NodeResultDouble);
283 Edge& leftChild = node->child1();
284 Edge& rightChild = node->child2();
286 && Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())
287 && m_graph.hasExitSite(node->origin.semantic, BadType)) {
288 fixEdge<UntypedUse>(leftChild);
289 fixEdge<UntypedUse>(rightChild);
290 node->setResult(NodeResultJS);
293 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
294 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) {
295 fixIntOrBooleanEdge(leftChild);
296 fixIntOrBooleanEdge(rightChild);
297 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
298 node->setArithMode(Arith::Unchecked);
299 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
300 node->setArithMode(Arith::CheckOverflow);
302 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
306 // This will cause conversion nodes to be inserted later.
307 fixDoubleOrBooleanEdge(leftChild);
308 fixDoubleOrBooleanEdge(rightChild);
310 // We don't need to do ref'ing on the children because we're stealing them from
311 // the original division.
312 Node* newDivision = m_insertionSet.insertNode(
313 m_indexInBlock, SpecBytecodeDouble, *node);
314 newDivision->setResult(NodeResultDouble);
316 node->setOp(DoubleAsInt32);
317 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
318 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
319 node->setArithMode(Arith::CheckOverflow);
321 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
324 fixDoubleOrBooleanEdge(leftChild);
325 fixDoubleOrBooleanEdge(rightChild);
326 node->setResult(NodeResultDouble);
332 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
333 fixIntOrBooleanEdge(node->child1());
334 fixIntOrBooleanEdge(node->child2());
337 fixDoubleOrBooleanEdge(node->child1());
338 fixDoubleOrBooleanEdge(node->child2());
339 node->setResult(NodeResultDouble);
344 if (node->child1()->shouldSpeculateInt32OrBoolean()
345 && node->canSpeculateInt32(FixupPass)) {
346 fixIntOrBooleanEdge(node->child1());
347 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
348 node->setArithMode(Arith::Unchecked);
350 node->setArithMode(Arith::CheckOverflow);
351 node->clearFlags(NodeMustGenerate);
352 node->setResult(NodeResultInt32);
356 if (node->child1()->shouldSpeculateNotCell()) {
357 fixDoubleOrBooleanEdge(node->child1());
358 node->clearFlags(NodeMustGenerate);
360 fixEdge<UntypedUse>(node->child1());
361 node->setResult(NodeResultDouble);
366 if (node->child2()->shouldSpeculateInt32OrBooleanForArithmetic()) {
367 fixDoubleOrBooleanEdge(node->child1());
368 fixIntOrBooleanEdge(node->child2());
372 fixDoubleOrBooleanEdge(node->child1());
373 fixDoubleOrBooleanEdge(node->child2());
378 node->setResult(NodeResultDouble);
386 if (node->child1()->shouldSpeculateInt32OrBoolean() && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
387 fixIntOrBooleanEdge(node->child1());
388 insertCheck<Int32Use>(node->child1().node());
389 node->convertToIdentity();
392 if (node->child1()->shouldSpeculateNotCell()) {
393 fixDoubleOrBooleanEdge(node->child1());
395 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
396 node->setResult(NodeResultInt32);
397 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
398 node->setArithRoundingMode(Arith::RoundingMode::Int32);
400 node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
402 node->setResult(NodeResultDouble);
403 node->setArithRoundingMode(Arith::RoundingMode::Double);
405 node->clearFlags(NodeMustGenerate);
407 fixEdge<UntypedUse>(node->child1());
417 Edge& child1 = node->child1();
418 if (child1->shouldSpeculateNotCell()) {
419 fixDoubleOrBooleanEdge(child1);
420 node->clearFlags(NodeMustGenerate);
422 fixEdge<UntypedUse>(child1);
427 if (node->child1()->shouldSpeculateBoolean()) {
428 if (node->child1()->result() == NodeResultBoolean) {
429 // This is necessary in case we have a bytecode instruction implemented by:
434 // In that case, CompareEq might have a side-effect. Then, we need to make
435 // sure that we know that Branch does not exit.
436 fixEdge<KnownBooleanUse>(node->child1());
438 fixEdge<BooleanUse>(node->child1());
439 } else if (node->child1()->shouldSpeculateObjectOrOther())
440 fixEdge<ObjectOrOtherUse>(node->child1());
441 else if (node->child1()->shouldSpeculateInt32OrBoolean())
442 fixIntOrBooleanEdge(node->child1());
443 else if (node->child1()->shouldSpeculateNumber())
444 fixEdge<DoubleRepUse>(node->child1());
445 else if (node->child1()->shouldSpeculateString())
446 fixEdge<StringUse>(node->child1());
447 else if (node->child1()->shouldSpeculateStringOrOther())
448 fixEdge<StringOrOtherUse>(node->child1());
450 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
451 if (masqueradesAsUndefinedWatchpoint->isStillValid())
452 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
461 case CompareGreaterEq: {
462 if (node->op() == CompareEq
463 && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
464 fixEdge<BooleanUse>(node->child1());
465 fixEdge<BooleanUse>(node->child2());
466 node->clearFlags(NodeMustGenerate);
469 if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
470 fixIntOrBooleanEdge(node->child1());
471 fixIntOrBooleanEdge(node->child2());
472 node->clearFlags(NodeMustGenerate);
476 && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
477 fixEdge<Int52RepUse>(node->child1());
478 fixEdge<Int52RepUse>(node->child2());
479 node->clearFlags(NodeMustGenerate);
482 if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
483 fixDoubleOrBooleanEdge(node->child1());
484 fixDoubleOrBooleanEdge(node->child2());
486 if (node->op() != CompareEq
487 && node->child1()->shouldSpeculateNotCell()
488 && node->child2()->shouldSpeculateNotCell()) {
489 if (node->child1()->shouldSpeculateNumberOrBoolean())
490 fixDoubleOrBooleanEdge(node->child1());
492 fixEdge<DoubleRepUse>(node->child1());
493 if (node->child2()->shouldSpeculateNumberOrBoolean())
494 fixDoubleOrBooleanEdge(node->child2());
496 fixEdge<DoubleRepUse>(node->child2());
497 node->clearFlags(NodeMustGenerate);
500 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
501 fixEdge<StringIdentUse>(node->child1());
502 fixEdge<StringIdentUse>(node->child2());
503 node->clearFlags(NodeMustGenerate);
506 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
507 fixEdge<StringUse>(node->child1());
508 fixEdge<StringUse>(node->child2());
509 node->clearFlags(NodeMustGenerate);
513 if (node->op() != CompareEq)
515 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
516 fixEdge<SymbolUse>(node->child1());
517 fixEdge<SymbolUse>(node->child2());
518 node->clearFlags(NodeMustGenerate);
521 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
522 fixEdge<ObjectUse>(node->child1());
523 fixEdge<ObjectUse>(node->child2());
524 node->clearFlags(NodeMustGenerate);
528 // If either child can be proved to be Null or Undefined, comparing them is greatly simplified.
529 bool oneArgumentIsUsedAsSpecOther = false;
530 if (node->child1()->isUndefinedOrNullConstant()) {
531 fixEdge<OtherUse>(node->child1());
532 oneArgumentIsUsedAsSpecOther = true;
533 } else if (node->child1()->shouldSpeculateOther()) {
534 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
535 Edge(node->child1().node(), OtherUse));
536 fixEdge<OtherUse>(node->child1());
537 oneArgumentIsUsedAsSpecOther = true;
539 if (node->child2()->isUndefinedOrNullConstant()) {
540 fixEdge<OtherUse>(node->child2());
541 oneArgumentIsUsedAsSpecOther = true;
542 } else if (node->child2()->shouldSpeculateOther()) {
543 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
544 Edge(node->child2().node(), OtherUse));
545 fixEdge<OtherUse>(node->child2());
546 oneArgumentIsUsedAsSpecOther = true;
548 if (oneArgumentIsUsedAsSpecOther) {
549 node->clearFlags(NodeMustGenerate);
553 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
554 fixEdge<ObjectUse>(node->child1());
555 fixEdge<ObjectOrOtherUse>(node->child2());
556 node->clearFlags(NodeMustGenerate);
559 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
560 fixEdge<ObjectOrOtherUse>(node->child1());
561 fixEdge<ObjectUse>(node->child2());
562 node->clearFlags(NodeMustGenerate);
569 case CompareStrictEq: {
570 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
571 fixEdge<BooleanUse>(node->child1());
572 fixEdge<BooleanUse>(node->child2());
575 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
576 fixEdge<Int32Use>(node->child1());
577 fixEdge<Int32Use>(node->child2());
581 && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
582 fixEdge<Int52RepUse>(node->child1());
583 fixEdge<Int52RepUse>(node->child2());
586 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
587 fixEdge<DoubleRepUse>(node->child1());
588 fixEdge<DoubleRepUse>(node->child2());
591 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
592 fixEdge<SymbolUse>(node->child1());
593 fixEdge<SymbolUse>(node->child2());
596 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
597 fixEdge<StringIdentUse>(node->child1());
598 fixEdge<StringIdentUse>(node->child2());
601 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 7) || isFTL(m_graph.m_plan.mode))) {
602 fixEdge<StringUse>(node->child1());
603 fixEdge<StringUse>(node->child2());
606 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
607 if (masqueradesAsUndefinedWatchpoint->isStillValid()) {
609 if (node->child1()->shouldSpeculateObject()) {
610 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
611 fixEdge<ObjectUse>(node->child1());
614 if (node->child2()->shouldSpeculateObject()) {
615 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
616 fixEdge<ObjectUse>(node->child2());
620 } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
621 fixEdge<ObjectUse>(node->child1());
622 fixEdge<ObjectUse>(node->child2());
625 if (node->child1()->shouldSpeculateSymbol()) {
626 fixEdge<SymbolUse>(node->child1());
629 if (node->child2()->shouldSpeculateSymbol()) {
630 fixEdge<SymbolUse>(node->child2());
633 if (node->child1()->shouldSpeculateMisc()) {
634 fixEdge<MiscUse>(node->child1());
637 if (node->child2()->shouldSpeculateMisc()) {
638 fixEdge<MiscUse>(node->child2());
641 if (node->child1()->shouldSpeculateStringIdent()
642 && node->child2()->shouldSpeculateNotStringVar()) {
643 fixEdge<StringIdentUse>(node->child1());
644 fixEdge<NotStringVarUse>(node->child2());
647 if (node->child2()->shouldSpeculateStringIdent()
648 && node->child1()->shouldSpeculateNotStringVar()) {
649 fixEdge<StringIdentUse>(node->child2());
650 fixEdge<NotStringVarUse>(node->child1());
653 if (node->child1()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
654 fixEdge<StringUse>(node->child1());
657 if (node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
658 fixEdge<StringUse>(node->child2());
664 case StringFromCharCode:
665 if (node->child1()->shouldSpeculateInt32())
666 fixEdge<Int32Use>(node->child1());
668 fixEdge<UntypedUse>(node->child1());
672 case StringCharCodeAt: {
673 // Currently we have no good way of refining these.
674 ASSERT(node->arrayMode() == ArrayMode(Array::String));
675 blessArrayOperation(node->child1(), node->child2(), node->child3());
676 fixEdge<KnownCellUse>(node->child1());
677 fixEdge<Int32Use>(node->child2());
682 if (!node->prediction()) {
683 m_insertionSet.insertNode(
684 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
688 node->arrayMode().refine(
690 node->child1()->prediction(),
691 node->child2()->prediction(),
694 blessArrayOperation(node->child1(), node->child2(), node->child3());
696 ArrayMode arrayMode = node->arrayMode();
697 switch (arrayMode.type()) {
698 case Array::Contiguous:
700 if (arrayMode.arrayClass() == Array::OriginalArray
701 && arrayMode.speculation() == Array::InBounds) {
702 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
703 if (globalObject->arrayPrototypeChainIsSane()) {
704 // Check if SaneChain will work on a per-type basis. Note that:
706 // 1) We don't want double arrays to sometimes return undefined, since
707 // that would require a change to the return type and it would pessimise
708 // things a lot. So, we'd only want to do that if we actually had
709 // evidence that we could read from a hole. That's pretty annoying.
710 // Likely the best way to handle that case is with an equivalent of
711 // SaneChain for OutOfBounds. For now we just detect when Undefined and
712 // NaN are indistinguishable according to backwards propagation, and just
713 // use SaneChain in that case. This happens to catch a lot of cases.
715 // 2) We don't want int32 array loads to have to do a hole check just to
716 // coerce to Undefined, since that would mean twice the checks.
718 // This has two implications. First, we have to do more checks than we'd
719 // like. It's unfortunate that we have to do the hole check. Second,
720 // some accesses that hit a hole will now need to take the full-blown
721 // out-of-bounds slow path. We can fix that with:
722 // https://bugs.webkit.org/show_bug.cgi?id=144668
724 bool canDoSaneChain = false;
725 switch (arrayMode.type()) {
726 case Array::Contiguous:
727 // This is happens to be entirely natural. We already would have
728 // returned any JSValue, and now we'll return Undefined. We still do
729 // the check but it doesn't require taking any kind of slow path.
730 canDoSaneChain = true;
734 if (!(node->flags() & NodeBytecodeUsesAsOther)) {
735 // Holes look like NaN already, so if the user doesn't care
736 // about the difference between Undefined and NaN then we can
738 canDoSaneChain = true;
746 if (canDoSaneChain) {
747 m_graph.watchpoints().addLazily(
748 globalObject->arrayPrototype()->structure()->transitionWatchpointSet());
749 m_graph.watchpoints().addLazily(
750 globalObject->objectPrototype()->structure()->transitionWatchpointSet());
751 if (globalObject->arrayPrototypeChainIsSane())
752 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
759 if ((node->prediction() & ~SpecString)
760 || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
761 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
768 arrayMode = node->arrayMode();
769 switch (arrayMode.type()) {
770 case Array::SelectUsingPredictions:
771 case Array::Unprofiled:
772 RELEASE_ASSERT_NOT_REACHED();
775 #if USE(JSVALUE32_64)
776 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
779 case Array::ForceExit:
782 fixEdge<KnownCellUse>(node->child1());
783 fixEdge<Int32Use>(node->child2());
787 switch (arrayMode.type()) {
789 if (!arrayMode.isOutOfBounds())
790 node->setResult(NodeResultDouble);
793 case Array::Float32Array:
794 case Array::Float64Array:
795 node->setResult(NodeResultDouble);
798 case Array::Uint32Array:
799 if (node->shouldSpeculateInt32())
801 if (node->shouldSpeculateAnyInt() && enableInt52())
802 node->setResult(NodeResultInt52);
804 node->setResult(NodeResultDouble);
816 case PutByValAlias: {
817 Edge& child1 = m_graph.varArgChild(node, 0);
818 Edge& child2 = m_graph.varArgChild(node, 1);
819 Edge& child3 = m_graph.varArgChild(node, 2);
822 node->arrayMode().refine(
824 child1->prediction(),
825 child2->prediction(),
826 child3->prediction()));
828 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
830 switch (node->arrayMode().modeForPut().type()) {
831 case Array::SelectUsingPredictions:
832 case Array::SelectUsingArguments:
833 case Array::Unprofiled:
834 case Array::Undecided:
835 RELEASE_ASSERT_NOT_REACHED();
837 case Array::ForceExit:
839 #if USE(JSVALUE32_64)
840 // Due to register pressure on 32-bit, we speculate cell and
841 // ignore the base-is-not-cell case entirely by letting the
842 // baseline JIT handle it.
843 fixEdge<CellUse>(child1);
847 fixEdge<KnownCellUse>(child1);
848 fixEdge<Int32Use>(child2);
849 fixEdge<Int32Use>(child3);
852 fixEdge<KnownCellUse>(child1);
853 fixEdge<Int32Use>(child2);
854 fixEdge<DoubleRepRealUse>(child3);
856 case Array::Int8Array:
857 case Array::Int16Array:
858 case Array::Int32Array:
859 case Array::Uint8Array:
860 case Array::Uint8ClampedArray:
861 case Array::Uint16Array:
862 case Array::Uint32Array:
863 fixEdge<KnownCellUse>(child1);
864 fixEdge<Int32Use>(child2);
865 if (child3->shouldSpeculateInt32())
866 fixIntOrBooleanEdge(child3);
867 else if (child3->shouldSpeculateAnyInt())
868 fixEdge<Int52RepUse>(child3);
870 fixDoubleOrBooleanEdge(child3);
872 case Array::Float32Array:
873 case Array::Float64Array:
874 fixEdge<KnownCellUse>(child1);
875 fixEdge<Int32Use>(child2);
876 fixDoubleOrBooleanEdge(child3);
878 case Array::Contiguous:
879 case Array::ArrayStorage:
880 case Array::SlowPutArrayStorage:
881 fixEdge<KnownCellUse>(child1);
882 fixEdge<Int32Use>(child2);
883 speculateForBarrier(child3);
886 fixEdge<KnownCellUse>(child1);
887 fixEdge<Int32Use>(child2);
894 // May need to refine the array mode in case the value prediction contravenes
895 // the array prediction. For example, we may have evidence showing that the
896 // array is in Int32 mode, but the value we're storing is likely to be a double.
897 // Then we should turn this into a conversion to Double array followed by the
898 // push. On the other hand, we absolutely don't want to refine based on the
899 // base prediction. If it has non-cell garbage in it, then we want that to be
900 // ignored. That's because ArrayPush can't handle any array modes that aren't
901 // array-related - so if refine() turned this into a "Generic" ArrayPush then
902 // that would break things.
904 node->arrayMode().refine(
906 node->child1()->prediction() & SpecCell,
908 node->child2()->prediction()));
909 blessArrayOperation(node->child1(), Edge(), node->child3());
910 fixEdge<KnownCellUse>(node->child1());
912 switch (node->arrayMode().type()) {
914 fixEdge<Int32Use>(node->child2());
917 fixEdge<DoubleRepRealUse>(node->child2());
919 case Array::Contiguous:
920 case Array::ArrayStorage:
921 speculateForBarrier(node->child2());
930 blessArrayOperation(node->child1(), Edge(), node->child2());
931 fixEdge<KnownCellUse>(node->child1());
936 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
937 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
938 if (node->numChildren() == 4)
939 fixEdge<Int32Use>(m_graph.varArgChild(node, 2));
945 fixEdge<KnownCellUse>(node->child1());
947 if (node->child2()->shouldSpeculateRegExpObject()) {
948 fixEdge<RegExpObjectUse>(node->child2());
950 if (node->child3()->shouldSpeculateString())
951 fixEdge<StringUse>(node->child3());
957 case StringReplaceRegExp: {
958 if (node->child2()->shouldSpeculateString()) {
959 m_insertionSet.insertNode(
960 m_indexInBlock, SpecNone, Check, node->origin,
961 Edge(node->child2().node(), StringUse));
962 fixEdge<StringUse>(node->child2());
963 } else if (op == StringReplace) {
964 if (node->child2()->shouldSpeculateRegExpObject())
965 addStringReplacePrimordialChecks(node->child2().node());
967 m_insertionSet.insertNode(
968 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
971 if (node->child1()->shouldSpeculateString()
972 && node->child2()->shouldSpeculateRegExpObject()
973 && node->child3()->shouldSpeculateString()) {
975 fixEdge<StringUse>(node->child1());
976 fixEdge<RegExpObjectUse>(node->child2());
977 fixEdge<StringUse>(node->child3());
984 if (node->child1()->shouldSpeculateBoolean()) {
985 if (node->child1()->result() == NodeResultBoolean) {
986 // This is necessary in case we have a bytecode instruction implemented by:
991 // In that case, CompareEq might have a side-effect. Then, we need to make
992 // sure that we know that Branch does not exit.
993 fixEdge<KnownBooleanUse>(node->child1());
995 fixEdge<BooleanUse>(node->child1());
996 } else if (node->child1()->shouldSpeculateObjectOrOther())
997 fixEdge<ObjectOrOtherUse>(node->child1());
998 else if (node->child1()->shouldSpeculateInt32OrBoolean())
999 fixIntOrBooleanEdge(node->child1());
1000 else if (node->child1()->shouldSpeculateNumber())
1001 fixEdge<DoubleRepUse>(node->child1());
1002 else if (node->child1()->shouldSpeculateString())
1003 fixEdge<StringUse>(node->child1());
1004 else if (node->child1()->shouldSpeculateStringOrOther())
1005 fixEdge<StringOrOtherUse>(node->child1());
1007 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
1008 if (masqueradesAsUndefinedWatchpoint->isStillValid())
1009 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
1015 SwitchData* data = node->switchData();
1016 switch (data->kind) {
1018 if (node->child1()->shouldSpeculateInt32())
1019 fixEdge<Int32Use>(node->child1());
1022 if (node->child1()->shouldSpeculateString())
1023 fixEdge<StringUse>(node->child1());
1026 if (node->child1()->shouldSpeculateStringIdent())
1027 fixEdge<StringIdentUse>(node->child1());
1028 else if (node->child1()->shouldSpeculateString())
1029 fixEdge<StringUse>(node->child1());
1032 if (node->child1()->shouldSpeculateCell())
1033 fixEdge<CellUse>(node->child1());
1034 // else it's fine for this to have UntypedUse; we will handle this by just making
1035 // non-cells take the default case.
1042 fixupToPrimitive(node);
1047 fixupToNumber(node);
1052 case CallStringConstructor: {
1053 fixupToStringOrCallStringConstructor(node);
1057 case NewStringObject: {
1058 fixEdge<KnownStringUse>(node->child1());
1062 case NewArrayWithSpread: {
1063 watchHavingABadTime(node);
1065 BitVector* bitVector = node->bitVector();
1066 for (unsigned i = node->numChildren(); i--;) {
1067 if (bitVector->get(i))
1068 fixEdge<KnownCellUse>(m_graph.m_varArgChildren[node->firstChild() + i]);
1070 fixEdge<UntypedUse>(m_graph.m_varArgChildren[node->firstChild() + i]);
1077 // Note: We care about performing the protocol on our child's global object, not necessarily ours.
1079 watchHavingABadTime(node->child1().node());
1081 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->child1()->origin.semantic);
1082 // When we go down the fast path, we don't consult the prototype chain, so we must prove
1083 // that it doesn't contain any indexed properties, and that any holes will result in
1085 InlineWatchpointSet& objectPrototypeTransition = globalObject->objectPrototype()->structure()->transitionWatchpointSet();
1086 InlineWatchpointSet& arrayPrototypeTransition = globalObject->arrayPrototype()->structure()->transitionWatchpointSet();
1087 if (node->child1()->shouldSpeculateArray()
1088 && arrayPrototypeTransition.isStillValid()
1089 && objectPrototypeTransition.isStillValid()
1090 && globalObject->arrayPrototypeChainIsSane()
1091 && m_graph.isWatchingArrayIteratorProtocolWatchpoint(node->child1().node())
1092 && m_graph.isWatchingHavingABadTimeWatchpoint(node->child1().node())) {
1093 m_graph.watchpoints().addLazily(objectPrototypeTransition);
1094 m_graph.watchpoints().addLazily(arrayPrototypeTransition);
1095 fixEdge<ArrayUse>(node->child1());
1097 fixEdge<CellUse>(node->child1());
1102 watchHavingABadTime(node);
1104 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
1105 node->setIndexingType(
1106 leastUpperBoundOfIndexingTypeAndType(
1107 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
1109 switch (node->indexingType()) {
1110 case ALL_BLANK_INDEXING_TYPES:
1113 case ALL_UNDECIDED_INDEXING_TYPES:
1114 if (node->numChildren()) {
1115 // This will only happen if the children have no type predictions. We
1116 // would have already exited by now, but insert a forced exit just to
1118 m_insertionSet.insertNode(
1119 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
1122 case ALL_INT32_INDEXING_TYPES:
1123 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1124 fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1126 case ALL_DOUBLE_INDEXING_TYPES:
1127 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1128 fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1130 case ALL_CONTIGUOUS_INDEXING_TYPES:
1131 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
1140 case NewTypedArray: {
1141 watchHavingABadTime(node);
1143 if (node->child1()->shouldSpeculateInt32()) {
1144 fixEdge<Int32Use>(node->child1());
1145 node->clearFlags(NodeMustGenerate);
1151 case NewArrayWithSize: {
1152 watchHavingABadTime(node);
1153 fixEdge<Int32Use>(node->child1());
1157 case NewArrayBuffer: {
1158 watchHavingABadTime(node);
1162 case CallObjectConstructor: {
1163 if (node->child1()->shouldSpeculateObject()) {
1164 fixEdge<ObjectUse>(node->child1());
1165 node->convertToIdentity();
1169 fixEdge<UntypedUse>(node->child1());
1178 case PutStructure: {
1179 fixEdge<KnownCellUse>(node->child1());
1184 case GetFromArguments: {
1185 fixEdge<KnownCellUse>(node->child1());
1190 case PutToArguments: {
1191 fixEdge<KnownCellUse>(node->child1());
1192 speculateForBarrier(node->child2());
1200 case GetGlobalObject: {
1201 fixEdge<KnownCellUse>(node->child1());
1205 case AllocatePropertyStorage:
1206 case ReallocatePropertyStorage: {
1207 fixEdge<KnownCellUse>(node->child1());
1211 case NukeStructureAndSetButterfly: {
1212 fixEdge<KnownCellUse>(node->child1());
1217 if (node->child1()->shouldSpeculateCell())
1218 fixEdge<CellUse>(node->child1());
1223 case GetByIdFlush: {
1224 // FIXME: This should be done in the ByteCodeParser based on reading the
1225 // PolymorphicAccess, which will surely tell us that this is a AccessCase::ArrayLength.
1226 // https://bugs.webkit.org/show_bug.cgi?id=154990
1227 if (node->child1()->shouldSpeculateCellOrOther()
1228 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1229 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1230 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1231 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1233 auto uid = m_graph.identifiers()[node->identifierNumber()];
1235 if (uid == vm().propertyNames->length.impl()) {
1236 attemptToMakeGetArrayLength(node);
1240 if (uid == vm().propertyNames->lastIndex.impl()
1241 && node->child1()->shouldSpeculateRegExpObject()) {
1242 node->setOp(GetRegExpObjectLastIndex);
1243 node->clearFlags(NodeMustGenerate);
1244 fixEdge<RegExpObjectUse>(node->child1());
1249 if (node->child1()->shouldSpeculateCell())
1250 fixEdge<CellUse>(node->child1());
1254 case GetByIdWithThis: {
1255 if (node->child1()->shouldSpeculateCell() && node->child2()->shouldSpeculateCell()) {
1256 fixEdge<CellUse>(node->child1());
1257 fixEdge<CellUse>(node->child2());
1264 case PutByIdDirect: {
1265 if (node->child1()->shouldSpeculateCellOrOther()
1266 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1267 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1268 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1269 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1271 auto uid = m_graph.identifiers()[node->identifierNumber()];
1273 if (uid == vm().propertyNames->lastIndex.impl()
1274 && node->child1()->shouldSpeculateRegExpObject()) {
1275 node->setOp(SetRegExpObjectLastIndex);
1276 fixEdge<RegExpObjectUse>(node->child1());
1277 speculateForBarrier(node->child2());
1282 fixEdge<CellUse>(node->child1());
1287 case PutSetterById: {
1288 fixEdge<KnownCellUse>(node->child1());
1289 fixEdge<KnownCellUse>(node->child2());
1293 case PutGetterSetterById: {
1294 fixEdge<KnownCellUse>(node->child1());
1298 case PutGetterByVal:
1299 case PutSetterByVal: {
1300 fixEdge<KnownCellUse>(node->child1());
1301 fixEdge<KnownCellUse>(node->child3());
1305 case GetExecutable: {
1306 fixEdge<FunctionUse>(node->child1());
1310 case OverridesHasInstance:
1311 case CheckStructure:
1314 case GetButterfly: {
1315 fixEdge<CellUse>(node->child1());
1319 case CheckStringIdent: {
1320 fixEdge<StringIdentUse>(node->child1());
1325 case ArrayifyToStructure: {
1326 fixEdge<CellUse>(node->child1());
1328 fixEdge<Int32Use>(node->child2());
1333 case GetGetterSetterByOffset: {
1334 if (!node->child1()->hasStorageResult())
1335 fixEdge<KnownCellUse>(node->child1());
1336 fixEdge<KnownCellUse>(node->child2());
1340 case MultiGetByOffset: {
1341 fixEdge<CellUse>(node->child1());
1346 if (!node->child1()->hasStorageResult())
1347 fixEdge<KnownCellUse>(node->child1());
1348 fixEdge<KnownCellUse>(node->child2());
1349 unsigned index = indexForChecks();
1350 insertInferredTypeCheck(
1351 m_insertionSet, index, originForCheck(index), node->child3().node(),
1352 node->storageAccessData().inferredType);
1353 speculateForBarrier(node->child3());
1357 case MultiPutByOffset: {
1358 fixEdge<CellUse>(node->child1());
1363 if (!(node->child1()->prediction() & ~SpecCell))
1364 fixEdge<CellUse>(node->child1());
1365 fixEdge<CellUse>(node->child2());
1369 case InstanceOfCustom:
1370 fixEdge<CellUse>(node->child2());
1374 if (node->child2()->shouldSpeculateInt32()) {
1375 convertToHasIndexedProperty(node);
1379 fixEdge<CellUse>(node->child1());
1383 case HasOwnProperty: {
1384 fixEdge<ObjectUse>(node->child1());
1385 #if CPU(X86) && USE(JSVALUE32_64)
1386 // We don't have enough registers to do anything interesting on x86.
1387 fixEdge<UntypedUse>(node->child2());
1389 if (node->child2()->shouldSpeculateString())
1390 fixEdge<StringUse>(node->child2());
1391 else if (node->child2()->shouldSpeculateSymbol())
1392 fixEdge<SymbolUse>(node->child2());
1394 fixEdge<UntypedUse>(node->child2());
1400 m_graph.doToChildren(
1403 switch (edge.useKind()) {
1405 if (edge->shouldSpeculateInt32ForArithmetic())
1406 edge.setUseKind(Int32Use);
1411 observeUseKindOnEdge(edge);
1417 // Phantoms are meaningless past Fixup. We recreate them on-demand in the backend.
1422 RELEASE_ASSERT(enableInt52());
1423 node->convertToIdentity();
1424 fixEdge<Int52RepUse>(node->child1());
1425 node->setResult(NodeResultInt52);
1429 case GetArrayLength: {
1430 fixEdge<KnownCellUse>(node->child1());
1434 case GetTypedArrayByteOffset: {
1435 fixEdge<KnownCellUse>(node->child1());
1441 case GetIndexedPropertyStorage:
1443 case CheckTierUpInLoop:
1444 case CheckTierUpAtReturn:
1445 case CheckTierUpAndOSREnter:
1446 case InvalidationPoint:
1449 case ConstantStoragePointer:
1456 case Identity: // This should have been cleaned up.
1457 case BooleanToNumber:
1458 case PhantomNewObject:
1459 case PhantomNewFunction:
1460 case PhantomNewGeneratorFunction:
1461 case PhantomNewAsyncFunction:
1462 case PhantomCreateActivation:
1463 case PhantomDirectArguments:
1464 case PhantomCreateRest:
1466 case PhantomNewArrayWithSpread:
1467 case PhantomClonedArguments:
1468 case GetMyArgumentByVal:
1469 case GetMyArgumentByValOutOfBounds:
1471 case CheckStructureImmediate:
1472 case MaterializeNewObject:
1473 case MaterializeCreateActivation:
1478 case FencedStoreBarrier:
1479 case GetRegExpObjectLastIndex:
1480 case SetRegExpObjectLastIndex:
1481 case RecordRegExpCachedResult:
1482 // These are just nodes that we don't currently expect to see during fixup.
1483 // If we ever wanted to insert them prior to fixup, then we just have to create
1484 // fixup rules for them.
1485 DFG_CRASH(m_graph, node, "Unexpected node during fixup");
1488 case PutGlobalVariable: {
1489 fixEdge<CellUse>(node->child1());
1490 speculateForBarrier(node->child2());
1495 if (node->child1()->shouldSpeculateObject()) {
1496 m_insertionSet.insertNode(
1497 m_indexInBlock, SpecNone, Check, node->origin,
1498 Edge(node->child1().node(), ObjectUse));
1499 m_graph.convertToConstant(node, jsBoolean(true));
1500 observeUseKindOnNode<ObjectUse>(node);
1504 case IsCellWithType: {
1505 fixupIsCellWithType(node);
1509 case GetEnumerableLength: {
1510 fixEdge<CellUse>(node->child1());
1513 case HasGenericProperty: {
1514 fixEdge<CellUse>(node->child2());
1517 case HasStructureProperty: {
1518 fixEdge<StringUse>(node->child2());
1519 fixEdge<KnownCellUse>(node->child3());
1522 case HasIndexedProperty: {
1524 node->arrayMode().refine(
1526 node->child1()->prediction(),
1527 node->child2()->prediction(),
1530 blessArrayOperation(node->child1(), node->child2(), node->child3());
1531 fixEdge<CellUse>(node->child1());
1532 fixEdge<KnownInt32Use>(node->child2());
1535 case GetDirectPname: {
1536 Edge& base = m_graph.varArgChild(node, 0);
1537 Edge& property = m_graph.varArgChild(node, 1);
1538 Edge& index = m_graph.varArgChild(node, 2);
1539 Edge& enumerator = m_graph.varArgChild(node, 3);
1540 fixEdge<CellUse>(base);
1541 fixEdge<KnownCellUse>(property);
1542 fixEdge<KnownInt32Use>(index);
1543 fixEdge<KnownCellUse>(enumerator);
1546 case GetPropertyEnumerator: {
1547 fixEdge<CellUse>(node->child1());
1550 case GetEnumeratorStructurePname: {
1551 fixEdge<KnownCellUse>(node->child1());
1552 fixEdge<KnownInt32Use>(node->child2());
1555 case GetEnumeratorGenericPname: {
1556 fixEdge<KnownCellUse>(node->child1());
1557 fixEdge<KnownInt32Use>(node->child2());
1560 case ToIndexString: {
1561 fixEdge<KnownInt32Use>(node->child1());
1565 // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet.
1566 // Because the instructionTypeSet is contained in globalTypeSet, if we produce a type check for
1567 // type T for the instructionTypeSet, the global type set must also have information for type T.
1568 // So if it the type check succeeds for type T in the instructionTypeSet, a type check for type T
1569 // in the globalTypeSet would've also succeeded.
1570 // (The other direction does not hold in general).
1572 RefPtr<TypeSet> typeSet = node->typeLocation()->m_instructionTypeSet;
1573 RuntimeTypeMask seenTypes = typeSet->seenTypes();
1574 if (typeSet->doesTypeConformTo(TypeAnyInt)) {
1575 if (node->child1()->shouldSpeculateInt32()) {
1576 fixEdge<Int32Use>(node->child1());
1581 if (enableInt52()) {
1582 fixEdge<AnyIntUse>(node->child1());
1587 // Must not perform fixEdge<NumberUse> here since the type set only includes TypeAnyInt. Double values should be logged.
1590 if (typeSet->doesTypeConformTo(TypeNumber | TypeAnyInt)) {
1591 fixEdge<NumberUse>(node->child1());
1593 } else if (typeSet->doesTypeConformTo(TypeString)) {
1594 fixEdge<StringUse>(node->child1());
1596 } else if (typeSet->doesTypeConformTo(TypeBoolean)) {
1597 fixEdge<BooleanUse>(node->child1());
1599 } else if (typeSet->doesTypeConformTo(TypeUndefined | TypeNull) && (seenTypes & TypeUndefined) && (seenTypes & TypeNull)) {
1600 fixEdge<OtherUse>(node->child1());
1602 } else if (typeSet->doesTypeConformTo(TypeObject)) {
1605 ConcurrentJSLocker locker(typeSet->m_lock);
1606 set = typeSet->structureSet(locker);
1608 if (!set.isEmpty()) {
1609 fixEdge<CellUse>(node->child1());
1610 node->convertToCheckStructure(m_graph.addStructureSet(set));
1617 case CreateClonedArguments: {
1618 watchHavingABadTime(node);
1622 case CreateScopedArguments:
1623 case CreateActivation:
1625 case NewGeneratorFunction:
1626 case NewAsyncFunction: {
1627 fixEdge<CellUse>(node->child1());
1631 case SetFunctionName: {
1632 // The first child is guaranteed to be a cell because op_set_function_name is only used
1633 // on a newly instantiated function object (the first child).
1634 fixEdge<KnownCellUse>(node->child1());
1635 fixEdge<UntypedUse>(node->child2());
1640 watchHavingABadTime(node);
1641 fixEdge<KnownInt32Use>(node->child1());
1647 case PutDynamicVar: {
1648 fixEdge<KnownCellUse>(node->child1());
1652 case LogShadowChickenPrologue: {
1653 fixEdge<KnownCellUse>(node->child1());
1656 case LogShadowChickenTail: {
1657 fixEdge<UntypedUse>(node->child1());
1658 fixEdge<KnownCellUse>(node->child2());
1663 if (node->child1().useKind() == MapObjectUse)
1664 fixEdge<MapObjectUse>(node->child1());
1665 else if (node->child1().useKind() == SetObjectUse)
1666 fixEdge<SetObjectUse>(node->child1());
1668 RELEASE_ASSERT_NOT_REACHED();
1671 if (node->child2()->shouldSpeculateBoolean())
1672 fixEdge<BooleanUse>(node->child2());
1673 else if (node->child2()->shouldSpeculateInt32())
1674 fixEdge<Int32Use>(node->child2());
1675 else if (node->child2()->shouldSpeculateSymbol())
1676 fixEdge<SymbolUse>(node->child2());
1677 else if (node->child2()->shouldSpeculateObject())
1678 fixEdge<ObjectUse>(node->child2());
1679 else if (node->child2()->shouldSpeculateString())
1680 fixEdge<StringUse>(node->child2());
1681 else if (node->child2()->shouldSpeculateCell())
1682 fixEdge<CellUse>(node->child2());
1684 fixEdge<UntypedUse>(node->child2());
1686 fixEdge<UntypedUse>(node->child2());
1687 #endif // USE(JSVALUE64)
1689 fixEdge<Int32Use>(node->child3());
1692 case LoadFromJSMapBucket:
1693 fixEdge<KnownCellUse>(node->child1());
1696 case IsNonEmptyMapBucket:
1697 fixEdge<KnownCellUse>(node->child1());
1702 if (node->child1()->shouldSpeculateBoolean()) {
1703 fixEdge<BooleanUse>(node->child1());
1707 if (node->child1()->shouldSpeculateInt32()) {
1708 fixEdge<Int32Use>(node->child1());
1712 if (node->child1()->shouldSpeculateSymbol()) {
1713 fixEdge<SymbolUse>(node->child1());
1717 if (node->child1()->shouldSpeculateObject()) {
1718 fixEdge<ObjectUse>(node->child1());
1722 if (node->child1()->shouldSpeculateString()) {
1723 fixEdge<StringUse>(node->child1());
1727 if (node->child1()->shouldSpeculateCell()) {
1728 fixEdge<CellUse>(node->child1());
1732 fixEdge<UntypedUse>(node->child1());
1734 fixEdge<UntypedUse>(node->child1());
1735 #endif // USE(JSVALUE64)
1739 case DefineDataProperty: {
1740 fixEdge<CellUse>(m_graph.varArgChild(node, 0));
1741 Edge& propertyEdge = m_graph.varArgChild(node, 1);
1742 if (propertyEdge->shouldSpeculateSymbol())
1743 fixEdge<SymbolUse>(propertyEdge);
1744 else if (propertyEdge->shouldSpeculateStringIdent())
1745 fixEdge<StringIdentUse>(propertyEdge);
1746 else if (propertyEdge->shouldSpeculateString())
1747 fixEdge<StringUse>(propertyEdge);
1749 fixEdge<UntypedUse>(propertyEdge);
1750 fixEdge<UntypedUse>(m_graph.varArgChild(node, 2));
1751 fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 3));
1756 // We currently only support StringUse since that will ensure that
1757 // ToLowerCase is a pure operation. If we decide to update this with
1758 // more types in the future, we need to ensure that the clobberize rules
1760 fixEdge<StringUse>(node->child1());
1764 case DefineAccessorProperty: {
1765 fixEdge<CellUse>(m_graph.varArgChild(node, 0));
1766 Edge& propertyEdge = m_graph.varArgChild(node, 1);
1767 if (propertyEdge->shouldSpeculateSymbol())
1768 fixEdge<SymbolUse>(propertyEdge);
1769 else if (propertyEdge->shouldSpeculateStringIdent())
1770 fixEdge<StringIdentUse>(propertyEdge);
1771 else if (propertyEdge->shouldSpeculateString())
1772 fixEdge<StringUse>(propertyEdge);
1774 fixEdge<UntypedUse>(propertyEdge);
1775 fixEdge<CellUse>(m_graph.varArgChild(node, 2));
1776 fixEdge<CellUse>(m_graph.varArgChild(node, 3));
1777 fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 4));
1782 fixupCheckDOM(node);
1786 case CallDOMGetter: {
1787 DOMJIT::CallDOMGetterPatchpoint* patchpoint = node->callDOMGetterData()->patchpoint;
1788 fixEdge<CellUse>(node->child1()); // DOM.
1789 if (patchpoint->requireGlobalObject)
1790 fixEdge<KnownCellUse>(node->child2()); // GlobalObject.
1800 attemptToMakeCallDOM(node);
1805 if (node->child1()->shouldSpeculateInt32() && !node->child2()) {
1806 fixEdge<Int32Use>(node->child1());
1807 node->convertToIdentity();
1811 if (node->child1()->shouldSpeculateString()) {
1812 fixEdge<StringUse>(node->child1());
1813 node->clearFlags(NodeMustGenerate);
1817 fixEdge<Int32Use>(node->child2());
1822 #if !ASSERT_DISABLED
1823 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
1826 case LazyJSConstant:
1827 case DoubleConstant:
1830 case GetArgumentCountIncludingThis:
1835 case GetLocalUnlinked:
1837 case GetGlobalLexicalVariable:
1840 case CheckTypeInfoFlags:
1841 case TailCallInlinedCaller:
1842 case DirectTailCallInlinedCaller:
1844 case DirectConstruct:
1847 case TailCallVarargsInlinedCaller:
1848 case ConstructVarargs:
1849 case CallForwardVarargs:
1850 case ConstructForwardVarargs:
1851 case TailCallForwardVarargs:
1852 case TailCallForwardVarargsInlinedCaller:
1854 case ForwardVarargs:
1855 case ProfileControlFlow:
1860 case IsTypedArrayView:
1865 case IsObjectOrNull:
1867 case CreateDirectArguments:
1871 case DirectTailCall:
1872 case TailCallVarargs:
1874 case ThrowStaticError:
1875 case CountExecution:
1881 case ExtractOSREntryLocal:
1888 case PutByIdWithThis:
1889 case PutByValWithThis:
1890 case GetByValWithThis:
1900 void watchHavingABadTime(Node* node)
1902 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1904 // If this global object is not having a bad time, watch it. We go down this path anytime the code
1905 // does an array allocation. The types of array allocations may change if we start to have a bad
1906 // time. It's easier to reason about this if we know that whenever the types change after we start
1907 // optimizing, the code just gets thrown out. Doing this at FixupPhase is just early enough, since
1908 // prior to this point nobody should have been doing optimizations based on the indexing type of
1910 if (!globalObject->isHavingABadTime()) {
1911 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1912 m_graph.freeze(globalObject);
1916 template<UseKind useKind>
1917 void createToString(Node* node, Edge& edge)
1919 edge.setNode(m_insertionSet.insertNode(
1920 m_indexInBlock, SpecString, ToString, node->origin,
1921 Edge(edge.node(), useKind)));
1924 template<UseKind useKind>
1925 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
1927 ASSERT(arrayMode == ArrayMode(Array::Generic));
1929 if (!m_graph.canOptimizeStringObjectAccess(node->origin.semantic))
1932 createToString<useKind>(node, node->child1());
1933 arrayMode = ArrayMode(Array::String);
1936 template<UseKind useKind>
1937 bool isStringObjectUse()
1940 case StringObjectUse:
1941 case StringOrStringObjectUse:
1948 template<UseKind useKind>
1949 void convertStringAddUse(Node* node, Edge& edge)
1951 if (useKind == StringUse) {
1952 observeUseKindOnNode<StringUse>(edge.node());
1953 m_insertionSet.insertNode(
1954 m_indexInBlock, SpecNone, Check, node->origin,
1955 Edge(edge.node(), StringUse));
1956 edge.setUseKind(KnownStringUse);
1960 observeUseKindOnNode<useKind>(edge.node());
1961 createToString<useKind>(node, edge);
1964 void convertToMakeRope(Node* node)
1966 node->setOpAndDefaultFlags(MakeRope);
1967 fixupMakeRope(node);
1970 void fixupMakeRope(Node* node)
1972 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1973 Edge& edge = node->children.child(i);
1976 edge.setUseKind(KnownStringUse);
1977 JSString* string = edge->dynamicCastConstant<JSString*>(vm());
1980 if (string->length())
1983 // Don't allow the MakeRope to have zero children.
1984 if (!i && !node->child2())
1987 node->children.removeEdge(i--);
1990 if (!node->child2()) {
1991 ASSERT(!node->child3());
1992 node->convertToIdentity();
1996 void fixupIsCellWithType(Node* node)
1998 switch (node->speculatedTypeForQuery()) {
2000 if (node->child1()->shouldSpeculateString()) {
2001 m_insertionSet.insertNode(
2002 m_indexInBlock, SpecNone, Check, node->origin,
2003 Edge(node->child1().node(), StringUse));
2004 m_graph.convertToConstant(node, jsBoolean(true));
2005 observeUseKindOnNode<StringUse>(node);
2010 case SpecProxyObject:
2011 if (node->child1()->shouldSpeculateProxyObject()) {
2012 m_insertionSet.insertNode(
2013 m_indexInBlock, SpecNone, Check, node->origin,
2014 Edge(node->child1().node(), ProxyObjectUse));
2015 m_graph.convertToConstant(node, jsBoolean(true));
2016 observeUseKindOnNode<ProxyObjectUse>(node);
2021 case SpecRegExpObject:
2022 if (node->child1()->shouldSpeculateRegExpObject()) {
2023 m_insertionSet.insertNode(
2024 m_indexInBlock, SpecNone, Check, node->origin,
2025 Edge(node->child1().node(), RegExpObjectUse));
2026 m_graph.convertToConstant(node, jsBoolean(true));
2027 observeUseKindOnNode<RegExpObjectUse>(node);
2033 if (node->child1()->shouldSpeculateArray()) {
2034 m_insertionSet.insertNode(
2035 m_indexInBlock, SpecNone, Check, node->origin,
2036 Edge(node->child1().node(), ArrayUse));
2037 m_graph.convertToConstant(node, jsBoolean(true));
2038 observeUseKindOnNode<ArrayUse>(node);
2043 case SpecDerivedArray:
2044 if (node->child1()->shouldSpeculateDerivedArray()) {
2045 m_insertionSet.insertNode(
2046 m_indexInBlock, SpecNone, Check, node->origin,
2047 Edge(node->child1().node(), DerivedArrayUse));
2048 m_graph.convertToConstant(node, jsBoolean(true));
2049 observeUseKindOnNode<DerivedArrayUse>(node);
2055 if (node->child1()->shouldSpeculateCell()) {
2056 fixEdge<CellUse>(node->child1());
2060 if (node->child1()->shouldSpeculateNotCell()) {
2061 m_insertionSet.insertNode(
2062 m_indexInBlock, SpecNone, Check, node->origin,
2063 Edge(node->child1().node(), NotCellUse));
2064 m_graph.convertToConstant(node, jsBoolean(false));
2065 observeUseKindOnNode<NotCellUse>(node);
2070 void fixupToThis(Node* node)
2072 ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
2074 if (ecmaMode == StrictMode) {
2075 if (node->child1()->shouldSpeculateBoolean()) {
2076 fixEdge<BooleanUse>(node->child1());
2077 node->convertToIdentity();
2081 if (node->child1()->shouldSpeculateInt32()) {
2082 fixEdge<Int32Use>(node->child1());
2083 node->convertToIdentity();
2087 if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
2088 fixEdge<Int52RepUse>(node->child1());
2089 node->convertToIdentity();
2090 node->setResult(NodeResultInt52);
2094 if (node->child1()->shouldSpeculateNumber()) {
2095 fixEdge<DoubleRepUse>(node->child1());
2096 node->convertToIdentity();
2097 node->setResult(NodeResultDouble);
2101 if (node->child1()->shouldSpeculateSymbol()) {
2102 fixEdge<SymbolUse>(node->child1());
2103 node->convertToIdentity();
2107 if (node->child1()->shouldSpeculateStringIdent()) {
2108 fixEdge<StringIdentUse>(node->child1());
2109 node->convertToIdentity();
2113 if (node->child1()->shouldSpeculateString()) {
2114 fixEdge<StringUse>(node->child1());
2115 node->convertToIdentity();
2120 if (node->child1()->shouldSpeculateOther()) {
2121 if (ecmaMode == StrictMode) {
2122 fixEdge<OtherUse>(node->child1());
2123 node->convertToIdentity();
2127 m_insertionSet.insertNode(
2128 m_indexInBlock, SpecNone, Check, node->origin,
2129 Edge(node->child1().node(), OtherUse));
2130 observeUseKindOnNode<OtherUse>(node->child1().node());
2131 m_graph.convertToConstant(
2132 node, m_graph.globalThisObjectFor(node->origin.semantic));
2136 // FIXME: This should cover other use cases but we don't have use kinds for them. It's not critical,
2137 // however, since we cover all the missing cases in constant folding.
2138 // https://bugs.webkit.org/show_bug.cgi?id=157213
2139 if (node->child1()->shouldSpeculateStringObject()) {
2140 fixEdge<StringObjectUse>(node->child1());
2141 node->convertToIdentity();
2145 if (isFinalObjectSpeculation(node->child1()->prediction())) {
2146 fixEdge<FinalObjectUse>(node->child1());
2147 node->convertToIdentity();
2152 void fixupToPrimitive(Node* node)
2154 if (node->child1()->shouldSpeculateInt32()) {
2155 fixEdge<Int32Use>(node->child1());
2156 node->convertToIdentity();
2160 if (node->child1()->shouldSpeculateString()) {
2161 fixEdge<StringUse>(node->child1());
2162 node->convertToIdentity();
2166 if (node->child1()->shouldSpeculateStringObject()
2167 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2168 fixEdge<StringObjectUse>(node->child1());
2169 node->convertToToString();
2173 if (node->child1()->shouldSpeculateStringOrStringObject()
2174 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2175 fixEdge<StringOrStringObjectUse>(node->child1());
2176 node->convertToToString();
2181 void fixupToNumber(Node* node)
2183 // If the prediction of the child is Number, we attempt to convert ToNumber to Identity.
2184 if (node->child1()->shouldSpeculateNumber()) {
2185 if (isInt32Speculation(node->getHeapPrediction())) {
2186 // If the both predictions of this node and the child is Int32, we just convert ToNumber to Identity, that's simple.
2187 if (node->child1()->shouldSpeculateInt32()) {
2188 fixEdge<Int32Use>(node->child1());
2189 node->convertToIdentity();
2193 // 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.
2194 // 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.
2195 fixEdge<DoubleRepUse>(node->child1());
2196 node->setOp(DoubleAsInt32);
2197 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
2198 node->setArithMode(Arith::CheckOverflow);
2200 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
2204 fixEdge<DoubleRepUse>(node->child1());
2205 node->convertToIdentity();
2206 node->setResult(NodeResultDouble);
2210 fixEdge<UntypedUse>(node->child1());
2211 node->setResult(NodeResultJS);
2214 void fixupToStringOrCallStringConstructor(Node* node)
2216 if (node->child1()->shouldSpeculateString()) {
2217 fixEdge<StringUse>(node->child1());
2218 node->convertToIdentity();
2222 if (node->child1()->shouldSpeculateStringObject()
2223 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2224 fixEdge<StringObjectUse>(node->child1());
2228 if (node->child1()->shouldSpeculateStringOrStringObject()
2229 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2230 fixEdge<StringOrStringObjectUse>(node->child1());
2234 if (node->child1()->shouldSpeculateCell()) {
2235 fixEdge<CellUse>(node->child1());
2239 // ToString(Symbol) throws an error. So if the child1 can include Symbols,
2240 // we need to care about it in the clobberize. In the following case,
2241 // since NotCellUse edge filter is used and this edge filters Symbols,
2242 // we can say that ToString never throws an error!
2243 if (node->child1()->shouldSpeculateNotCell()) {
2244 fixEdge<NotCellUse>(node->child1());
2245 node->clearFlags(NodeMustGenerate);
2250 bool attemptToMakeFastStringAdd(Node* node)
2252 bool goodToGo = true;
2253 m_graph.doToChildren(
2256 if (edge->shouldSpeculateString())
2258 if (m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
2259 if (edge->shouldSpeculateStringObject())
2261 if (edge->shouldSpeculateStringOrStringObject())
2269 m_graph.doToChildren(
2272 if (edge->shouldSpeculateString()) {
2273 convertStringAddUse<StringUse>(node, edge);
2276 ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
2277 if (edge->shouldSpeculateStringObject()) {
2278 convertStringAddUse<StringObjectUse>(node, edge);
2281 if (edge->shouldSpeculateStringOrStringObject()) {
2282 convertStringAddUse<StringOrStringObjectUse>(node, edge);
2285 RELEASE_ASSERT_NOT_REACHED();
2288 convertToMakeRope(node);
2292 void fixupGetAndSetLocalsInBlock(BasicBlock* block)
2296 ASSERT(block->isReachable);
2298 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
2299 Node* node = m_currentNode = block->at(m_indexInBlock);
2300 if (node->op() != SetLocal && node->op() != GetLocal)
2303 VariableAccessData* variable = node->variableAccessData();
2304 switch (node->op()) {
2306 switch (variable->flushFormat()) {
2308 node->setResult(NodeResultDouble);
2311 node->setResult(NodeResultInt52);
2319 // NOTE: Any type checks we put here may get hoisted by fixupChecksInBlock(). So, if we
2320 // add new type checking use kind for SetLocals, we need to modify that code as well.
2322 switch (variable->flushFormat()) {
2323 case FlushedJSValue:
2326 fixEdge<DoubleRepUse>(node->child1());
2329 fixEdge<Int32Use>(node->child1());
2332 fixEdge<Int52RepUse>(node->child1());
2335 fixEdge<CellUse>(node->child1());
2337 case FlushedBoolean:
2338 fixEdge<BooleanUse>(node->child1());
2341 RELEASE_ASSERT_NOT_REACHED();
2347 RELEASE_ASSERT_NOT_REACHED();
2351 m_insertionSet.execute(block);
2354 void addStringReplacePrimordialChecks(Node* searchRegExp)
2356 Node* node = m_currentNode;
2358 // Check that structure of searchRegExp is RegExp object
2359 m_insertionSet.insertNode(
2360 m_indexInBlock, SpecNone, Check, node->origin,
2361 Edge(searchRegExp, RegExpObjectUse));
2363 auto emitPrimordialCheckFor = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2364 unsigned index = m_graph.identifiers().ensure(propertyUID);
2366 Node* actualProperty = m_insertionSet.insertNode(
2367 m_indexInBlock, SpecNone, TryGetById, node->origin,
2368 OpInfo(index), OpInfo(SpecFunction), Edge(searchRegExp, CellUse));
2370 m_insertionSet.insertNode(
2371 m_indexInBlock, SpecNone, CheckCell, node->origin,
2372 OpInfo(m_graph.freeze(primordialProperty)), Edge(actualProperty, CellUse));
2375 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
2377 // Check that searchRegExp.exec is the primordial RegExp.prototype.exec
2378 emitPrimordialCheckFor(globalObject->regExpProtoExecFunction(), vm().propertyNames->exec.impl());
2379 // Check that searchRegExp.global is the primordial RegExp.prototype.global
2380 emitPrimordialCheckFor(globalObject->regExpProtoGlobalGetter(), vm().propertyNames->global.impl());
2381 // Check that searchRegExp.unicode is the primordial RegExp.prototype.unicode
2382 emitPrimordialCheckFor(globalObject->regExpProtoUnicodeGetter(), vm().propertyNames->unicode.impl());
2383 // Check that searchRegExp[Symbol.match] is the primordial RegExp.prototype[Symbol.replace]
2384 emitPrimordialCheckFor(globalObject->regExpProtoSymbolReplaceFunction(), vm().propertyNames->replaceSymbol.impl());
2387 Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
2389 ASSERT(arrayMode.isSpecific());
2391 if (arrayMode.type() == Array::String) {
2392 m_insertionSet.insertNode(
2393 m_indexInBlock, SpecNone, Check, origin, Edge(array, StringUse));
2395 // Note that we only need to be using a structure check if we opt for SaneChain, since
2396 // that needs to protect against JSArray's __proto__ being changed.
2397 Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
2399 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
2401 if (arrayMode.doesConversion()) {
2403 m_insertionSet.insertNode(
2404 m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
2405 OpInfo(m_graph.registerStructure(structure)), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
2407 m_insertionSet.insertNode(
2408 m_indexInBlock, SpecNone, Arrayify, origin,
2409 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
2413 m_insertionSet.insertNode(
2414 m_indexInBlock, SpecNone, CheckStructure, origin,
2415 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
2417 m_insertionSet.insertNode(
2418 m_indexInBlock, SpecNone, CheckArray, origin,
2419 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
2424 if (!storageCheck(arrayMode))
2427 if (arrayMode.usesButterfly()) {
2428 return m_insertionSet.insertNode(
2429 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
2432 return m_insertionSet.insertNode(
2433 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
2434 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
2437 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
2439 Node* node = m_currentNode;
2441 switch (node->arrayMode().type()) {
2442 case Array::ForceExit: {
2443 m_insertionSet.insertNode(
2444 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
2448 case Array::SelectUsingPredictions:
2449 case Array::Unprofiled:
2450 RELEASE_ASSERT_NOT_REACHED();
2453 case Array::Generic:
2457 Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
2461 storageChild = Edge(storage);
2466 bool alwaysUnboxSimplePrimitives()
2471 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
2477 template<UseKind useKind>
2478 void observeUseKindOnNode(Node* node)
2480 if (useKind == UntypedUse)
2482 observeUseKindOnNode(node, useKind);
2485 void observeUseKindOnEdge(Edge edge)
2487 observeUseKindOnNode(edge.node(), edge.useKind());
2490 void observeUseKindOnNode(Node* node, UseKind useKind)
2492 if (node->op() != GetLocal)
2495 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
2496 // https://bugs.webkit.org/show_bug.cgi?id=121518
2498 VariableAccessData* variable = node->variableAccessData();
2502 if (alwaysUnboxSimplePrimitives()
2503 || isInt32Speculation(variable->prediction()))
2504 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2509 case DoubleRepRealUse:
2510 if (variable->doubleFormatState() == UsingDoubleFormat)
2511 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2514 case KnownBooleanUse:
2515 if (alwaysUnboxSimplePrimitives()
2516 || isBooleanSpeculation(variable->prediction()))
2517 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2520 if (isAnyIntSpeculation(variable->prediction()))
2521 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2528 case KnownStringUse:
2530 case StringObjectUse:
2531 case StringOrStringObjectUse:
2532 if (alwaysUnboxSimplePrimitives()
2533 || isCellSpeculation(variable->prediction()))
2534 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2541 template<UseKind useKind>
2542 void fixEdge(Edge& edge)
2544 observeUseKindOnNode<useKind>(edge.node());
2545 edge.setUseKind(useKind);
2548 unsigned indexForChecks()
2550 unsigned index = m_indexInBlock;
2551 while (!m_block->at(index)->origin.exitOK)
2556 NodeOrigin originForCheck(unsigned index)
2558 return m_block->at(index)->origin.withSemantic(m_currentNode->origin.semantic);
2561 void speculateForBarrier(Edge value)
2563 // Currently, the DFG won't take advantage of this speculation. But, we want to do it in
2564 // the DFG anyway because if such a speculation would be wrong, we want to know before
2565 // we do an expensive compile.
2567 if (value->shouldSpeculateInt32()) {
2568 insertCheck<Int32Use>(value.node());
2572 if (value->shouldSpeculateBoolean()) {
2573 insertCheck<BooleanUse>(value.node());
2577 if (value->shouldSpeculateOther()) {
2578 insertCheck<OtherUse>(value.node());
2582 if (value->shouldSpeculateNumber()) {
2583 insertCheck<NumberUse>(value.node());
2587 if (value->shouldSpeculateNotCell()) {
2588 insertCheck<NotCellUse>(value.node());
2593 template<UseKind useKind>
2594 void insertCheck(Node* node)
2596 observeUseKindOnNode<useKind>(node);
2597 unsigned index = indexForChecks();
2598 m_insertionSet.insertNode(index, SpecNone, Check, originForCheck(index), Edge(node, useKind));
2601 void fixIntConvertingEdge(Edge& edge)
2603 Node* node = edge.node();
2604 if (node->shouldSpeculateInt32OrBoolean()) {
2605 fixIntOrBooleanEdge(edge);
2610 if (node->shouldSpeculateAnyInt())
2611 useKind = Int52RepUse;
2612 else if (node->shouldSpeculateNumber())
2613 useKind = DoubleRepUse;
2615 useKind = NotCellUse;
2616 Node* newNode = m_insertionSet.insertNode(
2617 m_indexInBlock, SpecInt32Only, ValueToInt32, m_currentNode->origin,
2618 Edge(node, useKind));
2619 observeUseKindOnNode(node, useKind);
2621 edge = Edge(newNode, KnownInt32Use);
2624 void fixIntOrBooleanEdge(Edge& edge)
2626 Node* node = edge.node();
2627 if (!node->sawBooleans()) {
2628 fixEdge<Int32Use>(edge);
2633 if (node->shouldSpeculateBoolean())
2634 useKind = BooleanUse;
2636 useKind = UntypedUse;
2637 Node* newNode = m_insertionSet.insertNode(
2638 m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
2639 Edge(node, useKind));
2640 observeUseKindOnNode(node, useKind);
2642 edge = Edge(newNode, Int32Use);
2645 void fixDoubleOrBooleanEdge(Edge& edge)
2647 Node* node = edge.node();
2648 if (!node->sawBooleans()) {
2649 fixEdge<DoubleRepUse>(edge);
2654 if (node->shouldSpeculateBoolean())
2655 useKind = BooleanUse;
2657 useKind = UntypedUse;
2658 Node* newNode = m_insertionSet.insertNode(
2659 m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
2660 Edge(node, useKind));
2661 observeUseKindOnNode(node, useKind);
2663 edge = Edge(newNode, DoubleRepUse);
2666 void truncateConstantToInt32(Edge& edge)
2668 Node* oldNode = edge.node();
2670 JSValue value = oldNode->asJSValue();
2671 if (value.isInt32())
2674 value = jsNumber(JSC::toInt32(value.asNumber()));
2675 ASSERT(value.isInt32());
2676 edge.setNode(m_insertionSet.insertNode(
2677 m_indexInBlock, SpecInt32Only, JSConstant, m_currentNode->origin,
2678 OpInfo(m_graph.freeze(value))));
2681 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
2683 if (mode != SpeculateInt32AndTruncateConstants)
2686 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
2687 if (node->child1()->hasConstant())
2688 truncateConstantToInt32(node->child1());
2690 truncateConstantToInt32(node->child2());
2693 bool attemptToMakeIntegerAdd(Node* node)
2695 AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
2696 if (mode != DontSpeculateInt32) {
2697 truncateConstantsIfNecessary(node, mode);
2698 fixIntOrBooleanEdge(node->child1());
2699 fixIntOrBooleanEdge(node->child2());
2700 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
2701 node->setArithMode(Arith::Unchecked);
2703 node->setArithMode(Arith::CheckOverflow);
2707 if (m_graph.addShouldSpeculateAnyInt(node)) {
2708 fixEdge<Int52RepUse>(node->child1());
2709 fixEdge<Int52RepUse>(node->child2());
2710 node->setArithMode(Arith::CheckOverflow);
2711 node->setResult(NodeResultInt52);
2718 bool attemptToMakeGetArrayLength(Node* node)
2720 if (!isInt32Speculation(node->prediction()))
2722 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
2723 ArrayProfile* arrayProfile =
2724 profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex);
2725 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
2727 ConcurrentJSLocker locker(profiledBlock->m_lock);
2728 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
2729 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
2730 if (arrayMode.type() == Array::Unprofiled) {
2731 // For normal array operations, it makes sense to treat Unprofiled
2732 // accesses as ForceExit and get more data rather than using
2733 // predictions and then possibly ending up with a Generic. But here,
2734 // we treat anything that is Unprofiled as Generic and keep the
2735 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
2736 // profit - from treating the Unprofiled case as
2737 // SelectUsingPredictions.
2738 arrayMode = ArrayMode(Array::SelectUsingPredictions);
2742 arrayMode = arrayMode.refine(
2743 m_graph, node, node->child1()->prediction(), node->prediction());
2745 if (arrayMode.type() == Array::Generic) {
2746 // Check if the input is something that we can't get array length for, but for which we
2747 // could insert some conversions in order to transform it into something that we can do it
2749 if (node->child1()->shouldSpeculateStringObject())
2750 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
2751 else if (node->child1()->shouldSpeculateStringOrStringObject())
2752 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
2755 if (!arrayMode.supportsSelfLength())
2758 convertToGetArrayLength(node, arrayMode);
2762 void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
2764 node->setOp(GetArrayLength);
2765 node->clearFlags(NodeMustGenerate);
2766 fixEdge<KnownCellUse>(node->child1());
2767 node->setArrayMode(arrayMode);
2769 Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
2773 node->child2() = Edge(storage);
2776 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
2778 Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
2779 return m_insertionSet.insertNode(
2780 m_indexInBlock, SpecInt32Only, GetArrayLength, origin,
2781 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
2784 void convertToHasIndexedProperty(Node* node)
2786 node->setOp(HasIndexedProperty);
2787 node->clearFlags(NodeMustGenerate);
2789 node->arrayMode().refine(
2791 node->child1()->prediction(),
2792 node->child2()->prediction(),
2794 node->setInternalMethodType(PropertySlot::InternalMethodType::HasProperty);
2796 blessArrayOperation(node->child1(), node->child2(), node->child3());
2798 fixEdge<CellUse>(node->child1());
2799 fixEdge<Int32Use>(node->child2());
2802 bool attemptToMakeCallDOM(Node* node)
2804 if (m_graph.hasExitSite(node->origin.semantic, BadType))
2807 const DOMJIT::Signature* signature = node->signature();
2813 bool shouldConvertToCallDOM = true;
2814 m_graph.doToChildren(node, [&](Edge& edge) {
2815 // Callee. Ignore this. DFGByteCodeParser already emit appropriate checks.
2821 if (edge->shouldSpeculateNotCell())
2822 shouldConvertToCallDOM = false;
2824 switch (signature->arguments[index - 2]) {
2826 if (edge->shouldSpeculateNotString())
2827 shouldConvertToCallDOM = false;
2830 if (edge->shouldSpeculateNotInt32())
2831 shouldConvertToCallDOM = false;
2834 if (edge->shouldSpeculateNotBoolean())
2835 shouldConvertToCallDOM = false;
2838 RELEASE_ASSERT_NOT_REACHED();
2844 if (!shouldConvertToCallDOM)
2848 Node* thisNode = m_graph.varArgChild(node, 1).node();
2849 Ref<DOMJIT::Patchpoint> checkDOMPatchpoint = signature->checkDOM();
2850 m_graph.m_domJITPatchpoints.append(checkDOMPatchpoint.ptr());
2851 Node* checkDOM = m_insertionSet.insertNode(m_indexInBlock, SpecNone, CheckDOM, node->origin, OpInfo(checkDOMPatchpoint.ptr()), OpInfo(signature->classInfo), Edge(thisNode));
2852 node->convertToCallDOM(m_graph);
2853 fixupCheckDOM(checkDOM);
2858 void fixupCheckDOM(Node* node)
2860 fixEdge<CellUse>(node->child1());
2863 void fixupCallDOM(Node* node)
2865 const DOMJIT::Signature* signature = node->signature();
2866 auto fixup = [&](Edge& edge, unsigned argumentIndex) {
2869 switch (signature->arguments[argumentIndex]) {
2871 fixEdge<StringUse>(edge);
2874 fixEdge<Int32Use>(edge);
2877 fixEdge<BooleanUse>(edge);
2880 RELEASE_ASSERT_NOT_REACHED();
2884 fixEdge<CellUse>(node->child1()); // DOM.
2885 fixup(node->child2(), 0);
2886 fixup(node->child3(), 1);
2889 void fixupChecksInBlock(BasicBlock* block)
2893 ASSERT(block->isReachable);
2895 unsigned indexForChecks = UINT_MAX;
2896 NodeOrigin originForChecks;
2897 for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
2898 Node* node = block->at(indexInBlock);
2900 // If this is a node at which we could exit, then save its index. If nodes after this one
2901 // cannot exit, then we will hoist checks to here.
2902 if (node->origin.exitOK) {
2903 indexForChecks = indexInBlock;
2904 originForChecks = node->origin;
2907 originForChecks = originForChecks.withSemantic(node->origin.semantic);
2909 // First, try to relax the representational demands of each node, in order to have
2910 // fewer conversions.
2911 switch (node->op()) {
2914 m_graph.doToChildren(
2917 switch (edge.useKind()) {
2919 case DoubleRepRealUse:
2920 if (edge->hasDoubleResult())
2923 if (edge->hasInt52Result())
2924 edge.setUseKind(Int52RepUse);
2925 else if (edge.useKind() == DoubleRepUse)
2926 edge.setUseKind(NumberUse);
2930 // Nothing we can really do.
2935 if (edge->hasDoubleResult())
2936 edge.setUseKind(DoubleRepUse);
2937 else if (edge->hasInt52Result())
2938 edge.setUseKind(Int52RepUse);
2942 if (edge->hasDoubleResult())
2943 edge.setUseKind(DoubleRepRealUse);
2944 else if (edge->hasInt52Result())
2945 edge.setUseKind(Int52RepUse);
2955 if (node->child1().useKind() == DoubleRepUse
2956 && !node->child1()->hasDoubleResult()) {
2957 node->child1().setUseKind(NumberUse);
2966 // Now, insert type conversions if necessary.
2967 m_graph.doToChildren(
2970 Node* result = nullptr;
2972 switch (edge.useKind()) {
2974 case DoubleRepRealUse:
2975 case DoubleRepAnyIntUse: {
2976 if (edge->hasDoubleResult())
2979 if (edge->isNumberConstant()) {
2980 result = m_insertionSet.insertNode(
2981 indexForChecks, SpecBytecodeDouble, DoubleConstant, originForChecks,
2982 OpInfo(m_graph.freeze(jsDoubleNumber(edge->asNumber()))));
2983 } else if (edge->hasInt52Result()) {
2984 result = m_insertionSet.insertNode(
2985 indexForChecks, SpecAnyIntAsDouble, DoubleRep, originForChecks,
2986 Edge(edge.node(), Int52RepUse));
2989 if (edge->shouldSpeculateDoubleReal())
2990 useKind = RealNumberUse;
2991 else if (edge->shouldSpeculateNumber())
2992 useKind = NumberUse;
2994 useKind = NotCellUse;
2996 result = m_insertionSet.insertNode(
2997 indexForChecks, SpecBytecodeDouble, DoubleRep, originForChecks,
2998 Edge(edge.node(), useKind));
3001 edge.setNode(result);
3006 if (edge->hasInt52Result())
3009 if (edge->isAnyIntConstant()) {
3010 result = m_insertionSet.insertNode(
3011 indexForChecks, SpecAnyInt, Int52Constant, originForChecks,
3012 OpInfo(edge->constant()));
3013 } else if (edge->hasDoubleResult()) {
3014 result = m_insertionSet.insertNode(
3015 indexForChecks, SpecAnyInt, Int52Rep, originForChecks,
3016 Edge(edge.node(), DoubleRepAnyIntUse));
3017 } else if (edge->shouldSpeculateInt32ForArithmetic()) {
3018 result = m_insertionSet.insertNode(
3019 indexForChecks, SpecInt32Only, Int52Rep, originForChecks,
3020 Edge(edge.node(), Int32Use));
3022 result = m_insertionSet.insertNode(
3023 indexForChecks, SpecAnyInt, Int52Rep, originForChecks,
3024 Edge(edge.node(), AnyIntUse));
3027 edge.setNode(result);
3032 if (!edge->hasDoubleResult() && !edge->hasInt52Result())
3035 if (edge->hasDoubleResult()) {
3036 result = m_insertionSet.insertNode(
3037 indexForChecks, SpecBytecodeDouble, ValueRep, originForChecks,
3038 Edge(edge.node(), DoubleRepUse));
3040 result = m_insertionSet.insertNode(
3041 indexForChecks, SpecInt32Only | SpecAnyIntAsDouble, ValueRep,
3042 originForChecks, Edge(edge.node(), Int52RepUse));
3045 edge.setNode(result);
3049 // It's remotely possible that this node cannot do type checks, but we now have a
3050 // type check on this node. We don't have to handle the general form of this
3051 // problem. It only arises when ByteCodeParser emits an immediate SetLocal, rather
3052 // than a delayed one. So, we only worry about those checks that we may have put on
3053 // a SetLocal. Note that "indexForChecks != indexInBlock" is just another way of
3054 // saying "!node->origin.exitOK".
3055 if (indexForChecks != indexInBlock && mayHaveTypeCheck(edge.useKind())) {
3056 UseKind knownUseKind;