e862d6343c060cd61dc150012e3843f8bd874ec3
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGFixupPhase.cpp
1 /*
2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGFixupPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGGraph.h"
32 #include "DFGInsertionSet.h"
33 #include "DFGPhase.h"
34 #include "DFGPredictionPropagationPhase.h"
35 #include "DFGVariableAccessDataDump.h"
36 #include "Operations.h"
37
38 namespace JSC { namespace DFG {
39
40 class FixupPhase : public Phase {
41 public:
42     FixupPhase(Graph& graph)
43         : Phase(graph, "fixup")
44         , m_insertionSet(graph)
45     {
46     }
47     
48     bool run()
49     {
50         ASSERT(m_graph.m_fixpointState == BeforeFixpoint);
51         ASSERT(m_graph.m_form == ThreadedCPS);
52         
53         m_profitabilityChanged = false;
54         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
55             fixupBlock(m_graph.block(blockIndex));
56         
57         while (m_profitabilityChanged) {
58             m_profitabilityChanged = false;
59             
60             for (unsigned i = m_graph.m_argumentPositions.size(); i--;)
61                 m_graph.m_argumentPositions[i].mergeArgumentUnboxingAwareness();
62             
63             for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
64                 fixupSetLocalsInBlock(m_graph.block(blockIndex));
65         }
66         
67         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
68             fixupUntypedSetLocalsInBlock(m_graph.block(blockIndex));
69         
70         return true;
71     }
72
73 private:
74     void fixupBlock(BasicBlock* block)
75     {
76         if (!block)
77             return;
78         ASSERT(block->isReachable);
79         m_block = block;
80         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
81             m_currentNode = block->at(m_indexInBlock);
82             fixupNode(m_currentNode);
83         }
84         m_insertionSet.execute(block);
85     }
86     
87     void fixupNode(Node* node)
88     {
89         NodeType op = node->op();
90
91 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
92         dataLogF("   %s @%u: ", Graph::opName(op), node->index());
93 #endif
94         
95         switch (op) {
96         case SetLocal: {
97             // This gets handled by fixupSetLocalsInBlock().
98             return;
99         }
100             
101         case BitAnd:
102         case BitOr:
103         case BitXor:
104         case BitRShift:
105         case BitLShift:
106         case BitURShift:
107         case ArithIMul: {
108             fixIntEdge(node->child1());
109             fixIntEdge(node->child2());
110             break;
111         }
112             
113         case UInt32ToNumber: {
114             fixEdge<KnownInt32Use>(node->child1());
115             break;
116         }
117             
118         case DoubleAsInt32: {
119             RELEASE_ASSERT_NOT_REACHED();
120             break;
121         }
122             
123         case ValueToInt32: {
124             if (node->child1()->shouldSpeculateInt32()) {
125                 fixEdge<Int32Use>(node->child1());
126                 node->setOpAndDefaultFlags(Identity);
127                 break;
128             }
129             
130             if (node->child1()->shouldSpeculateMachineInt()) {
131                 fixEdge<MachineIntUse>(node->child1());
132                 break;
133             }
134             
135             if (node->child1()->shouldSpeculateNumber()) {
136                 fixEdge<NumberUse>(node->child1());
137                 break;
138             }
139             
140             if (node->child1()->shouldSpeculateBoolean()) {
141                 fixEdge<BooleanUse>(node->child1());
142                 break;
143             }
144             
145             fixEdge<NotCellUse>(node->child1());
146             break;
147         }
148             
149         case Int32ToDouble: {
150             RELEASE_ASSERT_NOT_REACHED();
151             break;
152         }
153             
154         case ValueAdd: {
155             if (attemptToMakeIntegerAdd(node))
156                 break;
157             if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {
158                 fixEdge<NumberUse>(node->child1());
159                 fixEdge<NumberUse>(node->child2());
160                 break;
161             }
162             
163             // FIXME: Optimize for the case where one of the operands is the
164             // empty string. Also consider optimizing for the case where we don't
165             // believe either side is the emtpy string. Both of these things should
166             // be easy.
167             
168             if (node->child1()->shouldSpeculateString()
169                 && attemptToMakeFastStringAdd<StringUse>(node, node->child1(), node->child2()))
170                 break;
171             if (node->child2()->shouldSpeculateString()
172                 && attemptToMakeFastStringAdd<StringUse>(node, node->child2(), node->child1()))
173                 break;
174             if (node->child1()->shouldSpeculateStringObject()
175                 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child1(), node->child2()))
176                 break;
177             if (node->child2()->shouldSpeculateStringObject()
178                 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child2(), node->child1()))
179                 break;
180             if (node->child1()->shouldSpeculateStringOrStringObject()
181                 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child1(), node->child2()))
182                 break;
183             if (node->child2()->shouldSpeculateStringOrStringObject()
184                 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child2(), node->child1()))
185                 break;
186             break;
187         }
188             
189         case MakeRope: {
190             fixupMakeRope(node);
191             break;
192         }
193             
194         case ArithAdd:
195         case ArithSub: {
196             if (attemptToMakeIntegerAdd(node))
197                 break;
198             fixEdge<NumberUse>(node->child1());
199             fixEdge<NumberUse>(node->child2());
200             break;
201         }
202             
203         case ArithNegate: {
204             if (m_graph.negateShouldSpeculateInt32(node)) {
205                 fixEdge<Int32Use>(node->child1());
206                 break;
207             }
208             if (m_graph.negateShouldSpeculateMachineInt(node)) {
209                 fixEdge<MachineIntUse>(node->child1());
210                 break;
211             }
212             fixEdge<NumberUse>(node->child1());
213             break;
214         }
215             
216         case ArithMul: {
217             if (m_graph.mulShouldSpeculateInt32(node)) {
218                 fixEdge<Int32Use>(node->child1());
219                 fixEdge<Int32Use>(node->child2());
220                 break;
221             }
222             if (m_graph.mulShouldSpeculateMachineInt(node)) {
223                 fixEdge<MachineIntUse>(node->child1());
224                 fixEdge<MachineIntUse>(node->child2());
225                 break;
226             }
227             fixEdge<NumberUse>(node->child1());
228             fixEdge<NumberUse>(node->child2());
229             break;
230         }
231
232         case ArithDiv:
233         case ArithMod: {
234             if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
235                 && node->canSpeculateInt32()) {
236                 if (isX86() || isARMv7s()) {
237                     fixEdge<Int32Use>(node->child1());
238                     fixEdge<Int32Use>(node->child2());
239                     break;
240                 }
241                 injectInt32ToDoubleNode(node->child1());
242                 injectInt32ToDoubleNode(node->child2());
243
244                 // We don't need to do ref'ing on the children because we're stealing them from
245                 // the original division.
246                 Node* newDivision = m_insertionSet.insertNode(
247                     m_indexInBlock, SpecDouble, *node);
248                 
249                 node->setOp(DoubleAsInt32);
250                 node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
251                 break;
252             }
253             fixEdge<NumberUse>(node->child1());
254             fixEdge<NumberUse>(node->child2());
255             break;
256         }
257             
258         case ArithMin:
259         case ArithMax: {
260             if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
261                 && node->canSpeculateInt32()) {
262                 fixEdge<Int32Use>(node->child1());
263                 fixEdge<Int32Use>(node->child2());
264                 break;
265             }
266             fixEdge<NumberUse>(node->child1());
267             fixEdge<NumberUse>(node->child2());
268             break;
269         }
270             
271         case ArithAbs: {
272             if (node->child1()->shouldSpeculateInt32ForArithmetic()
273                 && node->canSpeculateInt32()) {
274                 fixEdge<Int32Use>(node->child1());
275                 break;
276             }
277             fixEdge<NumberUse>(node->child1());
278             break;
279         }
280             
281         case ArithSqrt: {
282             fixEdge<NumberUse>(node->child1());
283             break;
284         }
285             
286         case LogicalNot: {
287             if (node->child1()->shouldSpeculateBoolean())
288                 fixEdge<BooleanUse>(node->child1());
289             else if (node->child1()->shouldSpeculateObjectOrOther())
290                 fixEdge<ObjectOrOtherUse>(node->child1());
291             else if (node->child1()->shouldSpeculateInt32())
292                 fixEdge<Int32Use>(node->child1());
293             else if (node->child1()->shouldSpeculateNumber())
294                 fixEdge<NumberUse>(node->child1());
295             break;
296         }
297             
298         case TypeOf: {
299             if (node->child1()->shouldSpeculateString())
300                 fixEdge<StringUse>(node->child1());
301             else if (node->child1()->shouldSpeculateCell())
302                 fixEdge<CellUse>(node->child1());
303             break;
304         }
305             
306         case CompareEqConstant: {
307             break;
308         }
309
310         case CompareEq:
311         case CompareLess:
312         case CompareLessEq:
313         case CompareGreater:
314         case CompareGreaterEq: {
315             if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
316                 fixEdge<Int32Use>(node->child1());
317                 fixEdge<Int32Use>(node->child2());
318                 break;
319             }
320             if (enableInt52()
321                 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
322                 fixEdge<MachineIntUse>(node->child1());
323                 fixEdge<MachineIntUse>(node->child2());
324                 break;
325             }
326             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
327                 fixEdge<NumberUse>(node->child1());
328                 fixEdge<NumberUse>(node->child2());
329                 break;
330             }
331             if (node->op() != CompareEq)
332                 break;
333             if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
334                 fixEdge<BooleanUse>(node->child1());
335                 fixEdge<BooleanUse>(node->child2());
336                 break;
337             }
338             if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
339                 fixEdge<StringIdentUse>(node->child1());
340                 fixEdge<StringIdentUse>(node->child2());
341                 break;
342             }
343             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
344                 fixEdge<StringUse>(node->child1());
345                 fixEdge<StringUse>(node->child2());
346                 break;
347             }
348             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
349                 fixEdge<ObjectUse>(node->child1());
350                 fixEdge<ObjectUse>(node->child2());
351                 break;
352             }
353             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
354                 fixEdge<ObjectUse>(node->child1());
355                 fixEdge<ObjectOrOtherUse>(node->child2());
356                 break;
357             }
358             if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
359                 fixEdge<ObjectOrOtherUse>(node->child1());
360                 fixEdge<ObjectUse>(node->child2());
361                 break;
362             }
363             break;
364         }
365             
366         case CompareStrictEqConstant: {
367             break;
368         }
369             
370         case CompareStrictEq: {
371             if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
372                 fixEdge<BooleanUse>(node->child1());
373                 fixEdge<BooleanUse>(node->child2());
374                 break;
375             }
376             if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
377                 fixEdge<Int32Use>(node->child1());
378                 fixEdge<Int32Use>(node->child2());
379                 break;
380             }
381             if (enableInt52()
382                 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
383                 fixEdge<MachineIntUse>(node->child1());
384                 fixEdge<MachineIntUse>(node->child2());
385                 break;
386             }
387             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
388                 fixEdge<NumberUse>(node->child1());
389                 fixEdge<NumberUse>(node->child2());
390                 break;
391             }
392             if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
393                 fixEdge<StringIdentUse>(node->child1());
394                 fixEdge<StringIdentUse>(node->child2());
395                 break;
396             }
397             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
398                 fixEdge<StringUse>(node->child1());
399                 fixEdge<StringUse>(node->child2());
400                 break;
401             }
402             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
403                 fixEdge<ObjectUse>(node->child1());
404                 fixEdge<ObjectUse>(node->child2());
405                 break;
406             }
407             break;
408         }
409
410         case StringFromCharCode:
411             fixEdge<Int32Use>(node->child1());
412             break;
413
414         case StringCharAt:
415         case StringCharCodeAt: {
416             // Currently we have no good way of refining these.
417             ASSERT(node->arrayMode() == ArrayMode(Array::String));
418             blessArrayOperation(node->child1(), node->child2(), node->child3());
419             fixEdge<KnownCellUse>(node->child1());
420             fixEdge<Int32Use>(node->child2());
421             break;
422         }
423
424         case GetByVal: {
425             node->setArrayMode(
426                 node->arrayMode().refine(
427                     node->child1()->prediction(),
428                     node->child2()->prediction(),
429                     SpecNone, node->flags()));
430             
431             blessArrayOperation(node->child1(), node->child2(), node->child3());
432             
433             ArrayMode arrayMode = node->arrayMode();
434             switch (arrayMode.type()) {
435             case Array::Double:
436                 if (arrayMode.arrayClass() == Array::OriginalArray
437                     && arrayMode.speculation() == Array::InBounds
438                     && m_graph.globalObjectFor(node->codeOrigin)->arrayPrototypeChainIsSane()
439                     && !(node->flags() & NodeBytecodeUsesAsOther))
440                     node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
441                 break;
442                 
443             case Array::String:
444                 if ((node->prediction() & ~SpecString)
445                     || m_graph.hasExitSite(node->codeOrigin, OutOfBounds))
446                     node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
447                 break;
448                 
449             default:
450                 break;
451             }
452             
453             switch (node->arrayMode().type()) {
454             case Array::SelectUsingPredictions:
455             case Array::Unprofiled:
456             case Array::Undecided:
457                 RELEASE_ASSERT_NOT_REACHED();
458                 break;
459             case Array::Generic:
460 #if USE(JSVALUE32_64)
461                 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
462 #endif
463                 break;
464             case Array::ForceExit:
465                 break;
466             default:
467                 fixEdge<KnownCellUse>(node->child1());
468                 fixEdge<Int32Use>(node->child2());
469                 break;
470             }
471             
472             break;
473         }
474             
475         case PutByVal:
476         case PutByValAlias: {
477             Edge& child1 = m_graph.varArgChild(node, 0);
478             Edge& child2 = m_graph.varArgChild(node, 1);
479             Edge& child3 = m_graph.varArgChild(node, 2);
480
481             node->setArrayMode(
482                 node->arrayMode().refine(
483                     child1->prediction(),
484                     child2->prediction(),
485                     child3->prediction()));
486             
487             blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
488             
489             switch (node->arrayMode().modeForPut().type()) {
490             case Array::SelectUsingPredictions:
491             case Array::Unprofiled:
492             case Array::Undecided:
493                 RELEASE_ASSERT_NOT_REACHED();
494                 break;
495             case Array::ForceExit:
496             case Array::Generic:
497 #if USE(JSVALUE32_64)
498                 // Due to register pressure on 32-bit, we speculate cell and
499                 // ignore the base-is-not-cell case entirely by letting the
500                 // baseline JIT handle it.
501                 fixEdge<CellUse>(child1);
502 #endif
503                 break;
504             case Array::Int32:
505                 fixEdge<KnownCellUse>(child1);
506                 fixEdge<Int32Use>(child2);
507                 fixEdge<Int32Use>(child3);
508                 if (child3->prediction() & SpecInt52)
509                     fixEdge<MachineIntUse>(child3);
510                 else
511                     fixEdge<Int32Use>(child3);
512                 break;
513             case Array::Double:
514                 fixEdge<KnownCellUse>(child1);
515                 fixEdge<Int32Use>(child2);
516                 fixEdge<RealNumberUse>(child3);
517                 break;
518             case Array::Int8Array:
519             case Array::Int16Array:
520             case Array::Int32Array:
521             case Array::Uint8Array:
522             case Array::Uint8ClampedArray:
523             case Array::Uint16Array:
524             case Array::Uint32Array:
525                 fixEdge<KnownCellUse>(child1);
526                 fixEdge<Int32Use>(child2);
527                 if (child3->shouldSpeculateInt32())
528                     fixEdge<Int32Use>(child3);
529                 else if (child3->shouldSpeculateMachineInt())
530                     fixEdge<MachineIntUse>(child3);
531                 else
532                     fixEdge<NumberUse>(child3);
533                 break;
534             case Array::Float32Array:
535             case Array::Float64Array:
536                 fixEdge<KnownCellUse>(child1);
537                 fixEdge<Int32Use>(child2);
538                 fixEdge<NumberUse>(child3);
539                 break;
540             default:
541                 fixEdge<KnownCellUse>(child1);
542                 fixEdge<Int32Use>(child2);
543                 break;
544             }
545             break;
546         }
547             
548         case ArrayPush: {
549             // May need to refine the array mode in case the value prediction contravenes
550             // the array prediction. For example, we may have evidence showing that the
551             // array is in Int32 mode, but the value we're storing is likely to be a double.
552             // Then we should turn this into a conversion to Double array followed by the
553             // push. On the other hand, we absolutely don't want to refine based on the
554             // base prediction. If it has non-cell garbage in it, then we want that to be
555             // ignored. That's because ArrayPush can't handle any array modes that aren't
556             // array-related - so if refine() turned this into a "Generic" ArrayPush then
557             // that would break things.
558             node->setArrayMode(
559                 node->arrayMode().refine(
560                     node->child1()->prediction() & SpecCell,
561                     SpecInt32,
562                     node->child2()->prediction()));
563             blessArrayOperation(node->child1(), Edge(), node->child3());
564             fixEdge<KnownCellUse>(node->child1());
565             
566             switch (node->arrayMode().type()) {
567             case Array::Int32:
568                 fixEdge<Int32Use>(node->child2());
569                 break;
570             case Array::Double:
571                 fixEdge<RealNumberUse>(node->child2());
572                 break;
573             default:
574                 break;
575             }
576             break;
577         }
578             
579         case ArrayPop: {
580             blessArrayOperation(node->child1(), Edge(), node->child2());
581             fixEdge<KnownCellUse>(node->child1());
582             break;
583         }
584             
585         case RegExpExec:
586         case RegExpTest: {
587             fixEdge<CellUse>(node->child1());
588             fixEdge<CellUse>(node->child2());
589             break;
590         }
591             
592         case Branch: {
593             if (node->child1()->shouldSpeculateBoolean())
594                 fixEdge<BooleanUse>(node->child1());
595             else if (node->child1()->shouldSpeculateObjectOrOther())
596                 fixEdge<ObjectOrOtherUse>(node->child1());
597             else if (node->child1()->shouldSpeculateInt32())
598                 fixEdge<Int32Use>(node->child1());
599             else if (node->child1()->shouldSpeculateNumber())
600                 fixEdge<NumberUse>(node->child1());
601
602             Node* logicalNot = node->child1().node();
603             if (logicalNot->op() == LogicalNot) {
604                 
605                 // Make sure that OSR exit can't observe the LogicalNot. If it can,
606                 // then we must compute it and cannot peephole around it.
607                 bool found = false;
608                 bool ok = true;
609                 for (unsigned i = m_indexInBlock; i--;) {
610                     Node* candidate = m_block->at(i);
611                     if (candidate == logicalNot) {
612                         found = true;
613                         break;
614                     }
615                     if (candidate->canExit()) {
616                         ok = false;
617                         found = true;
618                         break;
619                     }
620                 }
621                 ASSERT_UNUSED(found, found);
622                 
623                 if (ok) {
624                     Edge newChildEdge = logicalNot->child1();
625                     if (newChildEdge->hasBooleanResult()) {
626                         node->children.setChild1(newChildEdge);
627                         
628                         BasicBlock* toBeTaken = node->notTakenBlock();
629                         BasicBlock* toBeNotTaken = node->takenBlock();
630                         node->setTakenBlock(toBeTaken);
631                         node->setNotTakenBlock(toBeNotTaken);
632                     }
633                 }
634             }
635             break;
636         }
637             
638         case Switch: {
639             SwitchData* data = node->switchData();
640             switch (data->kind) {
641             case SwitchImm:
642                 if (node->child1()->shouldSpeculateInt32())
643                     fixEdge<Int32Use>(node->child1());
644                 break;
645             case SwitchChar:
646                 if (node->child1()->shouldSpeculateString())
647                     fixEdge<StringUse>(node->child1());
648                 break;
649             case SwitchString:
650                 if (node->child1()->shouldSpeculateStringIdent())
651                     fixEdge<StringIdentUse>(node->child1());
652                 else if (node->child1()->shouldSpeculateString())
653                     fixEdge<StringUse>(node->child1());
654                 break;
655             }
656             break;
657         }
658             
659         case ToPrimitive: {
660             fixupToPrimitive(node);
661             break;
662         }
663             
664         case ToString: {
665             fixupToString(node);
666             break;
667         }
668             
669         case NewStringObject: {
670             fixEdge<KnownStringUse>(node->child1());
671             break;
672         }
673             
674         case NewArray: {
675             for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
676                 node->setIndexingType(
677                     leastUpperBoundOfIndexingTypeAndType(
678                         node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
679             }
680             switch (node->indexingType()) {
681             case ALL_BLANK_INDEXING_TYPES:
682                 CRASH();
683                 break;
684             case ALL_UNDECIDED_INDEXING_TYPES:
685                 if (node->numChildren()) {
686                     // This will only happen if the children have no type predictions. We
687                     // would have already exited by now, but insert a forced exit just to
688                     // be safe.
689                     m_insertionSet.insertNode(
690                         m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
691                 }
692                 break;
693             case ALL_INT32_INDEXING_TYPES:
694                 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
695                     fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
696                 break;
697             case ALL_DOUBLE_INDEXING_TYPES:
698                 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
699                     fixEdge<RealNumberUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
700                 break;
701             case ALL_CONTIGUOUS_INDEXING_TYPES:
702             case ALL_ARRAY_STORAGE_INDEXING_TYPES:
703                 break;
704             default:
705                 CRASH();
706                 break;
707             }
708             break;
709         }
710             
711         case NewTypedArray: {
712             if (node->child1()->shouldSpeculateInt32()) {
713                 fixEdge<Int32Use>(node->child1());
714                 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
715                 break;
716             }
717             break;
718         }
719             
720         case NewArrayWithSize: {
721             fixEdge<Int32Use>(node->child1());
722             break;
723         }
724             
725         case ToThis: {
726             ECMAMode ecmaMode = m_graph.executableFor(node->codeOrigin)->isStrictMode() ? StrictMode : NotStrictMode;
727
728             if (isOtherSpeculation(node->child1()->prediction())) {
729                 if (ecmaMode == StrictMode) {
730                     fixEdge<OtherUse>(node->child1());
731                     node->convertToIdentity();
732                     break;
733                 }
734
735                 m_insertionSet.insertNode(
736                     m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
737                     Edge(node->child1().node(), OtherUse));
738                 observeUseKindOnNode<OtherUse>(node->child1().node());
739                 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->codeOrigin));
740                 break;
741             }
742             
743             if (isFinalObjectSpeculation(node->child1()->prediction())) {
744                 fixEdge<FinalObjectUse>(node->child1());
745                 node->convertToIdentity();
746                 break;
747             }
748             
749             break;
750         }
751             
752         case GetMyArgumentByVal:
753         case GetMyArgumentByValSafe: {
754             fixEdge<Int32Use>(node->child1());
755             break;
756         }
757             
758         case GetClosureRegisters:
759         case PutClosureVar:
760         case SkipTopScope:
761         case SkipScope:
762         case SetCallee:
763         case SetMyScope:
764         case PutStructure:
765         case AllocatePropertyStorage:
766         case ReallocatePropertyStorage:
767         case GetScope: {
768             fixEdge<KnownCellUse>(node->child1());
769             break;
770         }
771             
772         case GetById:
773         case GetByIdFlush: {
774             if (!node->child1()->shouldSpeculateCell())
775                 break;
776             StringImpl* impl = m_graph.identifiers()[node->identifierNumber()];
777             if (impl == vm().propertyNames->length.impl()) {
778                 attemptToMakeGetArrayLength(node);
779                 break;
780             }
781             if (impl == vm().propertyNames->byteLength.impl()) {
782                 attemptToMakeGetTypedArrayByteLength(node);
783                 break;
784             }
785             if (impl == vm().propertyNames->byteOffset.impl()) {
786                 attemptToMakeGetTypedArrayByteOffset(node);
787                 break;
788             }
789             fixEdge<CellUse>(node->child1());
790             break;
791         }
792             
793         case CheckExecutable:
794         case CheckStructure:
795         case StructureTransitionWatchpoint:
796         case CheckFunction:
797         case PutById:
798         case PutByIdDirect:
799         case CheckHasInstance:
800         case CreateThis:
801         case GetButterfly: {
802             fixEdge<CellUse>(node->child1());
803             break;
804         }
805             
806         case CheckArray: {
807             switch (node->arrayMode().type()) {
808             case Array::String:
809                 fixEdge<StringUse>(node->child1());
810                 break;
811             default:
812                 fixEdge<CellUse>(node->child1());
813                 break;
814             }
815             break;
816         }
817             
818         case Arrayify:
819         case ArrayifyToStructure: {
820             fixEdge<CellUse>(node->child1());
821             if (node->child2())
822                 fixEdge<Int32Use>(node->child2());
823             break;
824         }
825             
826         case GetByOffset: {
827             if (!node->child1()->hasStorageResult())
828                 fixEdge<KnownCellUse>(node->child1());
829             fixEdge<KnownCellUse>(node->child2());
830             break;
831         }
832             
833         case PutByOffset: {
834             if (!node->child1()->hasStorageResult())
835                 fixEdge<KnownCellUse>(node->child1());
836             fixEdge<KnownCellUse>(node->child2());
837             break;
838         }
839             
840         case InstanceOf: {
841             // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
842             // check. https://bugs.webkit.org/show_bug.cgi?id=107479
843             if (!(node->child1()->prediction() & ~SpecCell))
844                 fixEdge<CellUse>(node->child1());
845             fixEdge<CellUse>(node->child2());
846             break;
847         }
848             
849         case In: {
850             // FIXME: We should at some point have array profiling on op_in, in which
851             // case we would be able to turn this into a kind of GetByVal.
852             
853             fixEdge<CellUse>(node->child2());
854             break;
855         }
856
857         case Phantom:
858         case Identity: {
859             switch (node->child1().useKind()) {
860             case NumberUse:
861                 if (node->child1()->shouldSpeculateInt32ForArithmetic())
862                     node->child1().setUseKind(Int32Use);
863                 break;
864             default:
865                 break;
866             }
867             observeUseKindOnEdge(node->child1());
868             break;
869         }
870
871         case GetArrayLength:
872         case Phi:
873         case Upsilon:
874         case GetArgument:
875         case PhantomPutStructure:
876         case GetIndexedPropertyStorage:
877         case GetTypedArrayByteOffset:
878         case LastNodeType:
879         case MovHint:
880         case MovHintAndCheck:
881         case ZombieHint:
882         case CheckTierUpInLoop:
883         case CheckTierUpAtReturn:
884         case CheckTierUpAndOSREnter:
885         case Int52ToDouble:
886         case Int52ToValue:
887             RELEASE_ASSERT_NOT_REACHED();
888             break;
889         
890 #if !ASSERT_DISABLED    
891         // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
892         case SetArgument:
893         case JSConstant:
894         case WeakJSConstant:
895         case GetLocal:
896         case GetCallee:
897         case Flush:
898         case PhantomLocal:
899         case GetLocalUnlinked:
900         case InlineStart:
901         case GetMyScope:
902         case GetClosureVar:
903         case GetGlobalVar:
904         case PutGlobalVar:
905         case GlobalVarWatchpoint:
906         case VarInjectionWatchpoint:
907         case AllocationProfileWatchpoint:
908         case Call:
909         case Construct:
910         case NewObject:
911         case NewArrayBuffer:
912         case NewRegexp:
913         case Breakpoint:
914         case IsUndefined:
915         case IsBoolean:
916         case IsNumber:
917         case IsString:
918         case IsObject:
919         case IsFunction:
920         case CreateActivation:
921         case TearOffActivation:
922         case CreateArguments:
923         case PhantomArguments:
924         case TearOffArguments:
925         case GetMyArgumentsLength:
926         case GetMyArgumentsLengthSafe:
927         case CheckArgumentsNotCreated:
928         case NewFunction:
929         case NewFunctionNoCheck:
930         case NewFunctionExpression:
931         case Jump:
932         case Return:
933         case Throw:
934         case ThrowReferenceError:
935         case CountExecution:
936         case ForceOSRExit:
937         case CheckWatchdogTimer:
938         case Unreachable:
939         case ExtractOSREntryLocal:
940         case LoopHint:
941             break;
942 #else
943         default:
944             break;
945 #endif
946         }
947         
948         DFG_NODE_DO_TO_CHILDREN(m_graph, node, observeUntypedEdge);
949
950 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
951         if (!(node->flags() & NodeHasVarArgs)) {
952             dataLogF("new children: ");
953             node->dumpChildren(WTF::dataFile());
954         }
955         dataLogF("\n");
956 #endif
957     }
958     
959     void observeUntypedEdge(Node*, Edge& edge)
960     {
961         if (edge.useKind() != UntypedUse)
962             return;
963         fixEdge<UntypedUse>(edge);
964     }
965     
966     template<UseKind useKind>
967     void createToString(Node* node, Edge& edge)
968     {
969         edge.setNode(m_insertionSet.insertNode(
970             m_indexInBlock, SpecString, ToString, node->codeOrigin,
971             Edge(edge.node(), useKind)));
972     }
973     
974     template<UseKind useKind>
975     void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
976     {
977         ASSERT(arrayMode == ArrayMode(Array::Generic));
978         
979         if (!canOptimizeStringObjectAccess(node->codeOrigin))
980             return;
981         
982         createToString<useKind>(node, node->child1());
983         arrayMode = ArrayMode(Array::String);
984     }
985     
986     template<UseKind useKind>
987     bool isStringObjectUse()
988     {
989         switch (useKind) {
990         case StringObjectUse:
991         case StringOrStringObjectUse:
992             return true;
993         default:
994             return false;
995         }
996     }
997     
998     template<UseKind useKind>
999     void convertStringAddUse(Node* node, Edge& edge)
1000     {
1001         if (useKind == StringUse) {
1002             // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
1003             // two edges will always have identical use kinds, which makes the
1004             // decision process much easier.
1005             observeUseKindOnNode<StringUse>(edge.node());
1006             m_insertionSet.insertNode(
1007                 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
1008                 Edge(edge.node(), StringUse));
1009             edge.setUseKind(KnownStringUse);
1010             return;
1011         }
1012         
1013         // FIXME: We ought to be able to have a ToPrimitiveToString node.
1014         
1015         observeUseKindOnNode<useKind>(edge.node());
1016         createToString<useKind>(node, edge);
1017     }
1018     
1019     void convertToMakeRope(Node* node)
1020     {
1021         node->setOpAndDefaultFlags(MakeRope);
1022         fixupMakeRope(node);
1023     }
1024     
1025     void fixupMakeRope(Node* node)
1026     {
1027         for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1028             Edge& edge = node->children.child(i);
1029             if (!edge)
1030                 break;
1031             edge.setUseKind(KnownStringUse);
1032             if (!m_graph.isConstant(edge.node()))
1033                 continue;
1034             JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
1035             if (string->length())
1036                 continue;
1037             
1038             // Don't allow the MakeRope to have zero children.
1039             if (!i && !node->child2())
1040                 break;
1041             
1042             node->children.removeEdge(i--);
1043         }
1044         
1045         if (!node->child2()) {
1046             ASSERT(!node->child3());
1047             node->convertToIdentity();
1048         }
1049     }
1050     
1051     void fixupToPrimitive(Node* node)
1052     {
1053         if (node->child1()->shouldSpeculateInt32()) {
1054             fixEdge<Int32Use>(node->child1());
1055             node->convertToIdentity();
1056             return;
1057         }
1058         
1059         if (node->child1()->shouldSpeculateString()) {
1060             fixEdge<StringUse>(node->child1());
1061             node->convertToIdentity();
1062             return;
1063         }
1064         
1065         if (node->child1()->shouldSpeculateStringObject()
1066             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1067             fixEdge<StringObjectUse>(node->child1());
1068             node->convertToToString();
1069             return;
1070         }
1071         
1072         if (node->child1()->shouldSpeculateStringOrStringObject()
1073             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1074             fixEdge<StringOrStringObjectUse>(node->child1());
1075             node->convertToToString();
1076             return;
1077         }
1078     }
1079     
1080     void fixupToString(Node* node)
1081     {
1082         if (node->child1()->shouldSpeculateString()) {
1083             fixEdge<StringUse>(node->child1());
1084             node->convertToIdentity();
1085             return;
1086         }
1087         
1088         if (node->child1()->shouldSpeculateStringObject()
1089             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1090             fixEdge<StringObjectUse>(node->child1());
1091             return;
1092         }
1093         
1094         if (node->child1()->shouldSpeculateStringOrStringObject()
1095             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1096             fixEdge<StringOrStringObjectUse>(node->child1());
1097             return;
1098         }
1099         
1100         if (node->child1()->shouldSpeculateCell()) {
1101             fixEdge<CellUse>(node->child1());
1102             return;
1103         }
1104     }
1105     
1106     template<UseKind leftUseKind>
1107     bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1108     {
1109         Node* originalLeft = left.node();
1110         Node* originalRight = right.node();
1111         
1112         ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1113         
1114         if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->codeOrigin))
1115             return false;
1116         
1117         convertStringAddUse<leftUseKind>(node, left);
1118         
1119         if (right->shouldSpeculateString())
1120             convertStringAddUse<StringUse>(node, right);
1121         else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
1122             convertStringAddUse<StringObjectUse>(node, right);
1123         else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
1124             convertStringAddUse<StringOrStringObjectUse>(node, right);
1125         else {
1126             // At this point we know that the other operand is something weird. The semantically correct
1127             // way of dealing with this is:
1128             //
1129             // MakeRope(@left, ToString(ToPrimitive(@right)))
1130             //
1131             // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1132             // anything to @right, since ToPrimitive may be effectful.
1133             
1134             Node* toPrimitive = m_insertionSet.insertNode(
1135                 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive, node->codeOrigin,
1136                 Edge(right.node()));
1137             Node* toString = m_insertionSet.insertNode(
1138                 m_indexInBlock, SpecString, ToString, node->codeOrigin, Edge(toPrimitive));
1139             
1140             fixupToPrimitive(toPrimitive);
1141             fixupToString(toString);
1142             
1143             right.setNode(toString);
1144         }
1145         
1146         // We're doing checks up there, so we need to make sure that the
1147         // *original* inputs to the addition are live up to here.
1148         m_insertionSet.insertNode(
1149             m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
1150             Edge(originalLeft), Edge(originalRight));
1151         
1152         convertToMakeRope(node);
1153         return true;
1154     }
1155     
1156     bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid)
1157     {
1158         unsigned attributesUnused;
1159         JSCell* specificValue;
1160         PropertyOffset offset = stringPrototypeStructure->getConcurrently(
1161             vm(), uid, attributesUnused, specificValue);
1162         if (!isValidOffset(offset))
1163             return false;
1164         
1165         if (!specificValue)
1166             return false;
1167         
1168         if (!specificValue->inherits(JSFunction::info()))
1169             return false;
1170         
1171         JSFunction* function = jsCast<JSFunction*>(specificValue);
1172         if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1173             return false;
1174         
1175         return true;
1176     }
1177     
1178     bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1179     {
1180         if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1181             return false;
1182         
1183         Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1184         ASSERT(stringObjectStructure->storedPrototype().isObject());
1185         ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == StringPrototype::info());
1186         
1187         JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1188         Structure* stringPrototypeStructure = stringPrototypeObject->structure();
1189         if (!m_graph.watchpoints().isStillValid(stringPrototypeStructure->transitionWatchpointSet()))
1190             return false;
1191         
1192         if (stringPrototypeStructure->isDictionary())
1193             return false;
1194         
1195         // We're being conservative here. We want DFG's ToString on StringObject to be
1196         // used in both numeric contexts (that would call valueOf()) and string contexts
1197         // (that would call toString()). We don't want the DFG to have to distinguish
1198         // between the two, just because that seems like it would get confusing. So we
1199         // just require both methods to be sane.
1200         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
1201             return false;
1202         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString.impl()))
1203             return false;
1204         
1205         return true;
1206     }
1207     
1208     void fixupSetLocalsInBlock(BasicBlock* block)
1209     {
1210         if (!block)
1211             return;
1212         ASSERT(block->isReachable);
1213         m_block = block;
1214         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1215             Node* node = m_currentNode = block->at(m_indexInBlock);
1216             if (node->op() != SetLocal)
1217                 continue;
1218             
1219             VariableAccessData* variable = node->variableAccessData();
1220             switch (variable->flushFormat()) {
1221             case FlushedJSValue:
1222                 break;
1223             case FlushedDouble:
1224                 fixEdge<NumberUse>(node->child1(), ForwardSpeculation);
1225                 break;
1226             case FlushedInt32:
1227                 fixEdge<Int32Use>(node->child1());
1228                 break;
1229             case FlushedInt52:
1230                 fixEdge<MachineIntUse>(node->child1());
1231                 break;
1232             case FlushedCell:
1233                 fixEdge<CellUse>(node->child1());
1234                 break;
1235             case FlushedBoolean:
1236                 fixEdge<BooleanUse>(node->child1());
1237                 break;
1238             default:
1239                 RELEASE_ASSERT_NOT_REACHED();
1240                 break;
1241             }
1242         }
1243         m_insertionSet.execute(block);
1244     }
1245     
1246     void fixupUntypedSetLocalsInBlock(BasicBlock* block)
1247     {
1248         if (!block)
1249             return;
1250         ASSERT(block->isReachable);
1251         m_block = block;
1252         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1253             Node* node = m_currentNode = block->at(m_indexInBlock);
1254             if (node->op() != SetLocal)
1255                 continue;
1256             
1257             if (node->child1().useKind() == UntypedUse)
1258                 fixEdge<UntypedUse>(node->child1());
1259         }
1260         m_insertionSet.execute(block);
1261     }
1262     
1263     Node* checkArray(ArrayMode arrayMode, const CodeOrigin& codeOrigin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
1264     {
1265         ASSERT(arrayMode.isSpecific());
1266         
1267         Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
1268         
1269         Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1270         
1271         if (arrayMode.doesConversion()) {
1272             if (structure) {
1273                 m_insertionSet.insertNode(
1274                     m_indexInBlock, SpecNone, ArrayifyToStructure, codeOrigin,
1275                     OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1276             } else {
1277                 m_insertionSet.insertNode(
1278                     m_indexInBlock, SpecNone, Arrayify, codeOrigin,
1279                     OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1280             }
1281         } else {
1282             if (structure) {
1283                 m_insertionSet.insertNode(
1284                     m_indexInBlock, SpecNone, CheckStructure, codeOrigin,
1285                     OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1286             } else {
1287                 m_insertionSet.insertNode(
1288                     m_indexInBlock, SpecNone, CheckArray, codeOrigin,
1289                     OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1290             }
1291         }
1292         
1293         if (!storageCheck(arrayMode))
1294             return 0;
1295         
1296         if (arrayMode.usesButterfly()) {
1297             return m_insertionSet.insertNode(
1298                 m_indexInBlock, SpecNone, GetButterfly, codeOrigin, Edge(array, CellUse));
1299         }
1300         
1301         return m_insertionSet.insertNode(
1302             m_indexInBlock, SpecNone, GetIndexedPropertyStorage, codeOrigin,
1303             OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
1304     }
1305     
1306     void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
1307     {
1308         Node* node = m_currentNode;
1309         
1310         switch (node->arrayMode().type()) {
1311         case Array::ForceExit: {
1312             m_insertionSet.insertNode(
1313                 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
1314             return;
1315         }
1316             
1317         case Array::SelectUsingPredictions:
1318         case Array::Unprofiled:
1319             RELEASE_ASSERT_NOT_REACHED();
1320             return;
1321             
1322         case Array::Generic:
1323             return;
1324             
1325         default: {
1326             Node* storage = checkArray(node->arrayMode(), node->codeOrigin, base.node(), index.node());
1327             if (!storage)
1328                 return;
1329             
1330             storageChild = Edge(storage);
1331             return;
1332         } }
1333     }
1334     
1335     bool alwaysUnboxSimplePrimitives()
1336     {
1337 #if USE(JSVALUE64)
1338         return false;
1339 #else
1340         // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1341         // reduces traffic.
1342         return true;
1343 #endif
1344     }
1345
1346     template<UseKind useKind>
1347     void observeUseKindOnNode(Node* node)
1348     {
1349         if (useKind == UntypedUse)
1350             return;
1351         observeUseKindOnNode(node, useKind);
1352     }
1353
1354     void observeUseKindOnEdge(Edge edge)
1355     {
1356         observeUseKindOnNode(edge.node(), edge.useKind());
1357     }
1358
1359     void observeUseKindOnNode(Node* node, UseKind useKind)
1360     {
1361         if (node->op() != GetLocal)
1362             return;
1363         
1364         // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
1365         // https://bugs.webkit.org/show_bug.cgi?id=121518
1366         
1367         VariableAccessData* variable = node->variableAccessData();
1368         switch (useKind) {
1369         case Int32Use:
1370             if (alwaysUnboxSimplePrimitives()
1371                 || isInt32Speculation(variable->prediction()))
1372                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1373             break;
1374         case NumberUse:
1375         case RealNumberUse:
1376             if (variable->doubleFormatState() == UsingDoubleFormat)
1377                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1378             break;
1379         case BooleanUse:
1380             if (alwaysUnboxSimplePrimitives()
1381                 || isBooleanSpeculation(variable->prediction()))
1382                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1383             break;
1384         case MachineIntUse:
1385             if (isMachineIntSpeculation(variable->prediction()))
1386                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1387             break;
1388         case CellUse:
1389         case KnownCellUse:
1390         case ObjectUse:
1391         case StringUse:
1392         case KnownStringUse:
1393         case StringObjectUse:
1394         case StringOrStringObjectUse:
1395             if (alwaysUnboxSimplePrimitives()
1396                 || isCellSpeculation(variable->prediction()))
1397                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1398             break;
1399         default:
1400             break;
1401         }
1402     }
1403     
1404     // Set the use kind of the edge and perform any actions that need to be done for
1405     // that use kind, like inserting intermediate conversion nodes. Never call this
1406     // with useKind = UntypedUse explicitly; edges have UntypedUse implicitly and any
1407     // edge that survives fixup and still has UntypedUse will have this method called
1408     // from observeUntypedEdge(). Also, make sure that if you do change the type of an
1409     // edge, you either call fixEdge() or perform the equivalent functionality
1410     // yourself. Obviously, you should have a really good reason if you do the latter.
1411     template<UseKind useKind>
1412     void fixEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
1413     {
1414         if (isDouble(useKind)) {
1415             if (edge->shouldSpeculateInt32ForArithmetic()) {
1416                 injectInt32ToDoubleNode(edge, useKind, direction);
1417                 return;
1418             }
1419             
1420             if (enableInt52() && edge->shouldSpeculateMachineInt()) {
1421                 // Make all double uses of int52 values have an intermediate Int52ToDouble.
1422                 // This is for the same reason as Int52ToValue (see below) except that
1423                 // Int8ToDouble will convert int52's that fit in an int32 into a double
1424                 // rather than trying to create a boxed int32 like Int52ToValue does.
1425                 
1426                 Node* result = m_insertionSet.insertNode(
1427                     m_indexInBlock, SpecInt52AsDouble, Int52ToDouble,
1428                     m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
1429                 edge = Edge(result, useKind);
1430                 return;
1431             }
1432         }
1433         
1434         if (enableInt52() && useKind != MachineIntUse
1435             && edge->shouldSpeculateMachineInt() && !edge->shouldSpeculateInt32()) {
1436             // We make all non-int52 uses of int52 values have an intermediate Int52ToValue
1437             // node to ensure that we handle this properly:
1438             //
1439             // a: SomeInt52
1440             // b: ArithAdd(@a, ...)
1441             // c: Call(..., @a)
1442             // d: ArithAdd(@a, ...)
1443             //
1444             // Without an intermediate node and just labeling the uses, we will get:
1445             //
1446             // a: SomeInt52
1447             // b: ArithAdd(Int52:@a, ...)
1448             // c: Call(..., Untyped:@a)
1449             // d: ArithAdd(Int52:@a, ...)
1450             //
1451             // And now the c->Untyped:@a edge will box the value of @a into a double. This
1452             // is bad, because now the d->Int52:@a edge will either have to do double-to-int
1453             // conversions, or will have to OSR exit unconditionally. Alternatively we could
1454             // have the c->Untyped:@a edge box the value by copying rather than in-place.
1455             // But these boxings are also costly so this wouldn't be great.
1456             //
1457             // The solution we use is to always have non-Int52 uses of predicted Int52's use
1458             // an intervening Int52ToValue node:
1459             //
1460             // a: SomeInt52
1461             // b: ArithAdd(Int52:@a, ...)
1462             // x: Int52ToValue(Int52:@a)
1463             // c: Call(..., Untyped:@x)
1464             // d: ArithAdd(Int52:@a, ...)
1465             //
1466             // Note that even if we had multiple non-int52 uses of @a, the multiple
1467             // Int52ToValue's would get CSE'd together. So the boxing would only happen once.
1468             // At the same time, @a would continue to be represented as a native int52.
1469             //
1470             // An alternative would have been to insert ToNativeInt52 nodes on int52 uses of
1471             // int52's. This would have handled the above example but would fall over for:
1472             //
1473             // a: SomeInt52
1474             // b: Call(..., @a)
1475             // c: ArithAdd(@a, ...)
1476             //
1477             // But the solution we use handles the above gracefully.
1478             
1479             Node* result = m_insertionSet.insertNode(
1480                 m_indexInBlock, SpecInt52, Int52ToValue,
1481                 m_currentNode->codeOrigin, Edge(edge.node(), UntypedUse));
1482             edge = Edge(result, useKind);
1483             return;
1484         }
1485         
1486         observeUseKindOnNode<useKind>(edge.node());
1487         
1488         edge.setUseKind(useKind);
1489     }
1490     
1491     void fixIntEdge(Edge& edge)
1492     {
1493         Node* node = edge.node();
1494         if (node->op() != ValueToInt32) {
1495             fixEdge<KnownInt32Use>(edge);
1496             return;
1497         }
1498         
1499         Edge newEdge = node->child1();
1500         
1501         if (newEdge.useKind() != Int32Use) {
1502             edge.setUseKind(KnownInt32Use);
1503             return;
1504         }
1505         
1506         ASSERT(newEdge->shouldSpeculateInt32());
1507         edge = newEdge;
1508     }
1509     
1510     void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
1511     {
1512         Node* result = m_insertionSet.insertNode(
1513             m_indexInBlock, SpecInt52AsDouble, Int32ToDouble,
1514             m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
1515         if (direction == ForwardSpeculation)
1516             result->mergeFlags(NodeExitsForward);
1517         
1518 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1519         dataLogF(
1520             "(replacing @%u->@%u with @%u->@%u) ",
1521             m_currentNode->index(), edge->index(), m_currentNode->index(), result->index());
1522 #endif
1523
1524         edge = Edge(result, useKind);
1525     }
1526     
1527     void truncateConstantToInt32(Edge& edge)
1528     {
1529         Node* oldNode = edge.node();
1530         
1531         ASSERT(oldNode->hasConstant());
1532         JSValue value = m_graph.valueOfJSConstant(oldNode);
1533         if (value.isInt32())
1534             return;
1535         
1536         value = jsNumber(JSC::toInt32(value.asNumber()));
1537         ASSERT(value.isInt32());
1538         unsigned constantRegister;
1539         if (!codeBlock()->findConstant(value, constantRegister)) {
1540             constantRegister = codeBlock()->addConstantLazily();
1541             initializeLazyWriteBarrierForConstant(
1542                 m_graph.m_plan.writeBarriers,
1543                 codeBlock()->constants()[constantRegister],
1544                 codeBlock(),
1545                 constantRegister,
1546                 codeBlock()->ownerExecutable(),
1547                 value);
1548         }
1549         edge.setNode(m_insertionSet.insertNode(
1550             m_indexInBlock, SpecInt32, JSConstant, m_currentNode->codeOrigin,
1551             OpInfo(constantRegister)));
1552     }
1553     
1554     void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1555     {
1556         if (mode != SpeculateInt32AndTruncateConstants)
1557             return;
1558         
1559         ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1560         if (node->child1()->hasConstant())
1561             truncateConstantToInt32(node->child1());
1562         else
1563             truncateConstantToInt32(node->child2());
1564     }
1565     
1566     bool attemptToMakeIntegerAdd(Node* node)
1567     {
1568         AddSpeculationMode mode = m_graph.addSpeculationMode(node);
1569         if (mode != DontSpeculateInt32) {
1570             truncateConstantsIfNecessary(node, mode);
1571             fixEdge<Int32Use>(node->child1());
1572             fixEdge<Int32Use>(node->child2());
1573             return true;
1574         }
1575         
1576         if (m_graph.addShouldSpeculateMachineInt(node)) {
1577             fixEdge<MachineIntUse>(node->child1());
1578             fixEdge<MachineIntUse>(node->child2());
1579             return true;
1580         }
1581         
1582         return false;
1583     }
1584     
1585     bool attemptToMakeGetArrayLength(Node* node)
1586     {
1587         if (!isInt32Speculation(node->prediction()))
1588             return false;
1589         CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->codeOrigin);
1590         ArrayProfile* arrayProfile = 
1591             profiledBlock->getArrayProfile(node->codeOrigin.bytecodeIndex);
1592         ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
1593         if (arrayProfile) {
1594             ConcurrentJITLocker locker(profiledBlock->m_lock);
1595             arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
1596             arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
1597             if (arrayMode.type() == Array::Unprofiled) {
1598                 // For normal array operations, it makes sense to treat Unprofiled
1599                 // accesses as ForceExit and get more data rather than using
1600                 // predictions and then possibly ending up with a Generic. But here,
1601                 // we treat anything that is Unprofiled as Generic and keep the
1602                 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
1603                 // profit - from treating the Unprofiled case as
1604                 // SelectUsingPredictions.
1605                 arrayMode = ArrayMode(Array::SelectUsingPredictions);
1606             }
1607         }
1608             
1609         arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
1610             
1611         if (arrayMode.type() == Array::Generic) {
1612             // Check if the input is something that we can't get array length for, but for which we
1613             // could insert some conversions in order to transform it into something that we can do it
1614             // for.
1615             if (node->child1()->shouldSpeculateStringObject())
1616                 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
1617             else if (node->child1()->shouldSpeculateStringOrStringObject())
1618                 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
1619         }
1620             
1621         if (!arrayMode.supportsLength())
1622             return false;
1623         
1624         convertToGetArrayLength(node, arrayMode);
1625         return true;
1626     }
1627     
1628     bool attemptToMakeGetTypedArrayByteLength(Node* node)
1629     {
1630         if (!isInt32Speculation(node->prediction()))
1631             return false;
1632         
1633         TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1634         if (!isTypedView(type))
1635             return false;
1636         
1637         if (elementSize(type) == 1) {
1638             convertToGetArrayLength(node, ArrayMode(toArrayType(type)));
1639             return true;
1640         }
1641         
1642         Node* length = prependGetArrayLength(
1643             node->codeOrigin, node->child1().node(), ArrayMode(toArrayType(type)));
1644         
1645         Node* shiftAmount = m_insertionSet.insertNode(
1646             m_indexInBlock, SpecInt32, JSConstant, node->codeOrigin,
1647             OpInfo(m_graph.constantRegisterForConstant(jsNumber(logElementSize(type)))));
1648         
1649         // We can use a BitLShift here because typed arrays will never have a byteLength
1650         // that overflows int32.
1651         node->setOp(BitLShift);
1652         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1653         observeUseKindOnNode(length, Int32Use);
1654         observeUseKindOnNode(shiftAmount, Int32Use);
1655         node->child1() = Edge(length, Int32Use);
1656         node->child2() = Edge(shiftAmount, Int32Use);
1657         return true;
1658     }
1659     
1660     void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
1661     {
1662         node->setOp(GetArrayLength);
1663         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1664         fixEdge<KnownCellUse>(node->child1());
1665         node->setArrayMode(arrayMode);
1666             
1667         Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage);
1668         if (!storage)
1669             return;
1670             
1671         node->child2() = Edge(storage);
1672     }
1673     
1674     Node* prependGetArrayLength(CodeOrigin codeOrigin, Node* child, ArrayMode arrayMode)
1675     {
1676         Node* storage = checkArray(arrayMode, codeOrigin, child, 0, lengthNeedsStorage);
1677         return m_insertionSet.insertNode(
1678             m_indexInBlock, SpecInt32, GetArrayLength, codeOrigin,
1679             OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
1680     }
1681     
1682     bool attemptToMakeGetTypedArrayByteOffset(Node* node)
1683     {
1684         if (!isInt32Speculation(node->prediction()))
1685             return false;
1686         
1687         TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1688         if (!isTypedView(type))
1689             return false;
1690         
1691         checkArray(
1692             ArrayMode(toArrayType(type)), node->codeOrigin, node->child1().node(),
1693             0, neverNeedsStorage);
1694         
1695         node->setOp(GetTypedArrayByteOffset);
1696         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1697         fixEdge<KnownCellUse>(node->child1());
1698         return true;
1699     }
1700
1701     BasicBlock* m_block;
1702     unsigned m_indexInBlock;
1703     Node* m_currentNode;
1704     InsertionSet m_insertionSet;
1705     bool m_profitabilityChanged;
1706 };
1707     
1708 bool performFixup(Graph& graph)
1709 {
1710     SamplingRegion samplingRegion("DFG Fixup Phase");
1711     return runPhase<FixupPhase>(graph);
1712 }
1713
1714 } } // namespace JSC::DFG
1715
1716 #endif // ENABLE(DFG_JIT)
1717