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