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 && m_graph.hasExitSite(node->origin.semantic, BadType)) {
198 fixEdge<UntypedUse>(node->child1());
199 fixEdge<UntypedUse>(node->child2());
200 node->setResult(NodeResultJS);
203 if (attemptToMakeIntegerAdd(node))
205 fixDoubleOrBooleanEdge(node->child1());
206 fixDoubleOrBooleanEdge(node->child2());
207 node->setResult(NodeResultDouble);
212 if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
213 fixIntOrBooleanEdge(node->child1());
214 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
215 node->setArithMode(Arith::Unchecked);
216 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
217 node->setArithMode(Arith::CheckOverflow);
219 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
222 if (m_graph.unaryArithShouldSpeculateMachineInt(node, FixupPass)) {
223 fixEdge<Int52RepUse>(node->child1());
224 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
225 node->setArithMode(Arith::CheckOverflow);
227 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
228 node->setResult(NodeResultInt52);
231 fixDoubleOrBooleanEdge(node->child1());
232 node->setResult(NodeResultDouble);
237 Edge& leftChild = node->child1();
238 Edge& rightChild = node->child2();
239 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())
240 && m_graph.hasExitSite(node->origin.semantic, BadType)) {
241 fixEdge<UntypedUse>(leftChild);
242 fixEdge<UntypedUse>(rightChild);
243 node->setResult(NodeResultJS);
246 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
247 fixIntOrBooleanEdge(leftChild);
248 fixIntOrBooleanEdge(rightChild);
249 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
250 node->setArithMode(Arith::Unchecked);
251 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())
252 || leftChild.node() == rightChild.node())
253 node->setArithMode(Arith::CheckOverflow);
255 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
258 if (m_graph.binaryArithShouldSpeculateMachineInt(node, FixupPass)) {
259 fixEdge<Int52RepUse>(leftChild);
260 fixEdge<Int52RepUse>(rightChild);
261 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())
262 || leftChild.node() == rightChild.node())
263 node->setArithMode(Arith::CheckOverflow);
265 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
266 node->setResult(NodeResultInt52);
269 fixDoubleOrBooleanEdge(leftChild);
270 fixDoubleOrBooleanEdge(rightChild);
271 node->setResult(NodeResultDouble);
277 Edge& leftChild = node->child1();
278 Edge& rightChild = node->child2();
280 && Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())
281 && m_graph.hasExitSite(node->origin.semantic, BadType)) {
282 fixEdge<UntypedUse>(leftChild);
283 fixEdge<UntypedUse>(rightChild);
284 node->setResult(NodeResultJS);
287 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
288 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) {
289 fixIntOrBooleanEdge(leftChild);
290 fixIntOrBooleanEdge(rightChild);
291 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
292 node->setArithMode(Arith::Unchecked);
293 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
294 node->setArithMode(Arith::CheckOverflow);
296 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
300 // This will cause conversion nodes to be inserted later.
301 fixDoubleOrBooleanEdge(leftChild);
302 fixDoubleOrBooleanEdge(rightChild);
304 // We don't need to do ref'ing on the children because we're stealing them from
305 // the original division.
306 Node* newDivision = m_insertionSet.insertNode(
307 m_indexInBlock, SpecBytecodeDouble, *node);
308 newDivision->setResult(NodeResultDouble);
310 node->setOp(DoubleAsInt32);
311 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
312 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
313 node->setArithMode(Arith::CheckOverflow);
315 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
318 fixDoubleOrBooleanEdge(leftChild);
319 fixDoubleOrBooleanEdge(rightChild);
320 node->setResult(NodeResultDouble);
326 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
327 fixIntOrBooleanEdge(node->child1());
328 fixIntOrBooleanEdge(node->child2());
331 fixDoubleOrBooleanEdge(node->child1());
332 fixDoubleOrBooleanEdge(node->child2());
333 node->setResult(NodeResultDouble);
338 if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
339 fixIntOrBooleanEdge(node->child1());
340 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
341 node->setArithMode(Arith::Unchecked);
343 node->setArithMode(Arith::CheckOverflow);
346 fixDoubleOrBooleanEdge(node->child1());
347 node->setResult(NodeResultDouble);
352 node->setResult(NodeResultDouble);
353 if (node->child2()->shouldSpeculateInt32OrBooleanForArithmetic()) {
354 fixDoubleOrBooleanEdge(node->child1());
355 fixIntOrBooleanEdge(node->child2());
359 fixDoubleOrBooleanEdge(node->child1());
360 fixDoubleOrBooleanEdge(node->child2());
365 node->setResult(NodeResultDouble);
373 if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
374 fixIntOrBooleanEdge(node->child1());
375 insertCheck<Int32Use>(m_indexInBlock, node->child1().node());
376 node->convertToIdentity();
379 fixDoubleOrBooleanEdge(node->child1());
381 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
382 node->setResult(NodeResultInt32);
383 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
384 node->setArithRoundingMode(Arith::RoundingMode::Int32);
386 node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
388 node->setResult(NodeResultDouble);
389 node->setArithRoundingMode(Arith::RoundingMode::Double);
399 fixDoubleOrBooleanEdge(node->child1());
400 node->setResult(NodeResultDouble);
405 if (node->child1()->shouldSpeculateBoolean()) {
406 if (node->child1()->result() == NodeResultBoolean) {
407 // This is necessary in case we have a bytecode instruction implemented by:
412 // In that case, CompareEq might have a side-effect. Then, we need to make
413 // sure that we know that Branch does not exit.
414 fixEdge<KnownBooleanUse>(node->child1());
416 fixEdge<BooleanUse>(node->child1());
417 } else if (node->child1()->shouldSpeculateObjectOrOther())
418 fixEdge<ObjectOrOtherUse>(node->child1());
419 else if (node->child1()->shouldSpeculateInt32OrBoolean())
420 fixIntOrBooleanEdge(node->child1());
421 else if (node->child1()->shouldSpeculateNumber())
422 fixEdge<DoubleRepUse>(node->child1());
423 else if (node->child1()->shouldSpeculateString())
424 fixEdge<StringUse>(node->child1());
425 else if (node->child1()->shouldSpeculateStringOrOther())
426 fixEdge<StringOrOtherUse>(node->child1());
434 case CompareGreaterEq: {
435 if (node->op() == CompareEq
436 && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
437 fixEdge<BooleanUse>(node->child1());
438 fixEdge<BooleanUse>(node->child2());
439 node->clearFlags(NodeMustGenerate);
442 if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
443 fixIntOrBooleanEdge(node->child1());
444 fixIntOrBooleanEdge(node->child2());
445 node->clearFlags(NodeMustGenerate);
449 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
450 fixEdge<Int52RepUse>(node->child1());
451 fixEdge<Int52RepUse>(node->child2());
452 node->clearFlags(NodeMustGenerate);
455 if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
456 fixDoubleOrBooleanEdge(node->child1());
457 fixDoubleOrBooleanEdge(node->child2());
459 if (node->op() != CompareEq
460 && node->child1()->shouldSpeculateNotCell()
461 && node->child2()->shouldSpeculateNotCell()) {
462 if (node->child1()->shouldSpeculateNumberOrBoolean())
463 fixDoubleOrBooleanEdge(node->child1());
465 fixEdge<DoubleRepUse>(node->child1());
466 if (node->child2()->shouldSpeculateNumberOrBoolean())
467 fixDoubleOrBooleanEdge(node->child2());
469 fixEdge<DoubleRepUse>(node->child2());
470 node->clearFlags(NodeMustGenerate);
473 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
474 fixEdge<StringIdentUse>(node->child1());
475 fixEdge<StringIdentUse>(node->child2());
476 node->clearFlags(NodeMustGenerate);
479 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
480 fixEdge<StringUse>(node->child1());
481 fixEdge<StringUse>(node->child2());
482 node->clearFlags(NodeMustGenerate);
486 if (node->op() != CompareEq)
488 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
489 fixEdge<SymbolUse>(node->child1());
490 fixEdge<SymbolUse>(node->child2());
491 node->clearFlags(NodeMustGenerate);
494 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
495 fixEdge<ObjectUse>(node->child1());
496 fixEdge<ObjectUse>(node->child2());
497 node->clearFlags(NodeMustGenerate);
501 // If either child can be proved to be Null or Undefined, comparing them is greatly simplified.
502 bool oneArgumentIsUsedAsSpecOther = false;
503 if (node->child1()->isUndefinedOrNullConstant()) {
504 fixEdge<OtherUse>(node->child1());
505 oneArgumentIsUsedAsSpecOther = true;
506 } else if (node->child1()->shouldSpeculateOther()) {
507 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
508 Edge(node->child1().node(), OtherUse));
509 fixEdge<OtherUse>(node->child1());
510 oneArgumentIsUsedAsSpecOther = true;
512 if (node->child2()->isUndefinedOrNullConstant()) {
513 fixEdge<OtherUse>(node->child2());
514 oneArgumentIsUsedAsSpecOther = true;
515 } else if (node->child2()->shouldSpeculateOther()) {
516 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
517 Edge(node->child2().node(), OtherUse));
518 fixEdge<OtherUse>(node->child2());
519 oneArgumentIsUsedAsSpecOther = true;
521 if (oneArgumentIsUsedAsSpecOther) {
522 node->clearFlags(NodeMustGenerate);
526 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
527 fixEdge<ObjectUse>(node->child1());
528 fixEdge<ObjectOrOtherUse>(node->child2());
529 node->clearFlags(NodeMustGenerate);
532 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
533 fixEdge<ObjectOrOtherUse>(node->child1());
534 fixEdge<ObjectUse>(node->child2());
535 node->clearFlags(NodeMustGenerate);
542 case CompareStrictEq: {
543 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
544 fixEdge<BooleanUse>(node->child1());
545 fixEdge<BooleanUse>(node->child2());
548 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
549 fixEdge<Int32Use>(node->child1());
550 fixEdge<Int32Use>(node->child2());
554 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
555 fixEdge<Int52RepUse>(node->child1());
556 fixEdge<Int52RepUse>(node->child2());
559 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
560 fixEdge<DoubleRepUse>(node->child1());
561 fixEdge<DoubleRepUse>(node->child2());
564 if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
565 fixEdge<SymbolUse>(node->child1());
566 fixEdge<SymbolUse>(node->child2());
569 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
570 fixEdge<StringIdentUse>(node->child1());
571 fixEdge<StringIdentUse>(node->child2());
574 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 7) || isFTL(m_graph.m_plan.mode))) {
575 fixEdge<StringUse>(node->child1());
576 fixEdge<StringUse>(node->child2());
579 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
580 if (masqueradesAsUndefinedWatchpoint->isStillValid()) {
582 if (node->child1()->shouldSpeculateObject()) {
583 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
584 fixEdge<ObjectUse>(node->child1());
587 if (node->child2()->shouldSpeculateObject()) {
588 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
589 fixEdge<ObjectUse>(node->child2());
593 } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
594 fixEdge<ObjectUse>(node->child1());
595 fixEdge<ObjectUse>(node->child2());
598 if (node->child1()->shouldSpeculateMisc()) {
599 fixEdge<MiscUse>(node->child1());
602 if (node->child2()->shouldSpeculateMisc()) {
603 fixEdge<MiscUse>(node->child2());
606 if (node->child1()->shouldSpeculateStringIdent()
607 && node->child2()->shouldSpeculateNotStringVar()) {
608 fixEdge<StringIdentUse>(node->child1());
609 fixEdge<NotStringVarUse>(node->child2());
612 if (node->child2()->shouldSpeculateStringIdent()
613 && node->child1()->shouldSpeculateNotStringVar()) {
614 fixEdge<StringIdentUse>(node->child2());
615 fixEdge<NotStringVarUse>(node->child1());
618 if (node->child1()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
619 fixEdge<StringUse>(node->child1());
622 if (node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
623 fixEdge<StringUse>(node->child2());
629 case StringFromCharCode:
630 if (node->child1()->shouldSpeculateInt32())
631 fixEdge<Int32Use>(node->child1());
633 fixEdge<UntypedUse>(node->child1());
637 case StringCharCodeAt: {
638 // Currently we have no good way of refining these.
639 ASSERT(node->arrayMode() == ArrayMode(Array::String));
640 blessArrayOperation(node->child1(), node->child2(), node->child3());
641 fixEdge<KnownCellUse>(node->child1());
642 fixEdge<Int32Use>(node->child2());
647 if (!node->prediction()) {
648 m_insertionSet.insertNode(
649 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
653 node->arrayMode().refine(
655 node->child1()->prediction(),
656 node->child2()->prediction(),
659 blessArrayOperation(node->child1(), node->child2(), node->child3());
661 ArrayMode arrayMode = node->arrayMode();
662 switch (arrayMode.type()) {
663 case Array::Contiguous:
665 if (arrayMode.arrayClass() == Array::OriginalArray
666 && arrayMode.speculation() == Array::InBounds) {
667 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
668 if (globalObject->arrayPrototypeChainIsSane()) {
669 // Check if SaneChain will work on a per-type basis. Note that:
671 // 1) We don't want double arrays to sometimes return undefined, since
672 // that would require a change to the return type and it would pessimise
673 // things a lot. So, we'd only want to do that if we actually had
674 // evidence that we could read from a hole. That's pretty annoying.
675 // Likely the best way to handle that case is with an equivalent of
676 // SaneChain for OutOfBounds. For now we just detect when Undefined and
677 // NaN are indistinguishable according to backwards propagation, and just
678 // use SaneChain in that case. This happens to catch a lot of cases.
680 // 2) We don't want int32 array loads to have to do a hole check just to
681 // coerce to Undefined, since that would mean twice the checks.
683 // This has two implications. First, we have to do more checks than we'd
684 // like. It's unfortunate that we have to do the hole check. Second,
685 // some accesses that hit a hole will now need to take the full-blown
686 // out-of-bounds slow path. We can fix that with:
687 // https://bugs.webkit.org/show_bug.cgi?id=144668
689 bool canDoSaneChain = false;
690 switch (arrayMode.type()) {
691 case Array::Contiguous:
692 // This is happens to be entirely natural. We already would have
693 // returned any JSValue, and now we'll return Undefined. We still do
694 // the check but it doesn't require taking any kind of slow path.
695 canDoSaneChain = true;
699 if (!(node->flags() & NodeBytecodeUsesAsOther)) {
700 // Holes look like NaN already, so if the user doesn't care
701 // about the difference between Undefined and NaN then we can
703 canDoSaneChain = true;
711 if (canDoSaneChain) {
712 m_graph.watchpoints().addLazily(
713 globalObject->arrayPrototype()->structure()->transitionWatchpointSet());
714 m_graph.watchpoints().addLazily(
715 globalObject->objectPrototype()->structure()->transitionWatchpointSet());
716 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
723 if ((node->prediction() & ~SpecString)
724 || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
725 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
732 arrayMode = node->arrayMode();
733 switch (arrayMode.type()) {
734 case Array::SelectUsingPredictions:
735 case Array::Unprofiled:
736 RELEASE_ASSERT_NOT_REACHED();
739 #if USE(JSVALUE32_64)
740 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
743 case Array::ForceExit:
746 fixEdge<KnownCellUse>(node->child1());
747 fixEdge<Int32Use>(node->child2());
751 switch (arrayMode.type()) {
753 if (!arrayMode.isOutOfBounds())
754 node->setResult(NodeResultDouble);
757 case Array::Float32Array:
758 case Array::Float64Array:
759 node->setResult(NodeResultDouble);
762 case Array::Uint32Array:
763 if (node->shouldSpeculateInt32())
765 if (node->shouldSpeculateMachineInt() && enableInt52())
766 node->setResult(NodeResultInt52);
768 node->setResult(NodeResultDouble);
780 case PutByValAlias: {
781 Edge& child1 = m_graph.varArgChild(node, 0);
782 Edge& child2 = m_graph.varArgChild(node, 1);
783 Edge& child3 = m_graph.varArgChild(node, 2);
786 node->arrayMode().refine(
788 child1->prediction(),
789 child2->prediction(),
790 child3->prediction()));
792 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
794 switch (node->arrayMode().modeForPut().type()) {
795 case Array::SelectUsingPredictions:
796 case Array::SelectUsingArguments:
797 case Array::Unprofiled:
798 case Array::Undecided:
799 RELEASE_ASSERT_NOT_REACHED();
801 case Array::ForceExit:
803 #if USE(JSVALUE32_64)
804 // Due to register pressure on 32-bit, we speculate cell and
805 // ignore the base-is-not-cell case entirely by letting the
806 // baseline JIT handle it.
807 fixEdge<CellUse>(child1);
811 fixEdge<KnownCellUse>(child1);
812 fixEdge<Int32Use>(child2);
813 fixEdge<Int32Use>(child3);
816 fixEdge<KnownCellUse>(child1);
817 fixEdge<Int32Use>(child2);
818 fixEdge<DoubleRepRealUse>(child3);
820 case Array::Int8Array:
821 case Array::Int16Array:
822 case Array::Int32Array:
823 case Array::Uint8Array:
824 case Array::Uint8ClampedArray:
825 case Array::Uint16Array:
826 case Array::Uint32Array:
827 fixEdge<KnownCellUse>(child1);
828 fixEdge<Int32Use>(child2);
829 if (child3->shouldSpeculateInt32())
830 fixIntOrBooleanEdge(child3);
831 else if (child3->shouldSpeculateMachineInt())
832 fixEdge<Int52RepUse>(child3);
834 fixDoubleOrBooleanEdge(child3);
836 case Array::Float32Array:
837 case Array::Float64Array:
838 fixEdge<KnownCellUse>(child1);
839 fixEdge<Int32Use>(child2);
840 fixDoubleOrBooleanEdge(child3);
842 case Array::Contiguous:
843 case Array::ArrayStorage:
844 case Array::SlowPutArrayStorage:
845 fixEdge<KnownCellUse>(child1);
846 fixEdge<Int32Use>(child2);
847 speculateForBarrier(child3);
850 fixEdge<KnownCellUse>(child1);
851 fixEdge<Int32Use>(child2);
858 // May need to refine the array mode in case the value prediction contravenes
859 // the array prediction. For example, we may have evidence showing that the
860 // array is in Int32 mode, but the value we're storing is likely to be a double.
861 // Then we should turn this into a conversion to Double array followed by the
862 // push. On the other hand, we absolutely don't want to refine based on the
863 // base prediction. If it has non-cell garbage in it, then we want that to be
864 // ignored. That's because ArrayPush can't handle any array modes that aren't
865 // array-related - so if refine() turned this into a "Generic" ArrayPush then
866 // that would break things.
868 node->arrayMode().refine(
870 node->child1()->prediction() & SpecCell,
872 node->child2()->prediction()));
873 blessArrayOperation(node->child1(), Edge(), node->child3());
874 fixEdge<KnownCellUse>(node->child1());
876 switch (node->arrayMode().type()) {
878 fixEdge<Int32Use>(node->child2());
881 fixEdge<DoubleRepRealUse>(node->child2());
883 case Array::Contiguous:
884 case Array::ArrayStorage:
885 speculateForBarrier(node->child2());
894 blessArrayOperation(node->child1(), Edge(), node->child2());
895 fixEdge<KnownCellUse>(node->child1());
901 fixEdge<KnownCellUse>(node->child1());
903 if (node->child2()->shouldSpeculateRegExpObject()) {
904 fixEdge<RegExpObjectUse>(node->child2());
906 if (node->child3()->shouldSpeculateString())
907 fixEdge<StringUse>(node->child3());
912 case StringReplace: {
913 if (node->child1()->shouldSpeculateString()
914 && node->child2()->shouldSpeculateRegExpObject()
915 && node->child3()->shouldSpeculateString()) {
916 fixEdge<StringUse>(node->child1());
917 fixEdge<RegExpObjectUse>(node->child2());
918 fixEdge<StringUse>(node->child3());
925 if (node->child1()->shouldSpeculateBoolean()) {
926 if (node->child1()->result() == NodeResultBoolean) {
927 // This is necessary in case we have a bytecode instruction implemented by:
932 // In that case, CompareEq might have a side-effect. Then, we need to make
933 // sure that we know that Branch does not exit.
934 fixEdge<KnownBooleanUse>(node->child1());
936 fixEdge<BooleanUse>(node->child1());
937 } else if (node->child1()->shouldSpeculateObjectOrOther())
938 fixEdge<ObjectOrOtherUse>(node->child1());
939 else if (node->child1()->shouldSpeculateInt32OrBoolean())
940 fixIntOrBooleanEdge(node->child1());
941 else if (node->child1()->shouldSpeculateNumber())
942 fixEdge<DoubleRepUse>(node->child1());
943 else if (node->child1()->shouldSpeculateString())
944 fixEdge<StringUse>(node->child1());
945 else if (node->child1()->shouldSpeculateStringOrOther())
946 fixEdge<StringOrOtherUse>(node->child1());
951 SwitchData* data = node->switchData();
952 switch (data->kind) {
954 if (node->child1()->shouldSpeculateInt32())
955 fixEdge<Int32Use>(node->child1());
958 if (node->child1()->shouldSpeculateString())
959 fixEdge<StringUse>(node->child1());
962 if (node->child1()->shouldSpeculateStringIdent())
963 fixEdge<StringIdentUse>(node->child1());
964 else if (node->child1()->shouldSpeculateString())
965 fixEdge<StringUse>(node->child1());
968 if (node->child1()->shouldSpeculateCell())
969 fixEdge<CellUse>(node->child1());
970 // else it's fine for this to have UntypedUse; we will handle this by just making
971 // non-cells take the default case.
978 fixupToPrimitive(node);
983 case CallStringConstructor: {
984 fixupToStringOrCallStringConstructor(node);
988 case NewStringObject: {
989 fixEdge<KnownStringUse>(node->child1());
994 watchHavingABadTime(node);
996 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
997 node->setIndexingType(
998 leastUpperBoundOfIndexingTypeAndType(
999 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
1001 switch (node->indexingType()) {
1002 case ALL_BLANK_INDEXING_TYPES:
1005 case ALL_UNDECIDED_INDEXING_TYPES:
1006 if (node->numChildren()) {
1007 // This will only happen if the children have no type predictions. We
1008 // would have already exited by now, but insert a forced exit just to
1010 m_insertionSet.insertNode(
1011 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
1014 case ALL_INT32_INDEXING_TYPES:
1015 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1016 fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1018 case ALL_DOUBLE_INDEXING_TYPES:
1019 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
1020 fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
1022 case ALL_CONTIGUOUS_INDEXING_TYPES:
1023 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
1032 case NewTypedArray: {
1033 watchHavingABadTime(node);
1035 if (node->child1()->shouldSpeculateInt32()) {
1036 fixEdge<Int32Use>(node->child1());
1037 node->clearFlags(NodeMustGenerate);
1043 case NewArrayWithSize: {
1044 watchHavingABadTime(node);
1045 fixEdge<Int32Use>(node->child1());
1049 case CallObjectConstructor: {
1050 if (node->child1()->shouldSpeculateObject()) {
1051 fixEdge<ObjectUse>(node->child1());
1052 node->convertToIdentity();
1056 fixEdge<UntypedUse>(node->child1());
1065 case PutStructure: {
1066 fixEdge<KnownCellUse>(node->child1());
1071 case GetFromArguments: {
1072 fixEdge<KnownCellUse>(node->child1());
1077 case PutToArguments: {
1078 fixEdge<KnownCellUse>(node->child1());
1079 speculateForBarrier(node->child2());
1087 case GetGlobalObject: {
1088 fixEdge<KnownCellUse>(node->child1());
1092 case AllocatePropertyStorage:
1093 case ReallocatePropertyStorage: {
1094 fixEdge<KnownCellUse>(node->child1());
1099 if (node->child1()->shouldSpeculateCell())
1100 fixEdge<CellUse>(node->child1());
1105 case GetByIdFlush: {
1106 // FIXME: This should be done in the ByteCodeParser based on reading the
1107 // PolymorphicAccess, which will surely tell us that this is a AccessCase::ArrayLength.
1108 // https://bugs.webkit.org/show_bug.cgi?id=154990
1109 if (node->child1()->shouldSpeculateCellOrOther()
1110 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1111 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1112 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1113 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1115 auto uid = m_graph.identifiers()[node->identifierNumber()];
1117 if (uid == vm().propertyNames->length.impl()) {
1118 attemptToMakeGetArrayLength(node);
1122 if (uid == vm().propertyNames->lastIndex.impl()
1123 && node->child1()->shouldSpeculateRegExpObject()) {
1124 node->setOp(GetRegExpObjectLastIndex);
1125 node->clearFlags(NodeMustGenerate);
1126 fixEdge<RegExpObjectUse>(node->child1());
1131 if (node->child1()->shouldSpeculateCell())
1132 fixEdge<CellUse>(node->child1());
1138 case PutByIdDirect: {
1139 if (node->child1()->shouldSpeculateCellOrOther()
1140 && !m_graph.hasExitSite(node->origin.semantic, BadType)
1141 && !m_graph.hasExitSite(node->origin.semantic, BadCache)
1142 && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
1143 && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
1145 auto uid = m_graph.identifiers()[node->identifierNumber()];
1147 if (uid == vm().propertyNames->lastIndex.impl()
1148 && node->child1()->shouldSpeculateRegExpObject()) {
1149 node->setOp(SetRegExpObjectLastIndex);
1150 fixEdge<RegExpObjectUse>(node->child1());
1151 speculateForBarrier(node->child2());
1156 fixEdge<CellUse>(node->child1());
1161 case PutSetterById: {
1162 fixEdge<KnownCellUse>(node->child1());
1163 fixEdge<KnownCellUse>(node->child2());
1167 case PutGetterSetterById: {
1168 fixEdge<KnownCellUse>(node->child1());
1172 case PutGetterByVal:
1173 case PutSetterByVal: {
1174 fixEdge<KnownCellUse>(node->child1());
1175 fixEdge<KnownCellUse>(node->child3());
1179 case GetExecutable: {
1180 fixEdge<FunctionUse>(node->child1());
1184 case OverridesHasInstance:
1185 case CheckStructure:
1188 case GetButterfly: {
1189 fixEdge<CellUse>(node->child1());
1194 UniquedStringImpl* uid = node->uidOperand();
1195 if (uid->isSymbol())
1196 fixEdge<SymbolUse>(node->child1());
1198 fixEdge<StringIdentUse>(node->child1());
1203 case ArrayifyToStructure: {
1204 fixEdge<CellUse>(node->child1());
1206 fixEdge<Int32Use>(node->child2());
1211 case GetGetterSetterByOffset: {
1212 if (!node->child1()->hasStorageResult())
1213 fixEdge<KnownCellUse>(node->child1());
1214 fixEdge<KnownCellUse>(node->child2());
1218 case MultiGetByOffset: {
1219 fixEdge<CellUse>(node->child1());
1224 if (!node->child1()->hasStorageResult())
1225 fixEdge<KnownCellUse>(node->child1());
1226 fixEdge<KnownCellUse>(node->child2());
1227 insertInferredTypeCheck(
1228 m_insertionSet, m_indexInBlock, node->origin, node->child3().node(),
1229 node->storageAccessData().inferredType);
1230 speculateForBarrier(node->child3());
1234 case MultiPutByOffset: {
1235 fixEdge<CellUse>(node->child1());
1236 speculateForBarrier(node->child2());
1241 if (!(node->child1()->prediction() & ~SpecCell))
1242 fixEdge<CellUse>(node->child1());
1243 fixEdge<CellUse>(node->child2());
1247 case InstanceOfCustom:
1248 fixEdge<CellUse>(node->child2());
1252 // FIXME: We should at some point have array profiling on op_in, in which
1253 // case we would be able to turn this into a kind of GetByVal.
1255 fixEdge<CellUse>(node->child2());
1260 m_graph.doToChildren(
1263 switch (edge.useKind()) {
1265 if (edge->shouldSpeculateInt32ForArithmetic())
1266 edge.setUseKind(Int32Use);
1271 observeUseKindOnEdge(edge);
1277 // Phantoms are meaningless past Fixup. We recreate them on-demand in the backend.
1282 RELEASE_ASSERT(enableInt52());
1283 node->convertToIdentity();
1284 fixEdge<Int52RepUse>(node->child1());
1285 node->setResult(NodeResultInt52);
1289 case GetArrayLength: {
1290 fixEdge<KnownCellUse>(node->child1());
1294 case GetTypedArrayByteOffset: {
1295 fixEdge<KnownCellUse>(node->child1());
1301 case GetIndexedPropertyStorage:
1303 case CheckTierUpInLoop:
1304 case CheckTierUpAtReturn:
1305 case CheckTierUpAndOSREnter:
1306 case InvalidationPoint:
1309 case ConstantStoragePointer:
1316 case Identity: // This should have been cleaned up.
1317 case BooleanToNumber:
1318 case PhantomNewObject:
1319 case PhantomNewFunction:
1320 case PhantomNewGeneratorFunction:
1321 case PhantomCreateActivation:
1322 case PhantomDirectArguments:
1323 case PhantomClonedArguments:
1324 case ForwardVarargs:
1325 case GetMyArgumentByVal:
1327 case CheckStructureImmediate:
1328 case MaterializeNewObject:
1329 case MaterializeCreateActivation:
1334 case GetRegExpObjectLastIndex:
1335 case SetRegExpObjectLastIndex:
1336 case RecordRegExpCachedResult:
1337 // These are just nodes that we don't currently expect to see during fixup.
1338 // If we ever wanted to insert them prior to fixup, then we just have to create
1339 // fixup rules for them.
1340 DFG_CRASH(m_graph, node, "Unexpected node during fixup");
1343 case PutGlobalVariable: {
1344 fixEdge<CellUse>(node->child1());
1345 speculateForBarrier(node->child2());
1350 if (node->child1()->shouldSpeculateString()) {
1351 m_insertionSet.insertNode(
1352 m_indexInBlock, SpecNone, Check, node->origin,
1353 Edge(node->child1().node(), StringUse));
1354 m_graph.convertToConstant(node, jsBoolean(true));
1355 observeUseKindOnNode<StringUse>(node);
1360 if (node->child1()->shouldSpeculateObject()) {
1361 m_insertionSet.insertNode(
1362 m_indexInBlock, SpecNone, Check, node->origin,
1363 Edge(node->child1().node(), ObjectUse));
1364 m_graph.convertToConstant(node, jsBoolean(true));
1365 observeUseKindOnNode<ObjectUse>(node);
1369 case GetEnumerableLength: {
1370 fixEdge<CellUse>(node->child1());
1373 case HasGenericProperty: {
1374 fixEdge<CellUse>(node->child2());
1377 case HasStructureProperty: {
1378 fixEdge<StringUse>(node->child2());
1379 fixEdge<KnownCellUse>(node->child3());
1382 case HasIndexedProperty: {
1384 node->arrayMode().refine(
1386 node->child1()->prediction(),
1387 node->child2()->prediction(),
1390 blessArrayOperation(node->child1(), node->child2(), node->child3());
1391 fixEdge<CellUse>(node->child1());
1392 fixEdge<KnownInt32Use>(node->child2());
1395 case GetDirectPname: {
1396 Edge& base = m_graph.varArgChild(node, 0);
1397 Edge& property = m_graph.varArgChild(node, 1);
1398 Edge& index = m_graph.varArgChild(node, 2);
1399 Edge& enumerator = m_graph.varArgChild(node, 3);
1400 fixEdge<CellUse>(base);
1401 fixEdge<KnownCellUse>(property);
1402 fixEdge<KnownInt32Use>(index);
1403 fixEdge<KnownCellUse>(enumerator);
1406 case GetPropertyEnumerator: {
1407 fixEdge<CellUse>(node->child1());
1410 case GetEnumeratorStructurePname: {
1411 fixEdge<KnownCellUse>(node->child1());
1412 fixEdge<KnownInt32Use>(node->child2());
1415 case GetEnumeratorGenericPname: {
1416 fixEdge<KnownCellUse>(node->child1());
1417 fixEdge<KnownInt32Use>(node->child2());
1420 case ToIndexString: {
1421 fixEdge<KnownInt32Use>(node->child1());
1425 // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet.
1426 // Because the instructionTypeSet is contained in globalTypeSet, if we produce a type check for
1427 // type T for the instructionTypeSet, the global type set must also have information for type T.
1428 // So if it the type check succeeds for type T in the instructionTypeSet, a type check for type T
1429 // in the globalTypeSet would've also succeeded.
1430 // (The other direction does not hold in general).
1432 RefPtr<TypeSet> typeSet = node->typeLocation()->m_instructionTypeSet;
1433 RuntimeTypeMask seenTypes = typeSet->seenTypes();
1434 if (typeSet->doesTypeConformTo(TypeMachineInt)) {
1435 if (node->child1()->shouldSpeculateInt32())
1436 fixEdge<Int32Use>(node->child1());
1438 fixEdge<MachineIntUse>(node->child1());
1440 } else if (typeSet->doesTypeConformTo(TypeNumber | TypeMachineInt)) {
1441 fixEdge<NumberUse>(node->child1());
1443 } else if (typeSet->doesTypeConformTo(TypeString)) {
1444 fixEdge<StringUse>(node->child1());
1446 } else if (typeSet->doesTypeConformTo(TypeBoolean)) {
1447 fixEdge<BooleanUse>(node->child1());
1449 } else if (typeSet->doesTypeConformTo(TypeUndefined | TypeNull) && (seenTypes & TypeUndefined) && (seenTypes & TypeNull)) {
1450 fixEdge<OtherUse>(node->child1());
1452 } else if (typeSet->doesTypeConformTo(TypeObject)) {
1453 StructureSet set = typeSet->structureSet();
1454 if (!set.isEmpty()) {
1455 fixEdge<CellUse>(node->child1());
1456 node->convertToCheckStructure(m_graph.addStructureSet(set));
1463 case CreateScopedArguments:
1464 case CreateActivation:
1466 case NewGeneratorFunction: {
1467 fixEdge<CellUse>(node->child1());
1471 case SetFunctionName: {
1472 // The first child is guaranteed to be a cell because op_set_function_name is only used
1473 // on a newly instantiated function object (the first child).
1474 fixEdge<KnownCellUse>(node->child1());
1475 fixEdge<UntypedUse>(node->child2());
1480 fixEdge<KnownCellUse>(node->child1());
1481 fixEdge<KnownInt32Use>(node->child2());
1487 case PutDynamicVar: {
1488 fixEdge<KnownCellUse>(node->child1());
1492 #if !ASSERT_DISABLED
1493 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
1496 case LazyJSConstant:
1497 case DoubleConstant:
1500 case GetArgumentCount:
1504 case GetLocalUnlinked:
1506 case GetGlobalLexicalVariable:
1508 case VarInjectionWatchpoint:
1510 case CheckTypeInfoFlags:
1511 case TailCallInlinedCaller:
1514 case TailCallVarargsInlinedCaller:
1515 case ConstructVarargs:
1516 case CallForwardVarargs:
1517 case ConstructForwardVarargs:
1518 case TailCallForwardVarargs:
1519 case TailCallForwardVarargsInlinedCaller:
1521 case ProfileControlFlow:
1523 case NewArrayBuffer:
1525 case ProfileWillCall:
1526 case ProfileDidCall:
1530 case IsArrayConstructor:
1534 case IsObjectOrNull:
1536 case IsRegExpObject:
1537 case CreateDirectArguments:
1538 case CreateClonedArguments:
1542 case TailCallVarargs:
1544 case ThrowReferenceError:
1545 case CountExecution:
1549 case CheckWatchdogTimer:
1550 case LogShadowChickenPrologue:
1551 case LogShadowChickenTail:
1553 case ExtractOSREntryLocal:
1568 void watchHavingABadTime(Node* node)
1570 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1572 // If this global object is not having a bad time, watch it. We go down this path anytime the code
1573 // does an array allocation. The types of array allocations may change if we start to have a bad
1574 // time. It's easier to reason about this if we know that whenever the types change after we start
1575 // optimizing, the code just gets thrown out. Doing this at FixupPhase is just early enough, since
1576 // prior to this point nobody should have been doing optimizations based on the indexing type of
1578 if (!globalObject->isHavingABadTime())
1579 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1582 template<UseKind useKind>
1583 void createToString(Node* node, Edge& edge)
1585 edge.setNode(m_insertionSet.insertNode(
1586 m_indexInBlock, SpecString, ToString, node->origin,
1587 Edge(edge.node(), useKind)));
1590 template<UseKind useKind>
1591 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
1593 ASSERT(arrayMode == ArrayMode(Array::Generic));
1595 if (!m_graph.canOptimizeStringObjectAccess(node->origin.semantic))
1598 createToString<useKind>(node, node->child1());
1599 arrayMode = ArrayMode(Array::String);
1602 template<UseKind useKind>
1603 bool isStringObjectUse()
1606 case StringObjectUse:
1607 case StringOrStringObjectUse:
1614 template<UseKind useKind>
1615 void convertStringAddUse(Node* node, Edge& edge)
1617 if (useKind == StringUse) {
1618 observeUseKindOnNode<StringUse>(edge.node());
1619 m_insertionSet.insertNode(
1620 m_indexInBlock, SpecNone, Check, node->origin,
1621 Edge(edge.node(), StringUse));
1622 edge.setUseKind(KnownStringUse);
1626 observeUseKindOnNode<useKind>(edge.node());
1627 createToString<useKind>(node, edge);
1630 void convertToMakeRope(Node* node)
1632 node->setOpAndDefaultFlags(MakeRope);
1633 fixupMakeRope(node);
1636 void fixupMakeRope(Node* node)
1638 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1639 Edge& edge = node->children.child(i);
1642 edge.setUseKind(KnownStringUse);
1643 JSString* string = edge->dynamicCastConstant<JSString*>();
1646 if (string->length())
1649 // Don't allow the MakeRope to have zero children.
1650 if (!i && !node->child2())
1653 node->children.removeEdge(i--);
1656 if (!node->child2()) {
1657 ASSERT(!node->child3());
1658 node->convertToIdentity();
1662 void fixupToThis(Node* node)
1664 ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
1666 if (ecmaMode == StrictMode) {
1667 if (node->child1()->shouldSpeculateBoolean()) {
1668 fixEdge<BooleanUse>(node->child1());
1669 node->convertToIdentity();
1673 if (node->child1()->shouldSpeculateInt32()) {
1674 fixEdge<Int32Use>(node->child1());
1675 node->convertToIdentity();
1679 if (enableInt52() && node->child1()->shouldSpeculateMachineInt()) {
1680 fixEdge<Int52RepUse>(node->child1());
1681 node->convertToIdentity();
1682 node->setResult(NodeResultInt52);
1686 if (node->child1()->shouldSpeculateNumber()) {
1687 fixEdge<DoubleRepUse>(node->child1());
1688 node->convertToIdentity();
1689 node->setResult(NodeResultDouble);
1693 if (node->child1()->shouldSpeculateSymbol()) {
1694 fixEdge<SymbolUse>(node->child1());
1695 node->convertToIdentity();
1699 if (node->child1()->shouldSpeculateStringIdent()) {
1700 fixEdge<StringIdentUse>(node->child1());
1701 node->convertToIdentity();
1705 if (node->child1()->shouldSpeculateString()) {
1706 fixEdge<StringUse>(node->child1());
1707 node->convertToIdentity();
1712 if (node->child1()->shouldSpeculateOther()) {
1713 if (ecmaMode == StrictMode) {
1714 fixEdge<OtherUse>(node->child1());
1715 node->convertToIdentity();
1719 m_insertionSet.insertNode(
1720 m_indexInBlock, SpecNone, Check, node->origin,
1721 Edge(node->child1().node(), OtherUse));
1722 observeUseKindOnNode<OtherUse>(node->child1().node());
1723 m_graph.convertToConstant(
1724 node, m_graph.globalThisObjectFor(node->origin.semantic));
1728 if (node->child1()->shouldSpeculateStringObject()) {
1729 fixEdge<StringObjectUse>(node->child1());
1730 node->convertToIdentity();
1734 if (isFinalObjectSpeculation(node->child1()->prediction())) {
1735 fixEdge<FinalObjectUse>(node->child1());
1736 node->convertToIdentity();
1741 void fixupToPrimitive(Node* node)
1743 if (node->child1()->shouldSpeculateInt32()) {
1744 fixEdge<Int32Use>(node->child1());
1745 node->convertToIdentity();
1749 if (node->child1()->shouldSpeculateString()) {
1750 fixEdge<StringUse>(node->child1());
1751 node->convertToIdentity();
1755 if (node->child1()->shouldSpeculateStringObject()
1756 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1757 fixEdge<StringObjectUse>(node->child1());
1758 node->convertToToString();
1762 if (node->child1()->shouldSpeculateStringOrStringObject()
1763 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1764 fixEdge<StringOrStringObjectUse>(node->child1());
1765 node->convertToToString();
1770 void fixupToStringOrCallStringConstructor(Node* node)
1772 if (node->child1()->shouldSpeculateString()) {
1773 fixEdge<StringUse>(node->child1());
1774 node->convertToIdentity();
1778 if (node->child1()->shouldSpeculateStringObject()
1779 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1780 fixEdge<StringObjectUse>(node->child1());
1784 if (node->child1()->shouldSpeculateStringOrStringObject()
1785 && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1786 fixEdge<StringOrStringObjectUse>(node->child1());
1790 if (node->child1()->shouldSpeculateCell()) {
1791 fixEdge<CellUse>(node->child1());
1796 bool attemptToMakeFastStringAdd(Node* node)
1798 bool goodToGo = true;
1799 m_graph.doToChildren(
1802 if (edge->shouldSpeculateString())
1804 if (m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
1805 if (edge->shouldSpeculateStringObject())
1807 if (edge->shouldSpeculateStringOrStringObject())
1815 m_graph.doToChildren(
1818 if (edge->shouldSpeculateString()) {
1819 convertStringAddUse<StringUse>(node, edge);
1822 ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
1823 if (edge->shouldSpeculateStringObject()) {
1824 convertStringAddUse<StringObjectUse>(node, edge);
1827 if (edge->shouldSpeculateStringOrStringObject()) {
1828 convertStringAddUse<StringOrStringObjectUse>(node, edge);
1831 RELEASE_ASSERT_NOT_REACHED();
1834 convertToMakeRope(node);
1838 void fixupGetAndSetLocalsInBlock(BasicBlock* block)
1842 ASSERT(block->isReachable);
1844 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1845 Node* node = m_currentNode = block->at(m_indexInBlock);
1846 if (node->op() != SetLocal && node->op() != GetLocal)
1849 VariableAccessData* variable = node->variableAccessData();
1850 switch (node->op()) {
1852 switch (variable->flushFormat()) {
1854 node->setResult(NodeResultDouble);
1857 node->setResult(NodeResultInt52);
1865 // NOTE: Any type checks we put here may get hoisted by fixupChecksInBlock(). So, if we
1866 // add new type checking use kind for SetLocals, we need to modify that code as well.
1868 switch (variable->flushFormat()) {
1869 case FlushedJSValue:
1872 fixEdge<DoubleRepUse>(node->child1());
1875 fixEdge<Int32Use>(node->child1());
1878 fixEdge<Int52RepUse>(node->child1());
1881 fixEdge<CellUse>(node->child1());
1883 case FlushedBoolean:
1884 fixEdge<BooleanUse>(node->child1());
1887 RELEASE_ASSERT_NOT_REACHED();
1893 RELEASE_ASSERT_NOT_REACHED();
1897 m_insertionSet.execute(block);
1900 Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
1902 ASSERT(arrayMode.isSpecific());
1904 if (arrayMode.type() == Array::String) {
1905 m_insertionSet.insertNode(
1906 m_indexInBlock, SpecNone, Check, origin, Edge(array, StringUse));
1908 // Note that we only need to be using a structure check if we opt for SaneChain, since
1909 // that needs to protect against JSArray's __proto__ being changed.
1910 Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
1912 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1914 if (arrayMode.doesConversion()) {
1916 m_insertionSet.insertNode(
1917 m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
1918 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1920 m_insertionSet.insertNode(
1921 m_indexInBlock, SpecNone, Arrayify, origin,
1922 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1926 m_insertionSet.insertNode(
1927 m_indexInBlock, SpecNone, CheckStructure, origin,
1928 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1930 m_insertionSet.insertNode(
1931 m_indexInBlock, SpecNone, CheckArray, origin,
1932 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1937 if (!storageCheck(arrayMode))
1940 if (arrayMode.usesButterfly()) {
1941 return m_insertionSet.insertNode(
1942 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
1945 return m_insertionSet.insertNode(
1946 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
1947 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
1950 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
1952 Node* node = m_currentNode;
1954 switch (node->arrayMode().type()) {
1955 case Array::ForceExit: {
1956 m_insertionSet.insertNode(
1957 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
1961 case Array::SelectUsingPredictions:
1962 case Array::Unprofiled:
1963 RELEASE_ASSERT_NOT_REACHED();
1966 case Array::Generic:
1970 Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
1974 storageChild = Edge(storage);
1979 bool alwaysUnboxSimplePrimitives()
1984 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1990 template<UseKind useKind>
1991 void observeUseKindOnNode(Node* node)
1993 if (useKind == UntypedUse)
1995 observeUseKindOnNode(node, useKind);
1998 void observeUseKindOnEdge(Edge edge)
2000 observeUseKindOnNode(edge.node(), edge.useKind());
2003 void observeUseKindOnNode(Node* node, UseKind useKind)
2005 if (node->op() != GetLocal)
2008 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
2009 // https://bugs.webkit.org/show_bug.cgi?id=121518
2011 VariableAccessData* variable = node->variableAccessData();
2015 if (alwaysUnboxSimplePrimitives()
2016 || isInt32Speculation(variable->prediction()))
2017 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2022 case DoubleRepRealUse:
2023 if (variable->doubleFormatState() == UsingDoubleFormat)
2024 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2027 case KnownBooleanUse:
2028 if (alwaysUnboxSimplePrimitives()
2029 || isBooleanSpeculation(variable->prediction()))
2030 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2033 if (isMachineIntSpeculation(variable->prediction()))
2034 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2041 case KnownStringUse:
2043 case StringObjectUse:
2044 case StringOrStringObjectUse:
2045 if (alwaysUnboxSimplePrimitives()
2046 || isCellSpeculation(variable->prediction()))
2047 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
2054 template<UseKind useKind>
2055 void fixEdge(Edge& edge)
2057 observeUseKindOnNode<useKind>(edge.node());
2058 edge.setUseKind(useKind);
2061 void speculateForBarrier(Edge value)
2063 // Currently, the DFG won't take advantage of this speculation. But, we want to do it in
2064 // the DFG anyway because if such a speculation would be wrong, we want to know before
2065 // we do an expensive compile.
2067 if (value->shouldSpeculateInt32()) {
2068 insertCheck<Int32Use>(m_indexInBlock, value.node());
2072 if (value->shouldSpeculateBoolean()) {
2073 insertCheck<BooleanUse>(m_indexInBlock, value.node());
2077 if (value->shouldSpeculateOther()) {
2078 insertCheck<OtherUse>(m_indexInBlock, value.node());
2082 if (value->shouldSpeculateNumber()) {
2083 insertCheck<NumberUse>(m_indexInBlock, value.node());
2087 if (value->shouldSpeculateNotCell()) {
2088 insertCheck<NotCellUse>(m_indexInBlock, value.node());
2093 template<UseKind useKind>
2094 void insertCheck(unsigned indexInBlock, Node* node)
2096 observeUseKindOnNode<useKind>(node);
2097 m_insertionSet.insertNode(
2098 indexInBlock, SpecNone, Check, m_currentNode->origin, Edge(node, useKind));
2101 void fixIntConvertingEdge(Edge& edge)
2103 Node* node = edge.node();
2104 if (node->shouldSpeculateInt32OrBoolean()) {
2105 fixIntOrBooleanEdge(edge);
2110 if (node->shouldSpeculateMachineInt())
2111 useKind = Int52RepUse;
2112 else if (node->shouldSpeculateNumber())
2113 useKind = DoubleRepUse;
2115 useKind = NotCellUse;
2116 Node* newNode = m_insertionSet.insertNode(
2117 m_indexInBlock, SpecInt32, ValueToInt32, m_currentNode->origin,
2118 Edge(node, useKind));
2119 observeUseKindOnNode(node, useKind);
2121 edge = Edge(newNode, KnownInt32Use);
2124 void fixIntOrBooleanEdge(Edge& edge)
2126 Node* node = edge.node();
2127 if (!node->sawBooleans()) {
2128 fixEdge<Int32Use>(edge);
2133 if (node->shouldSpeculateBoolean())
2134 useKind = BooleanUse;
2136 useKind = UntypedUse;
2137 Node* newNode = m_insertionSet.insertNode(
2138 m_indexInBlock, SpecInt32, BooleanToNumber, m_currentNode->origin,
2139 Edge(node, useKind));
2140 observeUseKindOnNode(node, useKind);
2142 edge = Edge(newNode, Int32Use);
2145 void fixDoubleOrBooleanEdge(Edge& edge)
2147 Node* node = edge.node();
2148 if (!node->sawBooleans()) {
2149 fixEdge<DoubleRepUse>(edge);
2154 if (node->shouldSpeculateBoolean())
2155 useKind = BooleanUse;
2157 useKind = UntypedUse;
2158 Node* newNode = m_insertionSet.insertNode(
2159 m_indexInBlock, SpecInt32, BooleanToNumber, m_currentNode->origin,
2160 Edge(node, useKind));
2161 observeUseKindOnNode(node, useKind);
2163 edge = Edge(newNode, DoubleRepUse);
2166 void truncateConstantToInt32(Edge& edge)
2168 Node* oldNode = edge.node();
2170 JSValue value = oldNode->asJSValue();
2171 if (value.isInt32())
2174 value = jsNumber(JSC::toInt32(value.asNumber()));
2175 ASSERT(value.isInt32());
2176 edge.setNode(m_insertionSet.insertNode(
2177 m_indexInBlock, SpecInt32, JSConstant, m_currentNode->origin,
2178 OpInfo(m_graph.freeze(value))));
2181 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
2183 if (mode != SpeculateInt32AndTruncateConstants)
2186 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
2187 if (node->child1()->hasConstant())
2188 truncateConstantToInt32(node->child1());
2190 truncateConstantToInt32(node->child2());
2193 bool attemptToMakeIntegerAdd(Node* node)
2195 AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
2196 if (mode != DontSpeculateInt32) {
2197 truncateConstantsIfNecessary(node, mode);
2198 fixIntOrBooleanEdge(node->child1());
2199 fixIntOrBooleanEdge(node->child2());
2200 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
2201 node->setArithMode(Arith::Unchecked);
2203 node->setArithMode(Arith::CheckOverflow);
2207 if (m_graph.addShouldSpeculateMachineInt(node)) {
2208 fixEdge<Int52RepUse>(node->child1());
2209 fixEdge<Int52RepUse>(node->child2());
2210 node->setArithMode(Arith::CheckOverflow);
2211 node->setResult(NodeResultInt52);
2218 bool attemptToMakeGetArrayLength(Node* node)
2220 if (!isInt32Speculation(node->prediction()))
2222 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
2223 ArrayProfile* arrayProfile =
2224 profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex);
2225 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
2227 ConcurrentJITLocker locker(profiledBlock->m_lock);
2228 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
2229 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
2230 if (arrayMode.type() == Array::Unprofiled) {
2231 // For normal array operations, it makes sense to treat Unprofiled
2232 // accesses as ForceExit and get more data rather than using
2233 // predictions and then possibly ending up with a Generic. But here,
2234 // we treat anything that is Unprofiled as Generic and keep the
2235 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
2236 // profit - from treating the Unprofiled case as
2237 // SelectUsingPredictions.
2238 arrayMode = ArrayMode(Array::SelectUsingPredictions);
2242 arrayMode = arrayMode.refine(
2243 m_graph, node, node->child1()->prediction(), node->prediction());
2245 if (arrayMode.type() == Array::Generic) {
2246 // Check if the input is something that we can't get array length for, but for which we
2247 // could insert some conversions in order to transform it into something that we can do it
2249 if (node->child1()->shouldSpeculateStringObject())
2250 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
2251 else if (node->child1()->shouldSpeculateStringOrStringObject())
2252 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
2255 if (!arrayMode.supportsSelfLength())
2258 convertToGetArrayLength(node, arrayMode);
2262 void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
2264 node->setOp(GetArrayLength);
2265 node->clearFlags(NodeMustGenerate);
2266 fixEdge<KnownCellUse>(node->child1());
2267 node->setArrayMode(arrayMode);
2269 Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
2273 node->child2() = Edge(storage);
2276 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
2278 Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
2279 return m_insertionSet.insertNode(
2280 m_indexInBlock, SpecInt32, GetArrayLength, origin,
2281 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
2284 void fixupChecksInBlock(BasicBlock* block)
2288 ASSERT(block->isReachable);
2290 unsigned indexForChecks = UINT_MAX;
2291 NodeOrigin originForChecks;
2292 for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
2293 Node* node = block->at(indexInBlock);
2295 // If this is a node at which we could exit, then save its index. If nodes after this one
2296 // cannot exit, then we will hoist checks to here.
2297 if (node->origin.exitOK) {
2298 indexForChecks = indexInBlock;
2299 originForChecks = node->origin;
2302 originForChecks = originForChecks.withSemantic(node->origin.semantic);
2304 // First, try to relax the representational demands of each node, in order to have
2305 // fewer conversions.
2306 switch (node->op()) {
2309 m_graph.doToChildren(
2312 switch (edge.useKind()) {
2314 case DoubleRepRealUse:
2315 if (edge->hasDoubleResult())
2318 if (edge->hasInt52Result())
2319 edge.setUseKind(Int52RepUse);
2320 else if (edge.useKind() == DoubleRepUse)
2321 edge.setUseKind(NumberUse);
2325 // Nothing we can really do.
2330 if (edge->hasDoubleResult())
2331 edge.setUseKind(DoubleRepUse);
2332 else if (edge->hasInt52Result())
2333 edge.setUseKind(Int52RepUse);
2337 if (edge->hasDoubleResult())
2338 edge.setUseKind(DoubleRepRealUse);
2339 else if (edge->hasInt52Result())
2340 edge.setUseKind(Int52RepUse);
2350 if (node->child1().useKind() == DoubleRepUse
2351 && !node->child1()->hasDoubleResult()) {
2352 node->child1().setUseKind(NumberUse);
2361 // Now, insert type conversions if necessary.
2362 m_graph.doToChildren(
2365 Node* result = nullptr;
2367 switch (edge.useKind()) {
2369 case DoubleRepRealUse:
2370 case DoubleRepMachineIntUse: {
2371 if (edge->hasDoubleResult())
2374 if (edge->isNumberConstant()) {
2375 result = m_insertionSet.insertNode(
2376 indexForChecks, SpecBytecodeDouble, DoubleConstant, originForChecks,
2377 OpInfo(m_graph.freeze(jsDoubleNumber(edge->asNumber()))));
2378 } else if (edge->hasInt52Result()) {
2379 result = m_insertionSet.insertNode(
2380 indexForChecks, SpecInt52AsDouble, DoubleRep, originForChecks,
2381 Edge(edge.node(), Int52RepUse));
2384 if (edge->shouldSpeculateDoubleReal())
2385 useKind = RealNumberUse;
2386 else if (edge->shouldSpeculateNumber())
2387 useKind = NumberUse;
2389 useKind = NotCellUse;
2391 result = m_insertionSet.insertNode(
2392 indexForChecks, SpecBytecodeDouble, DoubleRep, originForChecks,
2393 Edge(edge.node(), useKind));
2396 edge.setNode(result);
2401 if (edge->hasInt52Result())
2404 if (edge->isMachineIntConstant()) {
2405 result = m_insertionSet.insertNode(
2406 indexForChecks, SpecMachineInt, Int52Constant, originForChecks,
2407 OpInfo(edge->constant()));
2408 } else if (edge->hasDoubleResult()) {
2409 result = m_insertionSet.insertNode(
2410 indexForChecks, SpecMachineInt, Int52Rep, originForChecks,
2411 Edge(edge.node(), DoubleRepMachineIntUse));
2412 } else if (edge->shouldSpeculateInt32ForArithmetic()) {
2413 result = m_insertionSet.insertNode(
2414 indexForChecks, SpecInt32, Int52Rep, originForChecks,
2415 Edge(edge.node(), Int32Use));
2417 result = m_insertionSet.insertNode(
2418 indexForChecks, SpecMachineInt, Int52Rep, originForChecks,
2419 Edge(edge.node(), MachineIntUse));
2422 edge.setNode(result);
2427 if (!edge->hasDoubleResult() && !edge->hasInt52Result())
2430 if (edge->hasDoubleResult()) {
2431 result = m_insertionSet.insertNode(
2432 indexForChecks, SpecBytecodeDouble, ValueRep, originForChecks,
2433 Edge(edge.node(), DoubleRepUse));
2435 result = m_insertionSet.insertNode(
2436 indexForChecks, SpecInt32 | SpecInt52AsDouble, ValueRep,
2437 originForChecks, Edge(edge.node(), Int52RepUse));
2440 edge.setNode(result);
2444 // It's remotely possible that this node cannot do type checks, but we now have a
2445 // type check on this node. We don't have to handle the general form of this
2446 // problem. It only arises when ByteCodeParser emits an immediate SetLocal, rather
2447 // than a delayed one. So, we only worry about those checks that we may have put on
2448 // a SetLocal. Note that "indexForChecks != indexInBlock" is just another way of
2449 // saying "!node->origin.exitOK".
2450 if (indexForChecks != indexInBlock && mayHaveTypeCheck(edge.useKind())) {
2451 UseKind knownUseKind;
2453 switch (edge.useKind()) {
2455 knownUseKind = KnownInt32Use;
2458 knownUseKind = KnownCellUse;
2461 knownUseKind = KnownBooleanUse;
2464 // This can only arise if we have a Check node, and in that case, we can
2465 // just remove the original check.
2466 DFG_ASSERT(m_graph, node, node->op() == Check);
2467 knownUseKind = UntypedUse;
2471 m_insertionSet.insertNode(
2472 indexForChecks, SpecNone, Check, originForChecks, edge);
2474 edge.setUseKind(knownUseKind);
2479 m_insertionSet.execute(block);
2482 BasicBlock* m_block;
2483 unsigned m_indexInBlock;
2484 Node* m_currentNode;
2485 InsertionSet m_insertionSet;
2486 bool m_profitabilityChanged;
2489 bool performFixup(Graph& graph)
2491 return runPhase<FixupPhase>(graph);
2494 } } // namespace JSC::DFG
2496 #endif // ENABLE(DFG_JIT)