Unreviewed, rolling out r149349 and r149354.
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGFixupPhase.cpp
1 /*
2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGFixupPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGGraph.h"
32 #include "DFGInsertionSet.h"
33 #include "DFGPhase.h"
34 #include "DFGPredictionPropagationPhase.h"
35 #include "DFGVariableAccessDataDump.h"
36 #include "Operations.h"
37
38 namespace JSC { namespace DFG {
39
40 class FixupPhase : public Phase {
41 public:
42     FixupPhase(Graph& graph)
43         : Phase(graph, "fixup")
44         , m_insertionSet(graph)
45     {
46     }
47     
48     bool run()
49     {
50         ASSERT(m_graph.m_fixpointState == BeforeFixpoint);
51         ASSERT(m_graph.m_form == ThreadedCPS);
52         
53         m_profitabilityChanged = false;
54         for (BlockIndex blockIndex = 0; blockIndex < m_graph.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             ArrayProfile* arrayProfile = 
692                 m_graph.baselineCodeBlockFor(node->codeOrigin)->getArrayProfile(
693                     node->codeOrigin.bytecodeIndex);
694             ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
695             if (arrayProfile) {
696                 arrayProfile->computeUpdatedPrediction(m_graph.baselineCodeBlockFor(node->codeOrigin));
697                 arrayMode = ArrayMode::fromObserved(arrayProfile, Array::Read, false);
698                 arrayMode = arrayMode.refine(
699                     node->child1()->prediction(), node->prediction());
700                 if (arrayMode.supportsLength() && arrayProfile->hasDefiniteStructure()) {
701                     m_insertionSet.insertNode(
702                         m_indexInBlock, SpecNone, CheckStructure, node->codeOrigin,
703                         OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())),
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             node->children.removeEdge(i--);
964         }
965         
966         if (!node->child2()) {
967             ASSERT(!node->child3());
968             node->convertToIdentity();
969         }
970     }
971     
972     void fixupToPrimitive(Node* node)
973     {
974         if (node->child1()->shouldSpeculateInteger()) {
975             setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
976             node->convertToIdentity();
977             return;
978         }
979         
980         if (node->child1()->shouldSpeculateString()) {
981             setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
982             node->convertToIdentity();
983             return;
984         }
985         
986         if (node->child1()->shouldSpeculateStringObject()
987             && canOptimizeStringObjectAccess(node->codeOrigin)) {
988             setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
989             node->convertToToString();
990             return;
991         }
992         
993         if (node->child1()->shouldSpeculateStringOrStringObject()
994             && canOptimizeStringObjectAccess(node->codeOrigin)) {
995             setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
996             node->convertToToString();
997             return;
998         }
999     }
1000     
1001     void fixupToString(Node* node)
1002     {
1003         if (node->child1()->shouldSpeculateString()) {
1004             setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
1005             node->convertToIdentity();
1006             return;
1007         }
1008         
1009         if (node->child1()->shouldSpeculateStringObject()
1010             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1011             setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
1012             return;
1013         }
1014         
1015         if (node->child1()->shouldSpeculateStringOrStringObject()
1016             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1017             setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
1018             return;
1019         }
1020         
1021         if (node->child1()->shouldSpeculateCell()) {
1022             setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
1023             return;
1024         }
1025     }
1026     
1027     template<UseKind leftUseKind>
1028     bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1029     {
1030         ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1031         
1032         if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->codeOrigin))
1033             return false;
1034         
1035         convertStringAddUse<leftUseKind>(node, left);
1036         
1037         if (right->shouldSpeculateString())
1038             convertStringAddUse<StringUse>(node, right);
1039         else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
1040             convertStringAddUse<StringObjectUse>(node, right);
1041         else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
1042             convertStringAddUse<StringOrStringObjectUse>(node, right);
1043         else {
1044             // At this point we know that the other operand is something weird. The semantically correct
1045             // way of dealing with this is:
1046             //
1047             // MakeRope(@left, ToString(ToPrimitive(@right)))
1048             //
1049             // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1050             // anything to @right, since ToPrimitive may be effectful.
1051             
1052             Node* toPrimitive = m_insertionSet.insertNode(
1053                 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive, node->codeOrigin,
1054                 Edge(right.node()));
1055             Node* toString = m_insertionSet.insertNode(
1056                 m_indexInBlock, SpecString, ToString, node->codeOrigin, Edge(toPrimitive));
1057             
1058             fixupToPrimitive(toPrimitive);
1059             fixupToString(toString);
1060             
1061             right.setNode(toString);
1062         }
1063         
1064         convertToMakeRope(node);
1065         return true;
1066     }
1067     
1068     bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, const Identifier& ident)
1069     {
1070         unsigned attributesUnused;
1071         JSCell* specificValue;
1072         PropertyOffset offset = stringPrototypeStructure->get(
1073             vm(), ident, attributesUnused, specificValue);
1074         if (!isValidOffset(offset))
1075             return false;
1076         
1077         if (!specificValue)
1078             return false;
1079         
1080         if (!specificValue->inherits(&JSFunction::s_info))
1081             return false;
1082         
1083         JSFunction* function = jsCast<JSFunction*>(specificValue);
1084         if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1085             return false;
1086         
1087         return true;
1088     }
1089     
1090     bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1091     {
1092         if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1093             return false;
1094         
1095         Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1096         ASSERT(stringObjectStructure->storedPrototype().isObject());
1097         ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == &StringPrototype::s_info);
1098         
1099         JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1100         Structure* stringPrototypeStructure = stringPrototypeObject->structure();
1101         if (stringPrototypeStructure->transitionWatchpointSetHasBeenInvalidated())
1102             return false;
1103         
1104         if (stringPrototypeStructure->isDictionary())
1105             return false;
1106         
1107         // We're being conservative here. We want DFG's ToString on StringObject to be
1108         // used in both numeric contexts (that would call valueOf()) and string contexts
1109         // (that would call toString()). We don't want the DFG to have to distinguish
1110         // between the two, just because that seems like it would get confusing. So we
1111         // just require both methods to be sane.
1112         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf))
1113             return false;
1114         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString))
1115             return false;
1116         
1117         return true;
1118     }
1119     
1120     void fixupSetLocalsInBlock(BasicBlock* block)
1121     {
1122         if (!block)
1123             return;
1124         ASSERT(block->isReachable);
1125         m_block = block;
1126         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1127             Node* node = m_currentNode = block->at(m_indexInBlock);
1128             if (node->op() != SetLocal)
1129                 continue;
1130             
1131             VariableAccessData* variable = node->variableAccessData();
1132             
1133             if (!variable->shouldUnboxIfPossible())
1134                 continue;
1135             
1136             if (variable->shouldUseDoubleFormat()) {
1137                 fixDoubleEdge<NumberUse>(node->child1(), ForwardSpeculation);
1138                 continue;
1139             }
1140             
1141             SpeculatedType predictedType = variable->argumentAwarePrediction();
1142             if (isInt32Speculation(predictedType))
1143                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1144             else if (isCellSpeculation(predictedType))
1145                 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
1146             else if (isBooleanSpeculation(predictedType))
1147                 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
1148         }
1149         m_insertionSet.execute(block);
1150     }
1151     
1152     void findAndRemoveUnnecessaryStructureCheck(Node* array, const CodeOrigin& codeOrigin)
1153     {
1154         for (unsigned index = m_indexInBlock; index--;) {
1155             Node* previousNode = m_block->at(index);
1156             if (previousNode->codeOrigin != codeOrigin)
1157                 return;
1158             
1159             if (previousNode->op() != CheckStructure)
1160                 continue;
1161             
1162             if (previousNode->child1() != array)
1163                 continue;
1164             
1165             previousNode->child1() = Edge();
1166             previousNode->convertToPhantom();
1167             return; // Assume we were smart enough to only insert one CheckStructure on the array.
1168         }
1169     }
1170     
1171     Node* checkArray(ArrayMode arrayMode, const CodeOrigin& codeOrigin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
1172     {
1173         ASSERT(arrayMode.isSpecific());
1174         
1175         Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
1176         
1177         Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1178         
1179         if (arrayMode.doesConversion()) {
1180             if (structure) {
1181                 if (m_indexInBlock > 0) {
1182                     // If the previous node was a CheckStructure inserted because of stuff
1183                     // that the array profile told us, then remove it, since we're going to be
1184                     // doing arrayification instead.
1185                     findAndRemoveUnnecessaryStructureCheck(array, codeOrigin);
1186                 }
1187                 
1188                 m_insertionSet.insertNode(
1189                     m_indexInBlock, SpecNone, ArrayifyToStructure, codeOrigin,
1190                     OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1191             } else {
1192                 m_insertionSet.insertNode(
1193                     m_indexInBlock, SpecNone, Arrayify, codeOrigin,
1194                     OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1195             }
1196         } else {
1197             if (structure) {
1198                 m_insertionSet.insertNode(
1199                     m_indexInBlock, SpecNone, CheckStructure, codeOrigin,
1200                     OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1201             } else {
1202                 m_insertionSet.insertNode(
1203                     m_indexInBlock, SpecNone, CheckArray, codeOrigin,
1204                     OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1205             }
1206         }
1207         
1208         if (!storageCheck(arrayMode))
1209             return 0;
1210         
1211         if (arrayMode.usesButterfly()) {
1212             return m_insertionSet.insertNode(
1213                 m_indexInBlock, SpecNone, GetButterfly, codeOrigin, Edge(array, KnownCellUse));
1214         }
1215         
1216         return m_insertionSet.insertNode(
1217             m_indexInBlock, SpecNone, GetIndexedPropertyStorage, codeOrigin,
1218             OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
1219     }
1220     
1221     void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
1222     {
1223         Node* node = m_currentNode;
1224         
1225         switch (node->arrayMode().type()) {
1226         case Array::ForceExit: {
1227             m_insertionSet.insertNode(
1228                 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
1229             return;
1230         }
1231             
1232         case Array::SelectUsingPredictions:
1233         case Array::Unprofiled:
1234             RELEASE_ASSERT_NOT_REACHED();
1235             return;
1236             
1237         case Array::Generic:
1238             findAndRemoveUnnecessaryStructureCheck(base.node(), node->codeOrigin);
1239             return;
1240             
1241         default: {
1242             Node* storage = checkArray(node->arrayMode(), node->codeOrigin, base.node(), index.node());
1243             if (!storage)
1244                 return;
1245             
1246             storageChild = Edge(storage);
1247             return;
1248         } }
1249     }
1250     
1251     bool alwaysUnboxSimplePrimitives()
1252     {
1253 #if USE(JSVALUE64)
1254         return false;
1255 #else
1256         // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1257         // reduces traffic.
1258         return true;
1259 #endif
1260     }
1261
1262     template<UseKind useKind>
1263     void observeUseKindOnNode(Node* node)
1264     {
1265         observeUseKindOnNode(node, useKind);
1266     }
1267
1268     void observeUseKindOnEdge(Edge edge)
1269     {
1270         observeUseKindOnNode(edge.node(), edge.useKind());
1271     }
1272
1273     void observeUseKindOnNode(Node* node, UseKind useKind)
1274     {
1275         if (node->op() != GetLocal)
1276             return;
1277         
1278         VariableAccessData* variable = node->variableAccessData();
1279         switch (useKind) {
1280         case Int32Use:
1281             if (alwaysUnboxSimplePrimitives()
1282                 || isInt32Speculation(variable->prediction()))
1283                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1284             break;
1285         case NumberUse:
1286         case RealNumberUse:
1287             if (variable->doubleFormatState() == UsingDoubleFormat)
1288                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1289             break;
1290         case BooleanUse:
1291             if (alwaysUnboxSimplePrimitives()
1292                 || isBooleanSpeculation(variable->prediction()))
1293                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1294             break;
1295         case CellUse:
1296         case ObjectUse:
1297         case StringUse:
1298         case KnownStringUse:
1299         case StringObjectUse:
1300         case StringOrStringObjectUse:
1301             if (alwaysUnboxSimplePrimitives()
1302                 || isCellSpeculation(variable->prediction()))
1303                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1304             break;
1305         default:
1306             break;
1307         }
1308     }
1309     
1310     // Set the use kind of the edge. In the future (https://bugs.webkit.org/show_bug.cgi?id=110433),
1311     // this can be used to notify the GetLocal that the variable is profitable to unbox.
1312     template<UseKind useKind>
1313     void setUseKindAndUnboxIfProfitable(Edge& edge)
1314     {
1315         observeUseKindOnNode<useKind>(edge.node());
1316         edge.setUseKind(useKind);
1317     }
1318     
1319     void fixIntEdge(Edge& edge)
1320     {
1321         Node* node = edge.node();
1322         if (node->op() != ValueToInt32) {
1323             setUseKindAndUnboxIfProfitable<KnownInt32Use>(edge);
1324             return;
1325         }
1326         
1327         Edge newEdge = node->child1();
1328         
1329         if (newEdge.useKind() != Int32Use) {
1330             edge.setUseKind(KnownInt32Use);
1331             return;
1332         }
1333         
1334         ASSERT(newEdge->shouldSpeculateInteger());
1335         edge = newEdge;
1336     }
1337     
1338     template<UseKind useKind>
1339     void fixDoubleEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
1340     {
1341         ASSERT(useKind == NumberUse || useKind == KnownNumberUse || useKind == RealNumberUse);
1342         
1343         if (edge->prediction() & SpecDouble) {
1344             setUseKindAndUnboxIfProfitable<useKind>(edge);
1345             return;
1346         }
1347         
1348         injectInt32ToDoubleNode(edge, useKind, direction);
1349     }
1350
1351     void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
1352     {
1353         Node* result = m_insertionSet.insertNode(
1354             m_indexInBlock, SpecDouble, 
1355             direction == BackwardSpeculation ? Int32ToDouble : ForwardInt32ToDouble,
1356             m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
1357         
1358 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1359         dataLogF(
1360             "(replacing @%u->@%u with @%u->@%u) ",
1361             m_currentNode->index(), edge->index(), m_currentNode->index(), result->index());
1362 #endif
1363
1364         edge = Edge(result, useKind);
1365     }
1366     
1367     void truncateConstantToInt32(Edge& edge)
1368     {
1369         Node* oldNode = edge.node();
1370         
1371         ASSERT(oldNode->hasConstant());
1372         JSValue value = m_graph.valueOfJSConstant(oldNode);
1373         if (value.isInt32())
1374             return;
1375         
1376         value = jsNumber(JSC::toInt32(value.asNumber()));
1377         ASSERT(value.isInt32());
1378         edge.setNode(m_insertionSet.insertNode(
1379             m_indexInBlock, SpecInt32, JSConstant, m_currentNode->codeOrigin,
1380             OpInfo(codeBlock()->addOrFindConstant(value))));
1381     }
1382     
1383     void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1384     {
1385         if (mode != SpeculateIntegerAndTruncateConstants)
1386             return;
1387         
1388         ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1389         if (node->child1()->hasConstant())
1390             truncateConstantToInt32(node->child1());
1391         else
1392             truncateConstantToInt32(node->child2());
1393     }
1394     
1395     bool attemptToMakeIntegerAdd(Node* node)
1396     {
1397         AddSpeculationMode mode = m_graph.addSpeculationMode(node);
1398         if (mode == DontSpeculateInteger)
1399             return false;
1400         
1401         truncateConstantsIfNecessary(node, mode);
1402         setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1403         setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
1404         return true;
1405     }
1406
1407     BasicBlock* m_block;
1408     unsigned m_indexInBlock;
1409     Node* m_currentNode;
1410     InsertionSet m_insertionSet;
1411     bool m_profitabilityChanged;
1412 };
1413     
1414 bool performFixup(Graph& graph)
1415 {
1416     SamplingRegion samplingRegion("DFG Fixup Phase");
1417     return runPhase<FixupPhase>(graph);
1418 }
1419
1420 } } // namespace JSC::DFG
1421
1422 #endif // ENABLE(DFG_JIT)
1423