DFG implementation of op_strcat should inline rope allocations
[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 "DFGVariableAccessDataDump.h"
35 #include "Operations.h"
36
37 namespace JSC { namespace DFG {
38
39 class FixupPhase : public Phase {
40 public:
41     FixupPhase(Graph& graph)
42         : Phase(graph, "fixup")
43         , m_insertionSet(graph)
44     {
45     }
46     
47     bool run()
48     {
49         ASSERT(m_graph.m_fixpointState == BeforeFixpoint);
50         ASSERT(m_graph.m_form == ThreadedCPS);
51         
52         m_profitabilityChanged = false;
53         for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
54             fixupBlock(m_graph.m_blocks[blockIndex].get());
55         
56         while (m_profitabilityChanged) {
57             m_profitabilityChanged = false;
58             
59             for (unsigned i = m_graph.m_argumentPositions.size(); i--;)
60                 m_graph.m_argumentPositions[i].mergeArgumentUnboxingAwareness();
61             
62             for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
63                 fixupSetLocalsInBlock(m_graph.m_blocks[blockIndex].get());
64         }
65         
66         return true;
67     }
68
69 private:
70     void fixupBlock(BasicBlock* block)
71     {
72         if (!block)
73             return;
74         ASSERT(block->isReachable);
75         m_block = block;
76         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
77             m_currentNode = block->at(m_indexInBlock);
78             fixupNode(m_currentNode);
79         }
80         m_insertionSet.execute(block);
81     }
82     
83     void fixupNode(Node* node)
84     {
85         NodeType op = node->op();
86
87 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
88         dataLogF("   %s @%u: ", Graph::opName(op), node->index());
89 #endif
90         
91         switch (op) {
92         case SetLocal: {
93             // This gets handled by fixupSetLocalsInBlock().
94             break;
95         }
96             
97         case BitAnd:
98         case BitOr:
99         case BitXor:
100         case BitRShift:
101         case BitLShift:
102         case BitURShift: {
103             fixIntEdge(node->child1());
104             fixIntEdge(node->child2());
105             break;
106         }
107             
108         case UInt32ToNumber: {
109             setUseKindAndUnboxIfProfitable<KnownInt32Use>(node->child1());
110             break;
111         }
112             
113         case DoubleAsInt32: {
114             RELEASE_ASSERT_NOT_REACHED();
115             break;
116         }
117             
118         case ValueToInt32: {
119             if (node->child1()->shouldSpeculateInteger()) {
120                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
121                 break;
122             }
123             
124             if (node->child1()->shouldSpeculateNumber()) {
125                 setUseKindAndUnboxIfProfitable<NumberUse>(node->child1());
126                 break;
127             }
128             
129             if (node->child1()->shouldSpeculateBoolean()) {
130                 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
131                 break;
132             }
133             
134             setUseKindAndUnboxIfProfitable<NotCellUse>(node->child1());
135             break;
136         }
137             
138         case Int32ToDouble: {
139             RELEASE_ASSERT_NOT_REACHED();
140             break;
141         }
142             
143         case ValueAdd: {
144             if (attemptToMakeIntegerAdd(node))
145                 break;
146             if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {
147                 fixDoubleEdge<NumberUse>(node->child1());
148                 fixDoubleEdge<NumberUse>(node->child2());
149                 break;
150             }
151             
152             // FIXME: Optimize for the case where one of the operands is the
153             // empty string. Also consider optimizing for the case where we don't
154             // believe either side is the emtpy string. Both of these things should
155             // be easy.
156             
157             if (node->child1()->shouldSpeculateString()
158                 && attemptToMakeFastStringAdd<StringUse>(node, node->child1(), node->child2()))
159                 break;
160             if (node->child2()->shouldSpeculateString()
161                 && attemptToMakeFastStringAdd<StringUse>(node, node->child2(), node->child1()))
162                 break;
163             if (node->child1()->shouldSpeculateStringObject()
164                 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child1(), node->child2()))
165                 break;
166             if (node->child2()->shouldSpeculateStringObject()
167                 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child2(), node->child1()))
168                 break;
169             if (node->child1()->shouldSpeculateStringOrStringObject()
170                 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child1(), node->child2()))
171                 break;
172             if (node->child2()->shouldSpeculateStringOrStringObject()
173                 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child2(), node->child1()))
174                 break;
175             break;
176         }
177             
178         case MakeRope: {
179             fixupMakeRope(node);
180             break;
181         }
182             
183         case ArithAdd:
184         case ArithSub: {
185             if (attemptToMakeIntegerAdd(node))
186                 break;
187             fixDoubleEdge<NumberUse>(node->child1());
188             fixDoubleEdge<NumberUse>(node->child2());
189             break;
190         }
191             
192         case ArithNegate: {
193             if (m_graph.negateShouldSpeculateInteger(node)) {
194                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
195                 break;
196             }
197             fixDoubleEdge<NumberUse>(node->child1());
198             break;
199         }
200             
201         case ArithMul: {
202             if (m_graph.mulShouldSpeculateInteger(node)) {
203                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
204                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
205                 break;
206             }
207             fixDoubleEdge<NumberUse>(node->child1());
208             fixDoubleEdge<NumberUse>(node->child2());
209             break;
210         }
211
212         case ArithDiv: {
213             if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
214                 && node->canSpeculateInteger()) {
215                 if (isX86() || isARMv7s()) {
216                     setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
217                     setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
218                     break;
219                 }
220                 injectInt32ToDoubleNode(node->child1());
221                 injectInt32ToDoubleNode(node->child2());
222
223                 // We don't need to do ref'ing on the children because we're stealing them from
224                 // the original division.
225                 Node* newDivision = m_insertionSet.insertNode(
226                     m_indexInBlock, SpecDouble, *node);
227                 
228                 node->setOp(DoubleAsInt32);
229                 node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
230                 break;
231             }
232             fixDoubleEdge<NumberUse>(node->child1());
233             fixDoubleEdge<NumberUse>(node->child2());
234             break;
235         }
236             
237         case ArithMin:
238         case ArithMax:
239         case ArithMod: {
240             if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
241                 && node->canSpeculateInteger()) {
242                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
243                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
244                 break;
245             }
246             fixDoubleEdge<NumberUse>(node->child1());
247             fixDoubleEdge<NumberUse>(node->child2());
248             break;
249         }
250             
251         case ArithAbs: {
252             if (node->child1()->shouldSpeculateIntegerForArithmetic()
253                 && node->canSpeculateInteger()) {
254                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
255                 break;
256             }
257             fixDoubleEdge<NumberUse>(node->child1());
258             break;
259         }
260             
261         case ArithSqrt: {
262             fixDoubleEdge<NumberUse>(node->child1());
263             break;
264         }
265             
266         case LogicalNot: {
267             if (node->child1()->shouldSpeculateBoolean())
268                 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
269             else if (node->child1()->shouldSpeculateObjectOrOther())
270                 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
271             else if (node->child1()->shouldSpeculateInteger())
272                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
273             else if (node->child1()->shouldSpeculateNumber())
274                 fixDoubleEdge<NumberUse>(node->child1());
275             break;
276         }
277             
278         case TypeOf: {
279             if (node->child1()->shouldSpeculateString())
280                 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
281             else if (node->child1()->shouldSpeculateCell())
282                 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
283             break;
284         }
285             
286         case CompareEq:
287         case CompareEqConstant:
288         case CompareLess:
289         case CompareLessEq:
290         case CompareGreater:
291         case CompareGreaterEq: {
292             if (node->op() == CompareEqConstant)
293                 break;
294             if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) {
295                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
296                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
297                 break;
298             }
299             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
300                 fixDoubleEdge<NumberUse>(node->child1());
301                 fixDoubleEdge<NumberUse>(node->child2());
302                 break;
303             }
304             if (node->op() != CompareEq)
305                 break;
306             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString())
307                 break;
308             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
309                 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
310                 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
311                 break;
312             }
313             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
314                 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
315                 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child2());
316                 break;
317             }
318             if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
319                 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
320                 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
321                 break;
322             }
323             break;
324         }
325             
326         case CompareStrictEq:
327         case CompareStrictEqConstant: {
328             if (node->op() == CompareStrictEqConstant)
329                 break;
330             if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) {
331                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
332                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
333                 break;
334             }
335             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
336                 fixDoubleEdge<NumberUse>(node->child1());
337                 fixDoubleEdge<NumberUse>(node->child2());
338                 break;
339             }
340             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString())
341                 break;
342             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
343                 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
344                 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
345                 break;
346             }
347             break;
348         }
349
350         case StringCharAt:
351         case StringCharCodeAt: {
352             // Currently we have no good way of refining these.
353             ASSERT(node->arrayMode() == ArrayMode(Array::String));
354             blessArrayOperation(node->child1(), node->child2(), node->child3());
355             setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
356             setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
357             break;
358         }
359
360         case GetByVal: {
361             node->setArrayMode(
362                 node->arrayMode().refine(
363                     node->child1()->prediction(),
364                     node->child2()->prediction(),
365                     SpecNone, node->flags()));
366             
367             blessArrayOperation(node->child1(), node->child2(), node->child3());
368             
369             ArrayMode arrayMode = node->arrayMode();
370             if (arrayMode.type() == Array::Double
371                 && arrayMode.arrayClass() == Array::OriginalArray
372                 && arrayMode.speculation() == Array::InBounds
373                 && arrayMode.conversion() == Array::AsIs
374                 && m_graph.globalObjectFor(node->codeOrigin)->arrayPrototypeChainIsSane()
375                 && !(node->flags() & NodeUsedAsOther))
376                 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
377             
378             switch (node->arrayMode().type()) {
379             case Array::SelectUsingPredictions:
380             case Array::Unprofiled:
381             case Array::Undecided:
382                 RELEASE_ASSERT_NOT_REACHED();
383                 break;
384             case Array::Generic:
385 #if USE(JSVALUE32_64)
386                 setUseKindAndUnboxIfProfitable<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
387 #endif
388                 break;
389             case Array::ForceExit:
390                 break;
391             default:
392                 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
393                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
394                 break;
395             }
396             
397             break;
398         }
399             
400         case PutByVal:
401         case PutByValAlias: {
402             Edge& child1 = m_graph.varArgChild(node, 0);
403             Edge& child2 = m_graph.varArgChild(node, 1);
404             Edge& child3 = m_graph.varArgChild(node, 2);
405
406             node->setArrayMode(
407                 node->arrayMode().refine(
408                     child1->prediction(),
409                     child2->prediction(),
410                     child3->prediction()));
411             
412             blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
413             
414             switch (node->arrayMode().modeForPut().type()) {
415             case Array::SelectUsingPredictions:
416             case Array::Unprofiled:
417             case Array::Undecided:
418                 RELEASE_ASSERT_NOT_REACHED();
419                 break;
420             case Array::ForceExit:
421             case Array::Generic:
422 #if USE(JSVALUE32_64)
423                 // Due to register pressure on 32-bit, we speculate cell and
424                 // ignore the base-is-not-cell case entirely by letting the
425                 // baseline JIT handle it.
426                 setUseKindAndUnboxIfProfitable<CellUse>(child1);
427 #endif
428                 break;
429             case Array::Int32:
430                 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
431                 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
432                 setUseKindAndUnboxIfProfitable<Int32Use>(child3);
433                 break;
434             case Array::Double:
435                 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
436                 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
437                 fixDoubleEdge<RealNumberUse>(child3);
438                 break;
439             case Array::Int8Array:
440             case Array::Int16Array:
441             case Array::Int32Array:
442             case Array::Uint8Array:
443             case Array::Uint8ClampedArray:
444             case Array::Uint16Array:
445             case Array::Uint32Array:
446                 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
447                 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
448                 if (child3->shouldSpeculateInteger())
449                     setUseKindAndUnboxIfProfitable<Int32Use>(child3);
450                 else
451                     fixDoubleEdge<NumberUse>(child3);
452                 break;
453             case Array::Float32Array:
454             case Array::Float64Array:
455                 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
456                 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
457                 fixDoubleEdge<NumberUse>(child3);
458                 break;
459             default:
460                 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
461                 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
462                 break;
463             }
464             break;
465         }
466             
467         case ArrayPush: {
468             // May need to refine the array mode in case the value prediction contravenes
469             // the array prediction. For example, we may have evidence showing that the
470             // array is in Int32 mode, but the value we're storing is likely to be a double.
471             // Then we should turn this into a conversion to Double array followed by the
472             // push. On the other hand, we absolutely don't want to refine based on the
473             // base prediction. If it has non-cell garbage in it, then we want that to be
474             // ignored. That's because ArrayPush can't handle any array modes that aren't
475             // array-related - so if refine() turned this into a "Generic" ArrayPush then
476             // that would break things.
477             node->setArrayMode(
478                 node->arrayMode().refine(
479                     node->child1()->prediction() & SpecCell,
480                     SpecInt32,
481                     node->child2()->prediction()));
482             blessArrayOperation(node->child1(), Edge(), node->child3());
483             setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
484             
485             switch (node->arrayMode().type()) {
486             case Array::Int32:
487                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
488                 break;
489             case Array::Double:
490                 fixDoubleEdge<RealNumberUse>(node->child2());
491                 break;
492             default:
493                 break;
494             }
495             break;
496         }
497             
498         case ArrayPop: {
499             blessArrayOperation(node->child1(), Edge(), node->child2());
500             setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
501             break;
502         }
503             
504         case RegExpExec:
505         case RegExpTest: {
506             setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
507             setUseKindAndUnboxIfProfitable<CellUse>(node->child2());
508             break;
509         }
510             
511         case Branch: {
512             if (node->child1()->shouldSpeculateBoolean())
513                 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
514             else if (node->child1()->shouldSpeculateObjectOrOther())
515                 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
516             else if (node->child1()->shouldSpeculateInteger())
517                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
518             else if (node->child1()->shouldSpeculateNumber())
519                 fixDoubleEdge<NumberUse>(node->child1());
520
521             Node* logicalNot = node->child1().node();
522             if (logicalNot->op() == LogicalNot) {
523                 
524                 // Make sure that OSR exit can't observe the LogicalNot. If it can,
525                 // then we must compute it and cannot peephole around it.
526                 bool found = false;
527                 bool ok = true;
528                 for (unsigned i = m_indexInBlock; i--;) {
529                     Node* candidate = m_block->at(i);
530                     if (candidate == logicalNot) {
531                         found = true;
532                         break;
533                     }
534                     if (candidate->canExit()) {
535                         ok = false;
536                         found = true;
537                         break;
538                     }
539                 }
540                 ASSERT_UNUSED(found, found);
541                 
542                 if (ok) {
543                     Edge newChildEdge = logicalNot->child1();
544                     if (newChildEdge->hasBooleanResult()) {
545                         node->children.setChild1(newChildEdge);
546                         
547                         BlockIndex toBeTaken = node->notTakenBlockIndex();
548                         BlockIndex toBeNotTaken = node->takenBlockIndex();
549                         node->setTakenBlockIndex(toBeTaken);
550                         node->setNotTakenBlockIndex(toBeNotTaken);
551                     }
552                 }
553             }
554             break;
555         }
556             
557         case ToPrimitive: {
558             if (node->child1()->shouldSpeculateInteger()) {
559                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
560                 node->convertToIdentity();
561                 break;
562             }
563             
564             if (node->child1()->shouldSpeculateString()) {
565                 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
566                 node->convertToIdentity();
567                 break;
568             }
569             
570             if (node->child1()->shouldSpeculateStringObject()
571                 && canOptimizeStringObjectAccess(node->codeOrigin)) {
572                 setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
573                 node->convertToToString();
574                 break;
575             }
576             
577             if (node->child1()->shouldSpeculateStringOrStringObject()
578                 && canOptimizeStringObjectAccess(node->codeOrigin)) {
579                 setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
580                 node->convertToToString();
581                 break;
582             }
583             
584             // FIXME: Add string speculation here.
585             // https://bugs.webkit.org/show_bug.cgi?id=110175
586             break;
587         }
588             
589         case ToString: {
590             if (node->child1()->shouldSpeculateString()) {
591                 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
592                 node->convertToIdentity();
593                 break;
594             }
595             
596             if (node->child1()->shouldSpeculateStringObject()
597                 && canOptimizeStringObjectAccess(node->codeOrigin)) {
598                 setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
599                 break;
600             }
601             
602             if (node->child1()->shouldSpeculateStringOrStringObject()
603                 && canOptimizeStringObjectAccess(node->codeOrigin)) {
604                 setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
605                 break;
606             }
607             
608             if (node->child1()->shouldSpeculateCell()) {
609                 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
610                 break;
611             }
612             
613             break;
614         }
615             
616         case NewStringObject: {
617             setUseKindAndUnboxIfProfitable<KnownStringUse>(node->child1());
618             break;
619         }
620             
621         case NewArray: {
622             for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
623                 node->setIndexingType(
624                     leastUpperBoundOfIndexingTypeAndType(
625                         node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
626             }
627             switch (node->indexingType()) {
628             case ALL_BLANK_INDEXING_TYPES:
629                 CRASH();
630                 break;
631             case ALL_UNDECIDED_INDEXING_TYPES:
632                 if (node->numChildren()) {
633                     // This will only happen if the children have no type predictions. We
634                     // would have already exited by now, but insert a forced exit just to
635                     // be safe.
636                     m_insertionSet.insertNode(
637                         m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
638                 }
639                 break;
640             case ALL_INT32_INDEXING_TYPES:
641                 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
642                     setUseKindAndUnboxIfProfitable<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
643                 break;
644             case ALL_DOUBLE_INDEXING_TYPES:
645                 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
646                     setUseKindAndUnboxIfProfitable<RealNumberUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
647                 break;
648             case ALL_CONTIGUOUS_INDEXING_TYPES:
649             case ALL_ARRAY_STORAGE_INDEXING_TYPES:
650                 break;
651             default:
652                 CRASH();
653                 break;
654             }
655             break;
656         }
657             
658         case NewArrayWithSize: {
659             setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
660             break;
661         }
662             
663         case ConvertThis: {
664             if (isOtherSpeculation(node->child1()->prediction())) {
665                 m_insertionSet.insertNode(
666                     m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
667                     Edge(node->child1().node(), OtherUse));
668                 observeUseKindOnNode<OtherUse>(node->child1().node());
669                 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->codeOrigin));
670                 break;
671             }
672             
673             if (isObjectSpeculation(node->child1()->prediction())) {
674                 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
675                 node->convertToIdentity();
676                 break;
677             }
678             
679             break;
680         }
681             
682         case CreateThis: {
683             setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
684             break;
685         }
686             
687         case GetMyArgumentByVal:
688         case GetMyArgumentByValSafe: {
689             setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
690             break;
691         }
692             
693         case GetScopeRegisters:
694         case PutScopedVar:
695         case SkipTopScope:
696         case SkipScope:
697         case SetCallee:
698         case SetMyScope:
699         case PutStructure:
700         case AllocatePropertyStorage:
701         case ReallocatePropertyStorage:
702         case GetScope:
703         case GetButterfly: {
704             setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
705             break;
706         }
707             
708         case GetById: {
709             if (!node->child1()->shouldSpeculateCell())
710                 break;
711             setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
712             if (!isInt32Speculation(node->prediction()))
713                 break;
714             if (codeBlock()->identifier(node->identifierNumber()) != globalData().propertyNames->length)
715                 break;
716             ArrayProfile* arrayProfile = 
717                 m_graph.baselineCodeBlockFor(node->codeOrigin)->getArrayProfile(
718                     node->codeOrigin.bytecodeIndex);
719             ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
720             if (arrayProfile) {
721                 arrayProfile->computeUpdatedPrediction(m_graph.baselineCodeBlockFor(node->codeOrigin));
722                 arrayMode = ArrayMode::fromObserved(arrayProfile, Array::Read, false);
723                 arrayMode = arrayMode.refine(
724                     node->child1()->prediction(), node->prediction());
725                 if (arrayMode.supportsLength() && arrayProfile->hasDefiniteStructure()) {
726                     m_insertionSet.insertNode(
727                         m_indexInBlock, SpecNone, CheckStructure, node->codeOrigin,
728                         OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())),
729                         node->child1());
730                 }
731             } else
732                 arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
733             
734             if (arrayMode.type() == Array::Generic) {
735                 // Check if the input is something that we can't get array length for, but for which we
736                 // could insert some conversions in order to transform it into something that we can do it
737                 // for.
738                 if (node->child1()->shouldSpeculateStringObject())
739                     attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
740                 else if (node->child1()->shouldSpeculateStringOrStringObject())
741                     attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
742             }
743             
744             if (!arrayMode.supportsLength())
745                 break;
746             node->setOp(GetArrayLength);
747             ASSERT(node->flags() & NodeMustGenerate);
748             node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
749             setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
750             node->setArrayMode(arrayMode);
751             
752             Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage);
753             if (!storage)
754                 break;
755             
756             node->child2() = Edge(storage);
757             break;
758         }
759             
760         case GetByIdFlush: {
761             if (node->child1()->shouldSpeculateCell())
762                 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
763             break;
764         }
765             
766         case CheckExecutable:
767         case CheckStructure:
768         case ForwardCheckStructure:
769         case StructureTransitionWatchpoint:
770         case ForwardStructureTransitionWatchpoint:
771         case CheckFunction:
772         case PutById:
773         case PutByIdDirect:
774         case CheckHasInstance: {
775             setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
776             break;
777         }
778             
779         case CheckArray: {
780             switch (node->arrayMode().type()) {
781             case Array::String:
782                 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
783                 break;
784             default:
785                 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
786                 break;
787             }
788             break;
789         }
790             
791         case Arrayify:
792         case ArrayifyToStructure: {
793             setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
794             if (node->child2())
795                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
796             break;
797         }
798             
799         case GetByOffset: {
800             if (!node->child1()->hasStorageResult())
801                 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
802             break;
803         }
804             
805         case PutByOffset: {
806             if (!node->child1()->hasStorageResult())
807                 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
808             setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child2());
809             break;
810         }
811             
812         case InstanceOf: {
813             // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
814             // check. https://bugs.webkit.org/show_bug.cgi?id=107479
815             if (!(node->child1()->prediction() & ~SpecCell))
816                 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
817             setUseKindAndUnboxIfProfitable<CellUse>(node->child2());
818             break;
819         }
820             
821         case GetArrayLength:
822         case Identity:
823         case Nop:
824         case Phi:
825         case ForwardInt32ToDouble:
826         case PhantomPutStructure:
827         case GetIndexedPropertyStorage:
828         case LastNodeType:
829         case MovHint:
830         case MovHintAndCheck:
831         case ZombieHint:
832             RELEASE_ASSERT_NOT_REACHED();
833             break;
834         
835 #if !ASSERT_DISABLED    
836         // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
837         case SetArgument:
838         case Phantom:
839         case JSConstant:
840         case WeakJSConstant:
841         case GetLocal:
842         case GetCallee:
843         case Flush:
844         case PhantomLocal:
845         case GetLocalUnlinked:
846         case InlineStart:
847         case GetMyScope:
848         case GetScopedVar:
849         case GetGlobalVar:
850         case PutGlobalVar:
851         case GlobalVarWatchpoint:
852         case PutGlobalVarCheck:
853         case AllocationProfileWatchpoint:
854         case Call:
855         case Construct:
856         case NewObject:
857         case NewArrayBuffer:
858         case NewRegexp:
859         case Resolve:
860         case ResolveBase:
861         case ResolveBaseStrictPut:
862         case ResolveGlobal:
863         case Breakpoint:
864         case IsUndefined:
865         case IsBoolean:
866         case IsNumber:
867         case IsString:
868         case IsObject:
869         case IsFunction:
870         case CreateActivation:
871         case TearOffActivation:
872         case CreateArguments:
873         case PhantomArguments:
874         case TearOffArguments:
875         case GetMyArgumentsLength:
876         case GetMyArgumentsLengthSafe:
877         case CheckArgumentsNotCreated:
878         case NewFunction:
879         case NewFunctionNoCheck:
880         case NewFunctionExpression:
881         case Jump:
882         case Return:
883         case Throw:
884         case ThrowReferenceError:
885         case GarbageValue:
886         case CountExecution:
887         case ForceOSRExit:
888             break;
889 #else
890         default:
891             break;
892 #endif
893         }
894
895 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
896         if (!(node->flags() & NodeHasVarArgs)) {
897             dataLogF("new children: ");
898             node->dumpChildren(WTF::dataFile());
899         }
900         dataLogF("\n");
901 #endif
902     }
903     
904     template<UseKind useKind>
905     void createToString(Node* node, Edge& edge)
906     {
907         edge.setNode(m_insertionSet.insertNode(
908             m_indexInBlock, SpecString, ToString, node->codeOrigin,
909             Edge(edge.node(), useKind)));
910     }
911     
912     template<UseKind useKind>
913     void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
914     {
915         ASSERT(arrayMode == ArrayMode(Array::Generic));
916         
917         if (!canOptimizeStringObjectAccess(node->codeOrigin))
918             return;
919         
920         createToString<useKind>(node, node->child1());
921         arrayMode = ArrayMode(Array::String);
922     }
923     
924     template<UseKind useKind>
925     bool isStringObjectUse()
926     {
927         switch (useKind) {
928         case StringObjectUse:
929         case StringOrStringObjectUse:
930             return true;
931         default:
932             return false;
933         }
934     }
935     
936     template<UseKind useKind>
937     void convertStringAddUse(Node* node, Edge& edge)
938     {
939         if (useKind == StringUse) {
940             // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
941             // two edges will always have identical use kinds, which makes the
942             // decision process much easier.
943             observeUseKindOnNode<StringUse>(edge.node());
944             m_insertionSet.insertNode(
945                 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
946                 Edge(edge.node(), StringUse));
947             edge.setUseKind(KnownStringUse);
948             return;
949         }
950         
951         // FIXME: We ought to be able to have a ToPrimitiveToString node.
952         
953         observeUseKindOnNode<useKind>(edge.node());
954         createToString<useKind>(node, edge);
955     }
956     
957     void convertToMakeRope(Node* node)
958     {
959         node->setOpAndDefaultFlags(MakeRope);
960         fixupMakeRope(node);
961     }
962     
963     void fixupMakeRope(Node* node)
964     {
965         for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
966             Edge& edge = node->children.child(i);
967             if (!edge)
968                 break;
969             edge.setUseKind(KnownStringUse);
970             if (!m_graph.isConstant(edge.node()))
971                 continue;
972             JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
973             if (string->length())
974                 continue;
975             node->children.removeEdge(i--);
976         }
977         
978         if (!node->child2()) {
979             ASSERT(!node->child3());
980             node->convertToIdentity();
981         }
982     }
983     
984     template<UseKind leftUseKind>
985     bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
986     {
987         ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
988         
989         if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->codeOrigin))
990             return false;
991         
992         if (right->shouldSpeculateString()) {
993             convertStringAddUse<leftUseKind>(node, left);
994             convertStringAddUse<StringUse>(node, right);
995             convertToMakeRope(node);
996             return true;
997         }
998         
999         if (right->shouldSpeculateStringObject()
1000             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1001             convertStringAddUse<leftUseKind>(node, left);
1002             convertStringAddUse<StringObjectUse>(node, right);
1003             convertToMakeRope(node);
1004             return true;
1005         }
1006         
1007         if (right->shouldSpeculateStringOrStringObject()
1008             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1009             convertStringAddUse<leftUseKind>(node, left);
1010             convertStringAddUse<StringOrStringObjectUse>(node, right);
1011             convertToMakeRope(node);
1012             return true;
1013         }
1014         
1015         // FIXME: We ought to be able to convert the right case to do
1016         // ToPrimitiveToString.
1017         return false; // Let the slow path worry about it.
1018     }
1019     
1020     bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, const Identifier& ident)
1021     {
1022         unsigned attributesUnused;
1023         JSCell* specificValue;
1024         PropertyOffset offset = stringPrototypeStructure->get(
1025             globalData(), ident, attributesUnused, specificValue);
1026         if (!isValidOffset(offset))
1027             return false;
1028         
1029         if (!specificValue)
1030             return false;
1031         
1032         if (!specificValue->inherits(&JSFunction::s_info))
1033             return false;
1034         
1035         JSFunction* function = jsCast<JSFunction*>(specificValue);
1036         if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1037             return false;
1038         
1039         return true;
1040     }
1041     
1042     bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1043     {
1044         if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1045             return false;
1046         
1047         Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1048         ASSERT(stringObjectStructure->storedPrototype().isObject());
1049         ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == &StringPrototype::s_info);
1050         
1051         JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1052         Structure* stringPrototypeStructure = stringPrototypeObject->structure();
1053         if (stringPrototypeStructure->transitionWatchpointSetHasBeenInvalidated())
1054             return false;
1055         
1056         if (stringPrototypeStructure->isDictionary())
1057             return false;
1058         
1059         // We're being conservative here. We want DFG's ToString on StringObject to be
1060         // used in both numeric contexts (that would call valueOf()) and string contexts
1061         // (that would call toString()). We don't want the DFG to have to distinguish
1062         // between the two, just because that seems like it would get confusing. So we
1063         // just require both methods to be sane.
1064         if (!isStringPrototypeMethodSane(stringPrototypeStructure, globalData().propertyNames->valueOf))
1065             return false;
1066         if (!isStringPrototypeMethodSane(stringPrototypeStructure, globalData().propertyNames->toString))
1067             return false;
1068         
1069         return true;
1070     }
1071     
1072     void fixupSetLocalsInBlock(BasicBlock* block)
1073     {
1074         if (!block)
1075             return;
1076         ASSERT(block->isReachable);
1077         m_block = block;
1078         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1079             Node* node = m_currentNode = block->at(m_indexInBlock);
1080             if (node->op() != SetLocal)
1081                 continue;
1082             
1083             VariableAccessData* variable = node->variableAccessData();
1084             
1085             if (!variable->shouldUnboxIfPossible())
1086                 continue;
1087             
1088             if (variable->shouldUseDoubleFormat()) {
1089                 fixDoubleEdge<NumberUse>(node->child1(), ForwardSpeculation);
1090                 continue;
1091             }
1092             
1093             SpeculatedType predictedType = variable->argumentAwarePrediction();
1094             if (isInt32Speculation(predictedType))
1095                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1096             else if (isCellSpeculation(predictedType))
1097                 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
1098             else if (isBooleanSpeculation(predictedType))
1099                 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
1100         }
1101         m_insertionSet.execute(block);
1102     }
1103     
1104     void findAndRemoveUnnecessaryStructureCheck(Node* array, const CodeOrigin& codeOrigin)
1105     {
1106         for (unsigned index = m_indexInBlock; index--;) {
1107             Node* previousNode = m_block->at(index);
1108             if (previousNode->codeOrigin != codeOrigin)
1109                 return;
1110             
1111             if (previousNode->op() != CheckStructure)
1112                 continue;
1113             
1114             if (previousNode->child1() != array)
1115                 continue;
1116             
1117             previousNode->child1() = Edge();
1118             previousNode->convertToPhantom();
1119             return; // Assume we were smart enough to only insert one CheckStructure on the array.
1120         }
1121     }
1122     
1123     Node* checkArray(ArrayMode arrayMode, const CodeOrigin& codeOrigin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
1124     {
1125         ASSERT(arrayMode.isSpecific());
1126         
1127         Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
1128         
1129         Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1130         
1131         if (arrayMode.doesConversion()) {
1132             if (structure) {
1133                 if (m_indexInBlock > 0) {
1134                     // If the previous node was a CheckStructure inserted because of stuff
1135                     // that the array profile told us, then remove it, since we're going to be
1136                     // doing arrayification instead.
1137                     findAndRemoveUnnecessaryStructureCheck(array, codeOrigin);
1138                 }
1139                 
1140                 m_insertionSet.insertNode(
1141                     m_indexInBlock, SpecNone, ArrayifyToStructure, codeOrigin,
1142                     OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1143             } else {
1144                 m_insertionSet.insertNode(
1145                     m_indexInBlock, SpecNone, Arrayify, codeOrigin,
1146                     OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1147             }
1148         } else {
1149             if (structure) {
1150                 m_insertionSet.insertNode(
1151                     m_indexInBlock, SpecNone, CheckStructure, codeOrigin,
1152                     OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1153             } else {
1154                 m_insertionSet.insertNode(
1155                     m_indexInBlock, SpecNone, CheckArray, codeOrigin,
1156                     OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1157             }
1158         }
1159         
1160         if (!storageCheck(arrayMode))
1161             return 0;
1162         
1163         if (arrayMode.usesButterfly()) {
1164             return m_insertionSet.insertNode(
1165                 m_indexInBlock, SpecNone, GetButterfly, codeOrigin, Edge(array, KnownCellUse));
1166         }
1167         
1168         return m_insertionSet.insertNode(
1169             m_indexInBlock, SpecNone, GetIndexedPropertyStorage, codeOrigin,
1170             OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
1171     }
1172     
1173     void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
1174     {
1175         Node* node = m_currentNode;
1176         
1177         switch (node->arrayMode().type()) {
1178         case Array::ForceExit: {
1179             m_insertionSet.insertNode(
1180                 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
1181             return;
1182         }
1183             
1184         case Array::SelectUsingPredictions:
1185         case Array::Unprofiled:
1186             RELEASE_ASSERT_NOT_REACHED();
1187             return;
1188             
1189         case Array::Generic:
1190             findAndRemoveUnnecessaryStructureCheck(base.node(), node->codeOrigin);
1191             return;
1192             
1193         default: {
1194             Node* storage = checkArray(node->arrayMode(), node->codeOrigin, base.node(), index.node());
1195             if (!storage)
1196                 return;
1197             
1198             storageChild = Edge(storage);
1199             return;
1200         } }
1201     }
1202     
1203     bool alwaysUnboxSimplePrimitives()
1204     {
1205 #if USE(JSVALUE64)
1206         return false;
1207 #else
1208         // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1209         // reduces traffic.
1210         return true;
1211 #endif
1212     }
1213     
1214     template<UseKind useKind>
1215     void observeUseKindOnNode(Node* node)
1216     {
1217         if (node->op() != GetLocal)
1218             return;
1219         
1220         VariableAccessData* variable = node->variableAccessData();
1221         switch (useKind) {
1222         case Int32Use:
1223             if (alwaysUnboxSimplePrimitives()
1224                 || isInt32Speculation(variable->prediction()))
1225                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1226             break;
1227         case NumberUse:
1228         case RealNumberUse:
1229             if (variable->doubleFormatState() == UsingDoubleFormat)
1230                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1231             break;
1232         case BooleanUse:
1233             if (alwaysUnboxSimplePrimitives()
1234                 || isBooleanSpeculation(variable->prediction()))
1235                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1236             break;
1237         case CellUse:
1238         case ObjectUse:
1239         case StringUse:
1240         case KnownStringUse:
1241         case StringObjectUse:
1242         case StringOrStringObjectUse:
1243             if (alwaysUnboxSimplePrimitives()
1244                 || isCellSpeculation(variable->prediction()))
1245                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1246             break;
1247         default:
1248             break;
1249         }
1250     }
1251     
1252     // Set the use kind of the edge. In the future (https://bugs.webkit.org/show_bug.cgi?id=110433),
1253     // this can be used to notify the GetLocal that the variable is profitable to unbox.
1254     template<UseKind useKind>
1255     void setUseKindAndUnboxIfProfitable(Edge& edge)
1256     {
1257         observeUseKindOnNode<useKind>(edge.node());
1258         edge.setUseKind(useKind);
1259     }
1260     
1261     void fixIntEdge(Edge& edge)
1262     {
1263         Node* node = edge.node();
1264         if (node->op() != ValueToInt32) {
1265             setUseKindAndUnboxIfProfitable<KnownInt32Use>(edge);
1266             return;
1267         }
1268         
1269         Edge newEdge = node->child1();
1270         
1271         if (newEdge.useKind() != Int32Use) {
1272             edge.setUseKind(KnownInt32Use);
1273             return;
1274         }
1275         
1276         ASSERT(newEdge->shouldSpeculateInteger());
1277         edge = newEdge;
1278     }
1279     
1280     template<UseKind useKind>
1281     void fixDoubleEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
1282     {
1283         ASSERT(useKind == NumberUse || useKind == KnownNumberUse || useKind == RealNumberUse);
1284         
1285         if (edge->prediction() & SpecDouble) {
1286             setUseKindAndUnboxIfProfitable<useKind>(edge);
1287             return;
1288         }
1289         
1290         injectInt32ToDoubleNode(edge, useKind, direction);
1291     }
1292
1293     void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
1294     {
1295         Node* result = m_insertionSet.insertNode(
1296             m_indexInBlock, SpecDouble, 
1297             direction == BackwardSpeculation ? Int32ToDouble : ForwardInt32ToDouble,
1298             m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
1299         
1300 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1301         dataLogF(
1302             "(replacing @%u->@%u with @%u->@%u) ",
1303             m_currentNode->index(), edge->index(), m_currentNode->index(), result->index());
1304 #endif
1305
1306         edge = Edge(result, useKind);
1307     }
1308     
1309     void truncateConstantToInt32(Edge& edge)
1310     {
1311         Node* oldNode = edge.node();
1312         
1313         ASSERT(oldNode->hasConstant());
1314         JSValue value = m_graph.valueOfJSConstant(oldNode);
1315         if (value.isInt32())
1316             return;
1317         
1318         value = jsNumber(JSC::toInt32(value.asNumber()));
1319         ASSERT(value.isInt32());
1320         edge.setNode(m_insertionSet.insertNode(
1321             m_indexInBlock, SpecInt32, JSConstant, m_currentNode->codeOrigin,
1322             OpInfo(codeBlock()->addOrFindConstant(value))));
1323     }
1324     
1325     void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1326     {
1327         if (mode != SpeculateIntegerAndTruncateConstants)
1328             return;
1329         
1330         ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1331         if (node->child1()->hasConstant())
1332             truncateConstantToInt32(node->child1());
1333         else
1334             truncateConstantToInt32(node->child2());
1335     }
1336     
1337     bool attemptToMakeIntegerAdd(Node* node)
1338     {
1339         AddSpeculationMode mode = m_graph.addSpeculationMode(node);
1340         if (mode == DontSpeculateInteger)
1341             return false;
1342         
1343         truncateConstantsIfNecessary(node, mode);
1344         setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1345         setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
1346         return true;
1347     }
1348
1349     BasicBlock* m_block;
1350     unsigned m_indexInBlock;
1351     Node* m_currentNode;
1352     InsertionSet m_insertionSet;
1353     bool m_profitabilityChanged;
1354 };
1355     
1356 bool performFixup(Graph& graph)
1357 {
1358     SamplingRegion samplingRegion("DFG Fixup Phase");
1359     return runPhase<FixupPhase>(graph);
1360 }
1361
1362 } } // namespace JSC::DFG
1363
1364 #endif // ENABLE(DFG_JIT)
1365