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