Unreviewed, rolling out r156019 and r156020.
[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             fixEdge<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()->shouldSpeculateInt32()) {
122                 fixEdge<Int32Use>(node->child1());
123                 node->setOpAndDefaultFlags(Identity);
124                 break;
125             }
126             
127             if (node->child1()->shouldSpeculateNumber()) {
128                 fixEdge<NumberUse>(node->child1());
129                 break;
130             }
131             
132             if (node->child1()->shouldSpeculateBoolean()) {
133                 fixEdge<BooleanUse>(node->child1());
134                 break;
135             }
136             
137             fixEdge<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                 fixEdge<NumberUse>(node->child1());
151                 fixEdge<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             fixEdge<NumberUse>(node->child1());
191             fixEdge<NumberUse>(node->child2());
192             break;
193         }
194             
195         case ArithNegate: {
196             if (m_graph.negateShouldSpeculateInt32(node)) {
197                 fixEdge<Int32Use>(node->child1());
198                 break;
199             }
200             fixEdge<NumberUse>(node->child1());
201             break;
202         }
203             
204         case ArithMul: {
205             if (m_graph.mulShouldSpeculateInt32(node)) {
206                 fixEdge<Int32Use>(node->child1());
207                 fixEdge<Int32Use>(node->child2());
208                 break;
209             }
210             fixEdge<NumberUse>(node->child1());
211             fixEdge<NumberUse>(node->child2());
212             break;
213         }
214
215         case ArithDiv:
216         case ArithMod: {
217             if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
218                 && node->canSpeculateInt32()) {
219                 if (isX86() || isARMv7s()) {
220                     fixEdge<Int32Use>(node->child1());
221                     fixEdge<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             fixEdge<NumberUse>(node->child1());
237             fixEdge<NumberUse>(node->child2());
238             break;
239         }
240             
241         case ArithMin:
242         case ArithMax: {
243             if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
244                 && node->canSpeculateInt32()) {
245                 fixEdge<Int32Use>(node->child1());
246                 fixEdge<Int32Use>(node->child2());
247                 break;
248             }
249             fixEdge<NumberUse>(node->child1());
250             fixEdge<NumberUse>(node->child2());
251             break;
252         }
253             
254         case ArithAbs: {
255             if (node->child1()->shouldSpeculateInt32ForArithmetic()
256                 && node->canSpeculateInt32()) {
257                 fixEdge<Int32Use>(node->child1());
258                 break;
259             }
260             fixEdge<NumberUse>(node->child1());
261             break;
262         }
263             
264         case ArithSqrt: {
265             fixEdge<NumberUse>(node->child1());
266             break;
267         }
268             
269         case LogicalNot: {
270             if (node->child1()->shouldSpeculateBoolean())
271                 fixEdge<BooleanUse>(node->child1());
272             else if (node->child1()->shouldSpeculateObjectOrOther())
273                 fixEdge<ObjectOrOtherUse>(node->child1());
274             else if (node->child1()->shouldSpeculateInt32())
275                 fixEdge<Int32Use>(node->child1());
276             else if (node->child1()->shouldSpeculateNumber())
277                 fixEdge<NumberUse>(node->child1());
278             break;
279         }
280             
281         case TypeOf: {
282             if (node->child1()->shouldSpeculateString())
283                 fixEdge<StringUse>(node->child1());
284             else if (node->child1()->shouldSpeculateCell())
285                 fixEdge<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::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
299                 fixEdge<Int32Use>(node->child1());
300                 fixEdge<Int32Use>(node->child2());
301                 break;
302             }
303             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
304                 fixEdge<NumberUse>(node->child1());
305                 fixEdge<NumberUse>(node->child2());
306                 break;
307             }
308             if (node->op() != CompareEq)
309                 break;
310             if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
311                 fixEdge<BooleanUse>(node->child1());
312                 fixEdge<BooleanUse>(node->child2());
313                 break;
314             }
315             if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
316                 fixEdge<StringIdentUse>(node->child1());
317                 fixEdge<StringIdentUse>(node->child2());
318                 break;
319             }
320             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
321                 fixEdge<StringUse>(node->child1());
322                 fixEdge<StringUse>(node->child2());
323                 break;
324             }
325             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
326                 fixEdge<ObjectUse>(node->child1());
327                 fixEdge<ObjectUse>(node->child2());
328                 break;
329             }
330             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
331                 fixEdge<ObjectUse>(node->child1());
332                 fixEdge<ObjectOrOtherUse>(node->child2());
333                 break;
334             }
335             if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
336                 fixEdge<ObjectOrOtherUse>(node->child1());
337                 fixEdge<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                 fixEdge<BooleanUse>(node->child1());
350                 fixEdge<BooleanUse>(node->child2());
351                 break;
352             }
353             if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
354                 fixEdge<Int32Use>(node->child1());
355                 fixEdge<Int32Use>(node->child2());
356                 break;
357             }
358             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
359                 fixEdge<NumberUse>(node->child1());
360                 fixEdge<NumberUse>(node->child2());
361                 break;
362             }
363             if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
364                 fixEdge<StringIdentUse>(node->child1());
365                 fixEdge<StringIdentUse>(node->child2());
366                 break;
367             }
368             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
369                 fixEdge<StringUse>(node->child1());
370                 fixEdge<StringUse>(node->child2());
371                 break;
372             }
373             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
374                 fixEdge<ObjectUse>(node->child1());
375                 fixEdge<ObjectUse>(node->child2());
376                 break;
377             }
378             break;
379         }
380
381         case StringFromCharCode:
382             fixEdge<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             fixEdge<KnownCellUse>(node->child1());
391             fixEdge<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() & NodeBytecodeUsesAsOther))
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                 fixEdge<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                 fixEdge<KnownCellUse>(node->child1());
439                 fixEdge<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                 fixEdge<CellUse>(child1);
473 #endif
474                 break;
475             case Array::Int32:
476                 fixEdge<KnownCellUse>(child1);
477                 fixEdge<Int32Use>(child2);
478                 fixEdge<Int32Use>(child3);
479                 break;
480             case Array::Double:
481                 fixEdge<KnownCellUse>(child1);
482                 fixEdge<Int32Use>(child2);
483                 fixEdge<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                 fixEdge<KnownCellUse>(child1);
493                 fixEdge<Int32Use>(child2);
494                 if (child3->shouldSpeculateInt32())
495                     fixEdge<Int32Use>(child3);
496                 else
497                     fixEdge<NumberUse>(child3);
498                 break;
499             case Array::Float32Array:
500             case Array::Float64Array:
501                 fixEdge<KnownCellUse>(child1);
502                 fixEdge<Int32Use>(child2);
503                 fixEdge<NumberUse>(child3);
504                 break;
505             default:
506                 fixEdge<KnownCellUse>(child1);
507                 fixEdge<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             fixEdge<KnownCellUse>(node->child1());
530             
531             switch (node->arrayMode().type()) {
532             case Array::Int32:
533                 fixEdge<Int32Use>(node->child2());
534                 break;
535             case Array::Double:
536                 fixEdge<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             fixEdge<KnownCellUse>(node->child1());
547             break;
548         }
549             
550         case RegExpExec:
551         case RegExpTest: {
552             fixEdge<CellUse>(node->child1());
553             fixEdge<CellUse>(node->child2());
554             break;
555         }
556             
557         case Branch: {
558             if (node->child1()->shouldSpeculateBoolean())
559                 fixEdge<BooleanUse>(node->child1());
560             else if (node->child1()->shouldSpeculateObjectOrOther())
561                 fixEdge<ObjectOrOtherUse>(node->child1());
562             else if (node->child1()->shouldSpeculateInt32())
563                 fixEdge<Int32Use>(node->child1());
564             else if (node->child1()->shouldSpeculateNumber())
565                 fixEdge<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()->shouldSpeculateInt32())
608                     fixEdge<Int32Use>(node->child1());
609                 break;
610             case SwitchChar:
611                 if (node->child1()->shouldSpeculateString())
612                     fixEdge<StringUse>(node->child1());
613                 break;
614             case SwitchString:
615                 if (node->child1()->shouldSpeculateStringIdent())
616                     fixEdge<StringIdentUse>(node->child1());
617                 else if (node->child1()->shouldSpeculateString())
618                     fixEdge<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             fixEdge<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                     fixEdge<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                     fixEdge<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 NewTypedArray: {
677             if (node->child1()->shouldSpeculateInt32()) {
678                 fixEdge<Int32Use>(node->child1());
679                 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
680                 break;
681             }
682             break;
683         }
684             
685         case NewArrayWithSize: {
686             fixEdge<Int32Use>(node->child1());
687             break;
688         }
689             
690         case ToThis: {
691             ECMAMode ecmaMode = m_graph.executableFor(node->codeOrigin)->isStrictMode() ? StrictMode : NotStrictMode;
692
693             if (isOtherSpeculation(node->child1()->prediction())) {
694                 if (ecmaMode == StrictMode) {
695                     fixEdge<OtherUse>(node->child1());
696                     node->convertToIdentity();
697                     break;
698                 }
699
700                 m_insertionSet.insertNode(
701                     m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
702                     Edge(node->child1().node(), OtherUse));
703                 observeUseKindOnNode<OtherUse>(node->child1().node());
704                 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->codeOrigin));
705                 break;
706             }
707             
708             if (isFinalObjectSpeculation(node->child1()->prediction())) {
709                 fixEdge<FinalObjectUse>(node->child1());
710                 node->convertToIdentity();
711                 break;
712             }
713             
714             break;
715         }
716             
717         case GetMyArgumentByVal:
718         case GetMyArgumentByValSafe: {
719             fixEdge<Int32Use>(node->child1());
720             break;
721         }
722             
723         case GetClosureRegisters:
724         case PutClosureVar:
725         case SkipTopScope:
726         case SkipScope:
727         case SetCallee:
728         case SetMyScope:
729         case PutStructure:
730         case AllocatePropertyStorage:
731         case ReallocatePropertyStorage:
732         case GetScope: {
733             fixEdge<KnownCellUse>(node->child1());
734             break;
735         }
736             
737         case GetById:
738         case GetByIdFlush: {
739             if (!node->child1()->shouldSpeculateCell())
740                 break;
741             StringImpl* impl = m_graph.identifiers()[node->identifierNumber()];
742             if (impl == vm().propertyNames->length.impl()) {
743                 attemptToMakeGetArrayLength(node);
744                 break;
745             }
746             if (impl == vm().propertyNames->byteLength.impl()) {
747                 attemptToMakeGetTypedArrayByteLength(node);
748                 break;
749             }
750             if (impl == vm().propertyNames->byteOffset.impl()) {
751                 attemptToMakeGetTypedArrayByteOffset(node);
752                 break;
753             }
754             fixEdge<CellUse>(node->child1());
755             break;
756         }
757             
758         case CheckExecutable:
759         case CheckStructure:
760         case StructureTransitionWatchpoint:
761         case CheckFunction:
762         case PutById:
763         case PutByIdDirect:
764         case CheckHasInstance:
765         case CreateThis:
766         case GetButterfly: {
767             fixEdge<CellUse>(node->child1());
768             break;
769         }
770             
771         case CheckArray: {
772             switch (node->arrayMode().type()) {
773             case Array::String:
774                 fixEdge<StringUse>(node->child1());
775                 break;
776             default:
777                 fixEdge<CellUse>(node->child1());
778                 break;
779             }
780             break;
781         }
782             
783         case Arrayify:
784         case ArrayifyToStructure: {
785             fixEdge<CellUse>(node->child1());
786             if (node->child2())
787                 fixEdge<Int32Use>(node->child2());
788             break;
789         }
790             
791         case GetByOffset: {
792             if (!node->child1()->hasStorageResult())
793                 fixEdge<KnownCellUse>(node->child1());
794             fixEdge<KnownCellUse>(node->child2());
795             break;
796         }
797             
798         case PutByOffset: {
799             if (!node->child1()->hasStorageResult())
800                 fixEdge<KnownCellUse>(node->child1());
801             fixEdge<KnownCellUse>(node->child2());
802             break;
803         }
804             
805         case InstanceOf: {
806             // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
807             // check. https://bugs.webkit.org/show_bug.cgi?id=107479
808             if (!(node->child1()->prediction() & ~SpecCell))
809                 fixEdge<CellUse>(node->child1());
810             fixEdge<CellUse>(node->child2());
811             break;
812         }
813             
814         case In: {
815             // FIXME: We should at some point have array profiling on op_in, in which
816             // case we would be able to turn this into a kind of GetByVal.
817             
818             fixEdge<CellUse>(node->child2());
819             break;
820         }
821
822         case Phantom:
823         case Identity: {
824             switch (node->child1().useKind()) {
825             case NumberUse:
826                 if (node->child1()->shouldSpeculateInt32ForArithmetic())
827                     node->child1().setUseKind(Int32Use);
828                 break;
829             default:
830                 break;
831             }
832             observeUseKindOnEdge(node->child1());
833             break;
834         }
835
836         case GetArrayLength:
837         case Phi:
838         case Upsilon:
839         case GetArgument:
840         case PhantomPutStructure:
841         case GetIndexedPropertyStorage:
842         case GetTypedArrayByteOffset:
843         case LastNodeType:
844         case MovHint:
845         case MovHintAndCheck:
846         case ZombieHint:
847         case CheckTierUpInLoop:
848         case CheckTierUpAtReturn:
849         case CheckTierUpAndOSREnter:
850             RELEASE_ASSERT_NOT_REACHED();
851             break;
852         
853 #if !ASSERT_DISABLED    
854         // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
855         case SetArgument:
856         case JSConstant:
857         case WeakJSConstant:
858         case GetLocal:
859         case GetCallee:
860         case Flush:
861         case PhantomLocal:
862         case GetLocalUnlinked:
863         case InlineStart:
864         case GetMyScope:
865         case GetClosureVar:
866         case GetGlobalVar:
867         case PutGlobalVar:
868         case GlobalVarWatchpoint:
869         case VarInjectionWatchpoint:
870         case AllocationProfileWatchpoint:
871         case Call:
872         case Construct:
873         case NewObject:
874         case NewArrayBuffer:
875         case NewRegexp:
876         case Breakpoint:
877         case IsUndefined:
878         case IsBoolean:
879         case IsNumber:
880         case IsString:
881         case IsObject:
882         case IsFunction:
883         case CreateActivation:
884         case TearOffActivation:
885         case CreateArguments:
886         case PhantomArguments:
887         case TearOffArguments:
888         case GetMyArgumentsLength:
889         case GetMyArgumentsLengthSafe:
890         case CheckArgumentsNotCreated:
891         case NewFunction:
892         case NewFunctionNoCheck:
893         case NewFunctionExpression:
894         case Jump:
895         case Return:
896         case Throw:
897         case ThrowReferenceError:
898         case CountExecution:
899         case ForceOSRExit:
900         case CheckWatchdogTimer:
901         case Unreachable:
902         case ExtractOSREntryLocal:
903         case LoopHint:
904             break;
905 #else
906         default:
907             break;
908 #endif
909         }
910         
911         DFG_NODE_DO_TO_CHILDREN(m_graph, node, observeUntypedEdge);
912
913 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
914         if (!(node->flags() & NodeHasVarArgs)) {
915             dataLogF("new children: ");
916             node->dumpChildren(WTF::dataFile());
917         }
918         dataLogF("\n");
919 #endif
920     }
921     
922     void observeUntypedEdge(Node*, Edge& edge)
923     {
924         if (edge.useKind() != UntypedUse)
925             return;
926         fixEdge<UntypedUse>(edge);
927     }
928     
929     template<UseKind useKind>
930     void createToString(Node* node, Edge& edge)
931     {
932         edge.setNode(m_insertionSet.insertNode(
933             m_indexInBlock, SpecString, ToString, node->codeOrigin,
934             Edge(edge.node(), useKind)));
935     }
936     
937     template<UseKind useKind>
938     void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
939     {
940         ASSERT(arrayMode == ArrayMode(Array::Generic));
941         
942         if (!canOptimizeStringObjectAccess(node->codeOrigin))
943             return;
944         
945         createToString<useKind>(node, node->child1());
946         arrayMode = ArrayMode(Array::String);
947     }
948     
949     template<UseKind useKind>
950     bool isStringObjectUse()
951     {
952         switch (useKind) {
953         case StringObjectUse:
954         case StringOrStringObjectUse:
955             return true;
956         default:
957             return false;
958         }
959     }
960     
961     template<UseKind useKind>
962     void convertStringAddUse(Node* node, Edge& edge)
963     {
964         if (useKind == StringUse) {
965             // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
966             // two edges will always have identical use kinds, which makes the
967             // decision process much easier.
968             observeUseKindOnNode<StringUse>(edge.node());
969             m_insertionSet.insertNode(
970                 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
971                 Edge(edge.node(), StringUse));
972             edge.setUseKind(KnownStringUse);
973             return;
974         }
975         
976         // FIXME: We ought to be able to have a ToPrimitiveToString node.
977         
978         observeUseKindOnNode<useKind>(edge.node());
979         createToString<useKind>(node, edge);
980     }
981     
982     void convertToMakeRope(Node* node)
983     {
984         node->setOpAndDefaultFlags(MakeRope);
985         fixupMakeRope(node);
986     }
987     
988     void fixupMakeRope(Node* node)
989     {
990         for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
991             Edge& edge = node->children.child(i);
992             if (!edge)
993                 break;
994             edge.setUseKind(KnownStringUse);
995             if (!m_graph.isConstant(edge.node()))
996                 continue;
997             JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
998             if (string->length())
999                 continue;
1000             
1001             // Don't allow the MakeRope to have zero children.
1002             if (!i && !node->child2())
1003                 break;
1004             
1005             node->children.removeEdge(i--);
1006         }
1007         
1008         if (!node->child2()) {
1009             ASSERT(!node->child3());
1010             node->convertToIdentity();
1011         }
1012     }
1013     
1014     void fixupToPrimitive(Node* node)
1015     {
1016         if (node->child1()->shouldSpeculateInt32()) {
1017             fixEdge<Int32Use>(node->child1());
1018             node->convertToIdentity();
1019             return;
1020         }
1021         
1022         if (node->child1()->shouldSpeculateString()) {
1023             fixEdge<StringUse>(node->child1());
1024             node->convertToIdentity();
1025             return;
1026         }
1027         
1028         if (node->child1()->shouldSpeculateStringObject()
1029             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1030             fixEdge<StringObjectUse>(node->child1());
1031             node->convertToToString();
1032             return;
1033         }
1034         
1035         if (node->child1()->shouldSpeculateStringOrStringObject()
1036             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1037             fixEdge<StringOrStringObjectUse>(node->child1());
1038             node->convertToToString();
1039             return;
1040         }
1041     }
1042     
1043     void fixupToString(Node* node)
1044     {
1045         if (node->child1()->shouldSpeculateString()) {
1046             fixEdge<StringUse>(node->child1());
1047             node->convertToIdentity();
1048             return;
1049         }
1050         
1051         if (node->child1()->shouldSpeculateStringObject()
1052             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1053             fixEdge<StringObjectUse>(node->child1());
1054             return;
1055         }
1056         
1057         if (node->child1()->shouldSpeculateStringOrStringObject()
1058             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1059             fixEdge<StringOrStringObjectUse>(node->child1());
1060             return;
1061         }
1062         
1063         if (node->child1()->shouldSpeculateCell()) {
1064             fixEdge<CellUse>(node->child1());
1065             return;
1066         }
1067     }
1068     
1069     template<UseKind leftUseKind>
1070     bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1071     {
1072         Node* originalLeft = left.node();
1073         Node* originalRight = right.node();
1074         
1075         ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1076         
1077         if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->codeOrigin))
1078             return false;
1079         
1080         convertStringAddUse<leftUseKind>(node, left);
1081         
1082         if (right->shouldSpeculateString())
1083             convertStringAddUse<StringUse>(node, right);
1084         else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
1085             convertStringAddUse<StringObjectUse>(node, right);
1086         else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
1087             convertStringAddUse<StringOrStringObjectUse>(node, right);
1088         else {
1089             // At this point we know that the other operand is something weird. The semantically correct
1090             // way of dealing with this is:
1091             //
1092             // MakeRope(@left, ToString(ToPrimitive(@right)))
1093             //
1094             // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1095             // anything to @right, since ToPrimitive may be effectful.
1096             
1097             Node* toPrimitive = m_insertionSet.insertNode(
1098                 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive, node->codeOrigin,
1099                 Edge(right.node()));
1100             Node* toString = m_insertionSet.insertNode(
1101                 m_indexInBlock, SpecString, ToString, node->codeOrigin, Edge(toPrimitive));
1102             
1103             fixupToPrimitive(toPrimitive);
1104             fixupToString(toString);
1105             
1106             right.setNode(toString);
1107         }
1108         
1109         // We're doing checks up there, so we need to make sure that the
1110         // *original* inputs to the addition are live up to here.
1111         m_insertionSet.insertNode(
1112             m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
1113             Edge(originalLeft), Edge(originalRight));
1114         
1115         convertToMakeRope(node);
1116         return true;
1117     }
1118     
1119     bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid)
1120     {
1121         unsigned attributesUnused;
1122         JSCell* specificValue;
1123         PropertyOffset offset = stringPrototypeStructure->getConcurrently(
1124             vm(), uid, attributesUnused, specificValue);
1125         if (!isValidOffset(offset))
1126             return false;
1127         
1128         if (!specificValue)
1129             return false;
1130         
1131         if (!specificValue->inherits(JSFunction::info()))
1132             return false;
1133         
1134         JSFunction* function = jsCast<JSFunction*>(specificValue);
1135         if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1136             return false;
1137         
1138         return true;
1139     }
1140     
1141     bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1142     {
1143         if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1144             return false;
1145         
1146         Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1147         ASSERT(stringObjectStructure->storedPrototype().isObject());
1148         ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == StringPrototype::info());
1149         
1150         JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1151         Structure* stringPrototypeStructure = stringPrototypeObject->structure();
1152         if (!m_graph.watchpoints().isStillValid(stringPrototypeStructure->transitionWatchpointSet()))
1153             return false;
1154         
1155         if (stringPrototypeStructure->isDictionary())
1156             return false;
1157         
1158         // We're being conservative here. We want DFG's ToString on StringObject to be
1159         // used in both numeric contexts (that would call valueOf()) and string contexts
1160         // (that would call toString()). We don't want the DFG to have to distinguish
1161         // between the two, just because that seems like it would get confusing. So we
1162         // just require both methods to be sane.
1163         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
1164             return false;
1165         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString.impl()))
1166             return false;
1167         
1168         return true;
1169     }
1170     
1171     void fixupSetLocalsInBlock(BasicBlock* block)
1172     {
1173         if (!block)
1174             return;
1175         ASSERT(block->isReachable);
1176         m_block = block;
1177         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1178             Node* node = m_currentNode = block->at(m_indexInBlock);
1179             if (node->op() != SetLocal)
1180                 continue;
1181             
1182             VariableAccessData* variable = node->variableAccessData();
1183             switch (variable->flushFormat()) {
1184             case FlushedJSValue:
1185                 break;
1186             case FlushedDouble:
1187                 fixEdge<NumberUse>(node->child1(), ForwardSpeculation);
1188                 break;
1189             case FlushedInt32:
1190                 fixEdge<Int32Use>(node->child1());
1191                 break;
1192             case FlushedCell:
1193                 fixEdge<CellUse>(node->child1());
1194                 break;
1195             case FlushedBoolean:
1196                 fixEdge<BooleanUse>(node->child1());
1197                 break;
1198             default:
1199                 RELEASE_ASSERT_NOT_REACHED();
1200                 break;
1201             }
1202         }
1203         m_insertionSet.execute(block);
1204     }
1205     
1206     Node* checkArray(ArrayMode arrayMode, const CodeOrigin& codeOrigin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
1207     {
1208         ASSERT(arrayMode.isSpecific());
1209         
1210         Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
1211         
1212         Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1213         
1214         if (arrayMode.doesConversion()) {
1215             if (structure) {
1216                 m_insertionSet.insertNode(
1217                     m_indexInBlock, SpecNone, ArrayifyToStructure, codeOrigin,
1218                     OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1219             } else {
1220                 m_insertionSet.insertNode(
1221                     m_indexInBlock, SpecNone, Arrayify, codeOrigin,
1222                     OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1223             }
1224         } else {
1225             if (structure) {
1226                 m_insertionSet.insertNode(
1227                     m_indexInBlock, SpecNone, CheckStructure, codeOrigin,
1228                     OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1229             } else {
1230                 m_insertionSet.insertNode(
1231                     m_indexInBlock, SpecNone, CheckArray, codeOrigin,
1232                     OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1233             }
1234         }
1235         
1236         if (!storageCheck(arrayMode))
1237             return 0;
1238         
1239         if (arrayMode.usesButterfly()) {
1240             return m_insertionSet.insertNode(
1241                 m_indexInBlock, SpecNone, GetButterfly, codeOrigin, Edge(array, CellUse));
1242         }
1243         
1244         return m_insertionSet.insertNode(
1245             m_indexInBlock, SpecNone, GetIndexedPropertyStorage, codeOrigin,
1246             OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
1247     }
1248     
1249     void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
1250     {
1251         Node* node = m_currentNode;
1252         
1253         switch (node->arrayMode().type()) {
1254         case Array::ForceExit: {
1255             m_insertionSet.insertNode(
1256                 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
1257             return;
1258         }
1259             
1260         case Array::SelectUsingPredictions:
1261         case Array::Unprofiled:
1262             RELEASE_ASSERT_NOT_REACHED();
1263             return;
1264             
1265         case Array::Generic:
1266             return;
1267             
1268         default: {
1269             Node* storage = checkArray(node->arrayMode(), node->codeOrigin, base.node(), index.node());
1270             if (!storage)
1271                 return;
1272             
1273             storageChild = Edge(storage);
1274             return;
1275         } }
1276     }
1277     
1278     bool alwaysUnboxSimplePrimitives()
1279     {
1280 #if USE(JSVALUE64)
1281         return false;
1282 #else
1283         // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1284         // reduces traffic.
1285         return true;
1286 #endif
1287     }
1288
1289     template<UseKind useKind>
1290     void observeUseKindOnNode(Node* node)
1291     {
1292         if (useKind == UntypedUse)
1293             return;
1294         observeUseKindOnNode(node, useKind);
1295     }
1296
1297     void observeUseKindOnEdge(Edge edge)
1298     {
1299         observeUseKindOnNode(edge.node(), edge.useKind());
1300     }
1301
1302     void observeUseKindOnNode(Node* node, UseKind useKind)
1303     {
1304         if (node->op() != GetLocal)
1305             return;
1306         
1307         VariableAccessData* variable = node->variableAccessData();
1308         switch (useKind) {
1309         case Int32Use:
1310             if (alwaysUnboxSimplePrimitives()
1311                 || isInt32Speculation(variable->prediction()))
1312                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1313             break;
1314         case NumberUse:
1315         case RealNumberUse:
1316             if (variable->doubleFormatState() == UsingDoubleFormat)
1317                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1318             break;
1319         case BooleanUse:
1320             if (alwaysUnboxSimplePrimitives()
1321                 || isBooleanSpeculation(variable->prediction()))
1322                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1323             break;
1324         case CellUse:
1325         case KnownCellUse:
1326         case ObjectUse:
1327         case StringUse:
1328         case KnownStringUse:
1329         case StringObjectUse:
1330         case StringOrStringObjectUse:
1331             if (alwaysUnboxSimplePrimitives()
1332                 || isCellSpeculation(variable->prediction()))
1333                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1334             break;
1335         default:
1336             break;
1337         }
1338     }
1339     
1340     // Set the use kind of the edge and perform any actions that need to be done for
1341     // that use kind, like inserting intermediate conversion nodes. Never call this
1342     // with useKind = UntypedUse explicitly; edges have UntypedUse implicitly and any
1343     // edge that survives fixup and still has UntypedUse will have this method called
1344     // from observeUntypedEdge(). Also, make sure that if you do change the type of an
1345     // edge, you either call fixEdge() or perform the equivalent functionality
1346     // yourself. Obviously, you should have a really good reason if you do the latter.
1347     template<UseKind useKind>
1348     void fixEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
1349     {
1350         if (isDouble(useKind) && edge->shouldSpeculateInt32ForArithmetic()) {
1351             injectInt32ToDoubleNode(edge, useKind, direction);
1352             return;
1353         }
1354         
1355         observeUseKindOnNode<useKind>(edge.node());
1356         edge.setUseKind(useKind);
1357     }
1358     
1359     void fixIntEdge(Edge& edge)
1360     {
1361         Node* node = edge.node();
1362         if (node->op() != ValueToInt32) {
1363             fixEdge<KnownInt32Use>(edge);
1364             return;
1365         }
1366         
1367         Edge newEdge = node->child1();
1368         
1369         if (newEdge.useKind() != Int32Use) {
1370             edge.setUseKind(KnownInt32Use);
1371             return;
1372         }
1373         
1374         ASSERT(newEdge->shouldSpeculateInt32());
1375         edge = newEdge;
1376     }
1377     
1378     void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
1379     {
1380         Node* result = m_insertionSet.insertNode(
1381             m_indexInBlock, SpecInt48, Int32ToDouble,
1382             m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
1383         if (direction == ForwardSpeculation)
1384             result->mergeFlags(NodeExitsForward);
1385         
1386 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1387         dataLogF(
1388             "(replacing @%u->@%u with @%u->@%u) ",
1389             m_currentNode->index(), edge->index(), m_currentNode->index(), result->index());
1390 #endif
1391
1392         edge = Edge(result, useKind);
1393     }
1394     
1395     void truncateConstantToInt32(Edge& edge)
1396     {
1397         Node* oldNode = edge.node();
1398         
1399         ASSERT(oldNode->hasConstant());
1400         JSValue value = m_graph.valueOfJSConstant(oldNode);
1401         if (value.isInt32())
1402             return;
1403         
1404         value = jsNumber(JSC::toInt32(value.asNumber()));
1405         ASSERT(value.isInt32());
1406         unsigned constantRegister;
1407         if (!codeBlock()->findConstant(value, constantRegister)) {
1408             constantRegister = codeBlock()->addConstantLazily();
1409             initializeLazyWriteBarrierForConstant(
1410                 m_graph.m_plan.writeBarriers,
1411                 codeBlock()->constants()[constantRegister],
1412                 codeBlock(),
1413                 constantRegister,
1414                 codeBlock()->ownerExecutable(),
1415                 value);
1416         }
1417         edge.setNode(m_insertionSet.insertNode(
1418             m_indexInBlock, SpecInt32, JSConstant, m_currentNode->codeOrigin,
1419             OpInfo(constantRegister)));
1420     }
1421     
1422     void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1423     {
1424         if (mode != SpeculateInt32AndTruncateConstants)
1425             return;
1426         
1427         ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1428         if (node->child1()->hasConstant())
1429             truncateConstantToInt32(node->child1());
1430         else
1431             truncateConstantToInt32(node->child2());
1432     }
1433     
1434     bool attemptToMakeIntegerAdd(Node* node)
1435     {
1436         AddSpeculationMode mode = m_graph.addSpeculationMode(node);
1437         if (mode == DontSpeculateInt32)
1438             return false;
1439         
1440         truncateConstantsIfNecessary(node, mode);
1441         fixEdge<Int32Use>(node->child1());
1442         fixEdge<Int32Use>(node->child2());
1443         return true;
1444     }
1445     
1446     bool attemptToMakeGetArrayLength(Node* node)
1447     {
1448         if (!isInt32Speculation(node->prediction()))
1449             return false;
1450         CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->codeOrigin);
1451         ArrayProfile* arrayProfile = 
1452             profiledBlock->getArrayProfile(node->codeOrigin.bytecodeIndex);
1453         ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
1454         if (arrayProfile) {
1455             ConcurrentJITLocker locker(profiledBlock->m_lock);
1456             arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
1457             arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
1458             if (arrayMode.type() == Array::Unprofiled) {
1459                 // For normal array operations, it makes sense to treat Unprofiled
1460                 // accesses as ForceExit and get more data rather than using
1461                 // predictions and then possibly ending up with a Generic. But here,
1462                 // we treat anything that is Unprofiled as Generic and keep the
1463                 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
1464                 // profit - from treating the Unprofiled case as
1465                 // SelectUsingPredictions.
1466                 arrayMode = ArrayMode(Array::SelectUsingPredictions);
1467             }
1468         }
1469             
1470         arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
1471             
1472         if (arrayMode.type() == Array::Generic) {
1473             // Check if the input is something that we can't get array length for, but for which we
1474             // could insert some conversions in order to transform it into something that we can do it
1475             // for.
1476             if (node->child1()->shouldSpeculateStringObject())
1477                 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
1478             else if (node->child1()->shouldSpeculateStringOrStringObject())
1479                 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
1480         }
1481             
1482         if (!arrayMode.supportsLength())
1483             return false;
1484         
1485         convertToGetArrayLength(node, arrayMode);
1486         return true;
1487     }
1488     
1489     bool attemptToMakeGetTypedArrayByteLength(Node* node)
1490     {
1491         if (!isInt32Speculation(node->prediction()))
1492             return false;
1493         
1494         TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1495         if (!isTypedView(type))
1496             return false;
1497         
1498         if (elementSize(type) == 1) {
1499             convertToGetArrayLength(node, ArrayMode(toArrayType(type)));
1500             return true;
1501         }
1502         
1503         Node* length = prependGetArrayLength(
1504             node->codeOrigin, node->child1().node(), ArrayMode(toArrayType(type)));
1505         
1506         Node* shiftAmount = m_insertionSet.insertNode(
1507             m_indexInBlock, SpecInt32, JSConstant, node->codeOrigin,
1508             OpInfo(m_graph.constantRegisterForConstant(jsNumber(logElementSize(type)))));
1509         
1510         // We can use a BitLShift here because typed arrays will never have a byteLength
1511         // that overflows int32.
1512         node->setOp(BitLShift);
1513         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1514         observeUseKindOnNode(length, Int32Use);
1515         observeUseKindOnNode(shiftAmount, Int32Use);
1516         node->child1() = Edge(length, Int32Use);
1517         node->child2() = Edge(shiftAmount, Int32Use);
1518         return true;
1519     }
1520     
1521     void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
1522     {
1523         node->setOp(GetArrayLength);
1524         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1525         fixEdge<KnownCellUse>(node->child1());
1526         node->setArrayMode(arrayMode);
1527             
1528         Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage);
1529         if (!storage)
1530             return;
1531             
1532         node->child2() = Edge(storage);
1533     }
1534     
1535     Node* prependGetArrayLength(CodeOrigin codeOrigin, Node* child, ArrayMode arrayMode)
1536     {
1537         Node* storage = checkArray(arrayMode, codeOrigin, child, 0, lengthNeedsStorage);
1538         return m_insertionSet.insertNode(
1539             m_indexInBlock, SpecInt32, GetArrayLength, codeOrigin,
1540             OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
1541     }
1542     
1543     bool attemptToMakeGetTypedArrayByteOffset(Node* node)
1544     {
1545         if (!isInt32Speculation(node->prediction()))
1546             return false;
1547         
1548         TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1549         if (!isTypedView(type))
1550             return false;
1551         
1552         checkArray(
1553             ArrayMode(toArrayType(type)), node->codeOrigin, node->child1().node(),
1554             0, neverNeedsStorage);
1555         
1556         node->setOp(GetTypedArrayByteOffset);
1557         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1558         fixEdge<KnownCellUse>(node->child1());
1559         return true;
1560     }
1561
1562     BasicBlock* m_block;
1563     unsigned m_indexInBlock;
1564     Node* m_currentNode;
1565     InsertionSet m_insertionSet;
1566     bool m_profitabilityChanged;
1567 };
1568     
1569 bool performFixup(Graph& graph)
1570 {
1571     SamplingRegion samplingRegion("DFG Fixup Phase");
1572     return runPhase<FixupPhase>(graph);
1573 }
1574
1575 } } // namespace JSC::DFG
1576
1577 #endif // ENABLE(DFG_JIT)
1578