Get rid of forward exit on DoubleAsInt32
[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         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
68             fixupUntypedSetLocalsInBlock(m_graph.block(blockIndex));
69         
70         return true;
71     }
72
73 private:
74     void fixupBlock(BasicBlock* block)
75     {
76         if (!block)
77             return;
78         ASSERT(block->isReachable);
79         m_block = block;
80         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
81             m_currentNode = block->at(m_indexInBlock);
82             fixupNode(m_currentNode);
83         }
84         m_insertionSet.execute(block);
85     }
86     
87     void fixupNode(Node* node)
88     {
89         NodeType op = node->op();
90
91         switch (op) {
92         case SetLocal: {
93             // This gets handled by fixupSetLocalsInBlock().
94             return;
95         }
96             
97         case BitOr: {
98             fixIntEdge(node->child1());
99             fixIntEdge(node->child2());
100             break;
101         }
102         case BitAnd:
103         case BitXor:
104         case BitRShift:
105         case BitLShift:
106         case BitURShift:
107         case ArithIMul: {
108             fixIntEdge(node->child1());
109             fixIntEdge(node->child2());
110             break;
111         }
112             
113         case UInt32ToNumber: {
114             fixEdge<KnownInt32Use>(node->child1());
115             break;
116         }
117             
118         case DoubleAsInt32: {
119             RELEASE_ASSERT_NOT_REACHED();
120             break;
121         }
122             
123         case ValueToInt32: {
124             if (node->child1()->shouldSpeculateInt32()) {
125                 fixEdge<Int32Use>(node->child1());
126                 node->setOpAndDefaultFlags(Identity);
127                 break;
128             }
129             
130             if (node->child1()->shouldSpeculateMachineInt()) {
131                 fixEdge<MachineIntUse>(node->child1());
132                 break;
133             }
134             
135             if (node->child1()->shouldSpeculateNumber()) {
136                 fixEdge<NumberUse>(node->child1());
137                 break;
138             }
139             
140             if (node->child1()->shouldSpeculateBoolean()) {
141                 fixEdge<BooleanUse>(node->child1());
142                 break;
143             }
144             
145             fixEdge<NotCellUse>(node->child1());
146             break;
147         }
148             
149         case Int32ToDouble: {
150             RELEASE_ASSERT_NOT_REACHED();
151             break;
152         }
153             
154         case ValueAdd: {
155             if (attemptToMakeIntegerAdd(node))
156                 break;
157             if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {
158                 fixEdge<NumberUse>(node->child1());
159                 fixEdge<NumberUse>(node->child2());
160                 break;
161             }
162             
163             // FIXME: Optimize for the case where one of the operands is the
164             // empty string. Also consider optimizing for the case where we don't
165             // believe either side is the emtpy string. Both of these things should
166             // be easy.
167             
168             if (node->child1()->shouldSpeculateString()
169                 && attemptToMakeFastStringAdd<StringUse>(node, node->child1(), node->child2()))
170                 break;
171             if (node->child2()->shouldSpeculateString()
172                 && attemptToMakeFastStringAdd<StringUse>(node, node->child2(), node->child1()))
173                 break;
174             if (node->child1()->shouldSpeculateStringObject()
175                 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child1(), node->child2()))
176                 break;
177             if (node->child2()->shouldSpeculateStringObject()
178                 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child2(), node->child1()))
179                 break;
180             if (node->child1()->shouldSpeculateStringOrStringObject()
181                 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child1(), node->child2()))
182                 break;
183             if (node->child2()->shouldSpeculateStringOrStringObject()
184                 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child2(), node->child1()))
185                 break;
186             break;
187         }
188             
189         case MakeRope: {
190             fixupMakeRope(node);
191             break;
192         }
193             
194         case ArithAdd:
195         case ArithSub: {
196             if (attemptToMakeIntegerAdd(node))
197                 break;
198             fixEdge<NumberUse>(node->child1());
199             fixEdge<NumberUse>(node->child2());
200             break;
201         }
202             
203         case ArithNegate: {
204             if (m_graph.negateShouldSpeculateInt32(node)) {
205                 fixEdge<Int32Use>(node->child1());
206                 break;
207             }
208             if (m_graph.negateShouldSpeculateMachineInt(node)) {
209                 fixEdge<MachineIntUse>(node->child1());
210                 break;
211             }
212             fixEdge<NumberUse>(node->child1());
213             break;
214         }
215             
216         case ArithMul: {
217             if (m_graph.mulShouldSpeculateInt32(node)) {
218                 fixEdge<Int32Use>(node->child1());
219                 fixEdge<Int32Use>(node->child2());
220                 break;
221             }
222             if (m_graph.mulShouldSpeculateMachineInt(node)) {
223                 fixEdge<MachineIntUse>(node->child1());
224                 fixEdge<MachineIntUse>(node->child2());
225                 break;
226             }
227             fixEdge<NumberUse>(node->child1());
228             fixEdge<NumberUse>(node->child2());
229             break;
230         }
231
232         case ArithDiv:
233         case ArithMod: {
234             if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
235                 && node->canSpeculateInt32()) {
236                 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7s()) {
237                     fixEdge<Int32Use>(node->child1());
238                     fixEdge<Int32Use>(node->child2());
239                     break;
240                 }
241                 Edge child1 = node->child1();
242                 Edge child2 = node->child2();
243                 
244                 injectInt32ToDoubleNode(node->child1());
245                 injectInt32ToDoubleNode(node->child2());
246
247                 // We don't need to do ref'ing on the children because we're stealing them from
248                 // the original division.
249                 Node* newDivision = m_insertionSet.insertNode(
250                     m_indexInBlock, SpecDouble, *node);
251                 
252                 node->setOp(DoubleAsInt32);
253                 node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
254                 
255                 m_insertionSet.insertNode(m_indexInBlock + 1, SpecNone, Phantom, node->codeOrigin, child1, child2);
256                 break;
257             }
258             fixEdge<NumberUse>(node->child1());
259             fixEdge<NumberUse>(node->child2());
260             break;
261         }
262             
263         case ArithMin:
264         case ArithMax: {
265             if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
266                 && node->canSpeculateInt32()) {
267                 fixEdge<Int32Use>(node->child1());
268                 fixEdge<Int32Use>(node->child2());
269                 break;
270             }
271             fixEdge<NumberUse>(node->child1());
272             fixEdge<NumberUse>(node->child2());
273             break;
274         }
275             
276         case ArithAbs: {
277             if (node->child1()->shouldSpeculateInt32ForArithmetic()
278                 && node->canSpeculateInt32()) {
279                 fixEdge<Int32Use>(node->child1());
280                 break;
281             }
282             fixEdge<NumberUse>(node->child1());
283             break;
284         }
285             
286         case ArithSqrt:
287         case ArithSin:
288         case ArithCos: {
289             fixEdge<NumberUse>(node->child1());
290             break;
291         }
292             
293         case LogicalNot: {
294             if (node->child1()->shouldSpeculateBoolean())
295                 fixEdge<BooleanUse>(node->child1());
296             else if (node->child1()->shouldSpeculateObjectOrOther())
297                 fixEdge<ObjectOrOtherUse>(node->child1());
298             else if (node->child1()->shouldSpeculateInt32())
299                 fixEdge<Int32Use>(node->child1());
300             else if (node->child1()->shouldSpeculateNumber())
301                 fixEdge<NumberUse>(node->child1());
302             else if (node->child1()->shouldSpeculateString())
303                 fixEdge<StringUse>(node->child1());
304             break;
305         }
306             
307         case TypeOf: {
308             if (node->child1()->shouldSpeculateString())
309                 fixEdge<StringUse>(node->child1());
310             else if (node->child1()->shouldSpeculateCell())
311                 fixEdge<CellUse>(node->child1());
312             break;
313         }
314             
315         case CompareEqConstant: {
316             break;
317         }
318
319         case CompareEq:
320         case CompareLess:
321         case CompareLessEq:
322         case CompareGreater:
323         case CompareGreaterEq: {
324             if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
325                 fixEdge<Int32Use>(node->child1());
326                 fixEdge<Int32Use>(node->child2());
327                 break;
328             }
329             if (enableInt52()
330                 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
331                 fixEdge<MachineIntUse>(node->child1());
332                 fixEdge<MachineIntUse>(node->child2());
333                 break;
334             }
335             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
336                 fixEdge<NumberUse>(node->child1());
337                 fixEdge<NumberUse>(node->child2());
338                 break;
339             }
340             if (node->op() != CompareEq)
341                 break;
342             if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
343                 fixEdge<BooleanUse>(node->child1());
344                 fixEdge<BooleanUse>(node->child2());
345                 break;
346             }
347             if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
348                 fixEdge<StringIdentUse>(node->child1());
349                 fixEdge<StringIdentUse>(node->child2());
350                 break;
351             }
352             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
353                 fixEdge<StringUse>(node->child1());
354                 fixEdge<StringUse>(node->child2());
355                 break;
356             }
357             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
358                 fixEdge<ObjectUse>(node->child1());
359                 fixEdge<ObjectUse>(node->child2());
360                 break;
361             }
362             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
363                 fixEdge<ObjectUse>(node->child1());
364                 fixEdge<ObjectOrOtherUse>(node->child2());
365                 break;
366             }
367             if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
368                 fixEdge<ObjectOrOtherUse>(node->child1());
369                 fixEdge<ObjectUse>(node->child2());
370                 break;
371             }
372             break;
373         }
374             
375         case CompareStrictEqConstant: {
376             break;
377         }
378             
379         case CompareStrictEq: {
380             if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
381                 fixEdge<BooleanUse>(node->child1());
382                 fixEdge<BooleanUse>(node->child2());
383                 break;
384             }
385             if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
386                 fixEdge<Int32Use>(node->child1());
387                 fixEdge<Int32Use>(node->child2());
388                 break;
389             }
390             if (enableInt52()
391                 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
392                 fixEdge<MachineIntUse>(node->child1());
393                 fixEdge<MachineIntUse>(node->child2());
394                 break;
395             }
396             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
397                 fixEdge<NumberUse>(node->child1());
398                 fixEdge<NumberUse>(node->child2());
399                 break;
400             }
401             if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
402                 fixEdge<StringIdentUse>(node->child1());
403                 fixEdge<StringIdentUse>(node->child2());
404                 break;
405             }
406             if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
407                 fixEdge<StringUse>(node->child1());
408                 fixEdge<StringUse>(node->child2());
409                 break;
410             }
411             if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
412                 fixEdge<ObjectUse>(node->child1());
413                 fixEdge<ObjectUse>(node->child2());
414                 break;
415             }
416             break;
417         }
418
419         case StringFromCharCode:
420             fixEdge<Int32Use>(node->child1());
421             break;
422
423         case StringCharAt:
424         case StringCharCodeAt: {
425             // Currently we have no good way of refining these.
426             ASSERT(node->arrayMode() == ArrayMode(Array::String));
427             blessArrayOperation(node->child1(), node->child2(), node->child3());
428             fixEdge<KnownCellUse>(node->child1());
429             fixEdge<Int32Use>(node->child2());
430             break;
431         }
432
433         case GetByVal: {
434             node->setArrayMode(
435                 node->arrayMode().refine(
436                     node->child1()->prediction(),
437                     node->child2()->prediction(),
438                     SpecNone, node->flags()));
439             
440             blessArrayOperation(node->child1(), node->child2(), node->child3());
441             
442             ArrayMode arrayMode = node->arrayMode();
443             switch (arrayMode.type()) {
444             case Array::Double:
445                 if (arrayMode.arrayClass() == Array::OriginalArray
446                     && arrayMode.speculation() == Array::InBounds
447                     && m_graph.globalObjectFor(node->codeOrigin)->arrayPrototypeChainIsSane()
448                     && !(node->flags() & NodeBytecodeUsesAsOther))
449                     node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
450                 break;
451                 
452             case Array::String:
453                 if ((node->prediction() & ~SpecString)
454                     || m_graph.hasExitSite(node->codeOrigin, OutOfBounds))
455                     node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
456                 break;
457                 
458             default:
459                 break;
460             }
461             
462             switch (node->arrayMode().type()) {
463             case Array::SelectUsingPredictions:
464             case Array::Unprofiled:
465             case Array::Undecided:
466                 RELEASE_ASSERT_NOT_REACHED();
467                 break;
468             case Array::Generic:
469 #if USE(JSVALUE32_64)
470                 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
471 #endif
472                 break;
473             case Array::ForceExit:
474                 break;
475             default:
476                 fixEdge<KnownCellUse>(node->child1());
477                 fixEdge<Int32Use>(node->child2());
478                 break;
479             }
480             
481             break;
482         }
483
484         case PutByValDirect:
485         case PutByVal:
486         case PutByValAlias: {
487             Edge& child1 = m_graph.varArgChild(node, 0);
488             Edge& child2 = m_graph.varArgChild(node, 1);
489             Edge& child3 = m_graph.varArgChild(node, 2);
490
491             node->setArrayMode(
492                 node->arrayMode().refine(
493                     child1->prediction(),
494                     child2->prediction(),
495                     child3->prediction()));
496             
497             blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
498             
499             switch (node->arrayMode().modeForPut().type()) {
500             case Array::SelectUsingPredictions:
501             case Array::Unprofiled:
502             case Array::Undecided:
503                 RELEASE_ASSERT_NOT_REACHED();
504                 break;
505             case Array::ForceExit:
506             case Array::Generic:
507 #if USE(JSVALUE32_64)
508                 // Due to register pressure on 32-bit, we speculate cell and
509                 // ignore the base-is-not-cell case entirely by letting the
510                 // baseline JIT handle it.
511                 fixEdge<CellUse>(child1);
512 #endif
513                 break;
514             case Array::Int32:
515                 fixEdge<KnownCellUse>(child1);
516                 fixEdge<Int32Use>(child2);
517                 fixEdge<Int32Use>(child3);
518                 if (child3->prediction() & SpecInt52)
519                     fixEdge<MachineIntUse>(child3);
520                 else
521                     fixEdge<Int32Use>(child3);
522                 break;
523             case Array::Double:
524                 fixEdge<KnownCellUse>(child1);
525                 fixEdge<Int32Use>(child2);
526                 fixEdge<RealNumberUse>(child3);
527                 break;
528             case Array::Int8Array:
529             case Array::Int16Array:
530             case Array::Int32Array:
531             case Array::Uint8Array:
532             case Array::Uint8ClampedArray:
533             case Array::Uint16Array:
534             case Array::Uint32Array:
535                 fixEdge<KnownCellUse>(child1);
536                 fixEdge<Int32Use>(child2);
537                 if (child3->shouldSpeculateInt32())
538                     fixEdge<Int32Use>(child3);
539                 else if (child3->shouldSpeculateMachineInt())
540                     fixEdge<MachineIntUse>(child3);
541                 else
542                     fixEdge<NumberUse>(child3);
543                 break;
544             case Array::Float32Array:
545             case Array::Float64Array:
546                 fixEdge<KnownCellUse>(child1);
547                 fixEdge<Int32Use>(child2);
548                 fixEdge<NumberUse>(child3);
549                 break;
550             default:
551                 fixEdge<KnownCellUse>(child1);
552                 fixEdge<Int32Use>(child2);
553                 break;
554             }
555             break;
556         }
557             
558         case ArrayPush: {
559             // May need to refine the array mode in case the value prediction contravenes
560             // the array prediction. For example, we may have evidence showing that the
561             // array is in Int32 mode, but the value we're storing is likely to be a double.
562             // Then we should turn this into a conversion to Double array followed by the
563             // push. On the other hand, we absolutely don't want to refine based on the
564             // base prediction. If it has non-cell garbage in it, then we want that to be
565             // ignored. That's because ArrayPush can't handle any array modes that aren't
566             // array-related - so if refine() turned this into a "Generic" ArrayPush then
567             // that would break things.
568             node->setArrayMode(
569                 node->arrayMode().refine(
570                     node->child1()->prediction() & SpecCell,
571                     SpecInt32,
572                     node->child2()->prediction()));
573             blessArrayOperation(node->child1(), Edge(), node->child3());
574             fixEdge<KnownCellUse>(node->child1());
575             
576             switch (node->arrayMode().type()) {
577             case Array::Int32:
578                 fixEdge<Int32Use>(node->child2());
579                 break;
580             case Array::Double:
581                 fixEdge<RealNumberUse>(node->child2());
582                 break;
583             default:
584                 break;
585             }
586             break;
587         }
588             
589         case ArrayPop: {
590             blessArrayOperation(node->child1(), Edge(), node->child2());
591             fixEdge<KnownCellUse>(node->child1());
592             break;
593         }
594             
595         case RegExpExec:
596         case RegExpTest: {
597             fixEdge<CellUse>(node->child1());
598             fixEdge<CellUse>(node->child2());
599             break;
600         }
601             
602         case Branch: {
603             if (node->child1()->shouldSpeculateBoolean())
604                 fixEdge<BooleanUse>(node->child1());
605             else if (node->child1()->shouldSpeculateObjectOrOther())
606                 fixEdge<ObjectOrOtherUse>(node->child1());
607             else if (node->child1()->shouldSpeculateInt32())
608                 fixEdge<Int32Use>(node->child1());
609             else if (node->child1()->shouldSpeculateNumber())
610                 fixEdge<NumberUse>(node->child1());
611
612             Node* logicalNot = node->child1().node();
613             if (logicalNot->op() == LogicalNot) {
614                 
615                 // Make sure that OSR exit can't observe the LogicalNot. If it can,
616                 // then we must compute it and cannot peephole around it.
617                 bool found = false;
618                 bool ok = true;
619                 for (unsigned i = m_indexInBlock; i--;) {
620                     Node* candidate = m_block->at(i);
621                     if (candidate == logicalNot) {
622                         found = true;
623                         break;
624                     }
625                     if (candidate->canExit()) {
626                         ok = false;
627                         found = true;
628                         break;
629                     }
630                 }
631                 ASSERT_UNUSED(found, found);
632                 
633                 if (ok) {
634                     Edge newChildEdge = logicalNot->child1();
635                     if (newChildEdge->hasBooleanResult()) {
636                         node->children.setChild1(newChildEdge);
637                         
638                         BasicBlock* toBeTaken = node->notTakenBlock();
639                         BasicBlock* toBeNotTaken = node->takenBlock();
640                         node->setTakenBlock(toBeTaken);
641                         node->setNotTakenBlock(toBeNotTaken);
642                     }
643                 }
644             }
645             break;
646         }
647             
648         case Switch: {
649             SwitchData* data = node->switchData();
650             switch (data->kind) {
651             case SwitchImm:
652                 if (node->child1()->shouldSpeculateInt32())
653                     fixEdge<Int32Use>(node->child1());
654                 break;
655             case SwitchChar:
656                 if (node->child1()->shouldSpeculateString())
657                     fixEdge<StringUse>(node->child1());
658                 break;
659             case SwitchString:
660                 if (node->child1()->shouldSpeculateStringIdent())
661                     fixEdge<StringIdentUse>(node->child1());
662                 else if (node->child1()->shouldSpeculateString())
663                     fixEdge<StringUse>(node->child1());
664                 break;
665             }
666             break;
667         }
668             
669         case ToPrimitive: {
670             fixupToPrimitive(node);
671             break;
672         }
673             
674         case ToString: {
675             fixupToString(node);
676             break;
677         }
678             
679         case NewStringObject: {
680             fixEdge<KnownStringUse>(node->child1());
681             break;
682         }
683             
684         case NewArray: {
685             for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
686                 node->setIndexingType(
687                     leastUpperBoundOfIndexingTypeAndType(
688                         node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
689             }
690             switch (node->indexingType()) {
691             case ALL_BLANK_INDEXING_TYPES:
692                 CRASH();
693                 break;
694             case ALL_UNDECIDED_INDEXING_TYPES:
695                 if (node->numChildren()) {
696                     // This will only happen if the children have no type predictions. We
697                     // would have already exited by now, but insert a forced exit just to
698                     // be safe.
699                     m_insertionSet.insertNode(
700                         m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
701                 }
702                 break;
703             case ALL_INT32_INDEXING_TYPES:
704                 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
705                     fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
706                 break;
707             case ALL_DOUBLE_INDEXING_TYPES:
708                 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
709                     fixEdge<RealNumberUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
710                 break;
711             case ALL_CONTIGUOUS_INDEXING_TYPES:
712             case ALL_ARRAY_STORAGE_INDEXING_TYPES:
713                 break;
714             default:
715                 CRASH();
716                 break;
717             }
718             break;
719         }
720             
721         case NewTypedArray: {
722             if (node->child1()->shouldSpeculateInt32()) {
723                 fixEdge<Int32Use>(node->child1());
724                 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
725                 break;
726             }
727             break;
728         }
729             
730         case NewArrayWithSize: {
731             fixEdge<Int32Use>(node->child1());
732             break;
733         }
734             
735         case ToThis: {
736             ECMAMode ecmaMode = m_graph.executableFor(node->codeOrigin)->isStrictMode() ? StrictMode : NotStrictMode;
737
738             if (isOtherSpeculation(node->child1()->prediction())) {
739                 if (ecmaMode == StrictMode) {
740                     fixEdge<OtherUse>(node->child1());
741                     node->convertToIdentity();
742                     break;
743                 }
744
745                 m_insertionSet.insertNode(
746                     m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
747                     Edge(node->child1().node(), OtherUse));
748                 observeUseKindOnNode<OtherUse>(node->child1().node());
749                 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->codeOrigin));
750                 break;
751             }
752             
753             if (isFinalObjectSpeculation(node->child1()->prediction())) {
754                 fixEdge<FinalObjectUse>(node->child1());
755                 node->convertToIdentity();
756                 break;
757             }
758             
759             break;
760         }
761             
762         case GetMyArgumentByVal:
763         case GetMyArgumentByValSafe: {
764             fixEdge<Int32Use>(node->child1());
765             break;
766         }
767             
768         case GetClosureRegisters:
769         case PutClosureVar:
770         case SkipTopScope:
771         case SkipScope:
772         case PutStructure:
773         case AllocatePropertyStorage:
774         case ReallocatePropertyStorage:
775         case GetScope: {
776             fixEdge<KnownCellUse>(node->child1());
777             break;
778         }
779             
780         case GetById:
781         case GetByIdFlush: {
782             if (!node->child1()->shouldSpeculateCell())
783                 break;
784             StringImpl* impl = m_graph.identifiers()[node->identifierNumber()];
785             if (impl == vm().propertyNames->length.impl()) {
786                 attemptToMakeGetArrayLength(node);
787                 break;
788             }
789             if (impl == vm().propertyNames->byteLength.impl()) {
790                 attemptToMakeGetTypedArrayByteLength(node);
791                 break;
792             }
793             if (impl == vm().propertyNames->byteOffset.impl()) {
794                 attemptToMakeGetTypedArrayByteOffset(node);
795                 break;
796             }
797             fixEdge<CellUse>(node->child1());
798             break;
799         }
800             
801         case CheckExecutable:
802         case CheckStructure:
803         case StructureTransitionWatchpoint:
804         case CheckFunction:
805         case PutById:
806         case PutByIdDirect:
807         case CheckHasInstance:
808         case CreateThis:
809         case GetButterfly: {
810             fixEdge<CellUse>(node->child1());
811             break;
812         }
813             
814         case Arrayify:
815         case ArrayifyToStructure: {
816             fixEdge<CellUse>(node->child1());
817             if (node->child2())
818                 fixEdge<Int32Use>(node->child2());
819             break;
820         }
821             
822         case GetByOffset: {
823             if (!node->child1()->hasStorageResult())
824                 fixEdge<KnownCellUse>(node->child1());
825             fixEdge<KnownCellUse>(node->child2());
826             break;
827         }
828             
829         case PutByOffset: {
830             if (!node->child1()->hasStorageResult())
831                 fixEdge<KnownCellUse>(node->child1());
832             fixEdge<KnownCellUse>(node->child2());
833             break;
834         }
835             
836         case InstanceOf: {
837             // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
838             // check. https://bugs.webkit.org/show_bug.cgi?id=107479
839             if (!(node->child1()->prediction() & ~SpecCell))
840                 fixEdge<CellUse>(node->child1());
841             fixEdge<CellUse>(node->child2());
842             break;
843         }
844             
845         case In: {
846             // FIXME: We should at some point have array profiling on op_in, in which
847             // case we would be able to turn this into a kind of GetByVal.
848             
849             fixEdge<CellUse>(node->child2());
850             break;
851         }
852
853         case Phantom:
854         case Identity: {
855             switch (node->child1().useKind()) {
856             case NumberUse:
857                 if (node->child1()->shouldSpeculateInt32ForArithmetic())
858                     node->child1().setUseKind(Int32Use);
859                 break;
860             default:
861                 break;
862             }
863             observeUseKindOnEdge(node->child1());
864             break;
865         }
866
867         case GetArrayLength:
868         case Phi:
869         case Upsilon:
870         case GetArgument:
871         case PhantomPutStructure:
872         case GetIndexedPropertyStorage:
873         case GetTypedArrayByteOffset:
874         case LastNodeType:
875         case MovHint:
876         case MovHintAndCheck:
877         case ZombieHint:
878         case CheckTierUpInLoop:
879         case CheckTierUpAtReturn:
880         case CheckTierUpAndOSREnter:
881         case Int52ToDouble:
882         case Int52ToValue:
883         case InvalidationPoint:
884         case CheckArray:
885         case CheckInBounds:
886         case ConstantStoragePointer:
887             // These are just nodes that we don't currently expect to see during fixup.
888             // If we ever wanted to insert them prior to fixup, then we just have to create
889             // fixup rules for them.
890             RELEASE_ASSERT_NOT_REACHED();
891             break;
892
893         case IsString:
894             if (node->child1()->shouldSpeculateString()) {
895                 m_insertionSet.insertNode(m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
896                     Edge(node->child1().node(), StringUse));
897                 m_graph.convertToConstant(node, jsBoolean(true));
898                 observeUseKindOnNode<StringUse>(node);
899             }
900             break;
901
902 #if !ASSERT_DISABLED
903         // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
904         case SetArgument:
905         case JSConstant:
906         case WeakJSConstant:
907         case GetLocal:
908         case GetCallee:
909         case Flush:
910         case PhantomLocal:
911         case GetLocalUnlinked:
912         case GetMyScope:
913         case GetClosureVar:
914         case GetGlobalVar:
915         case PutGlobalVar:
916         case NotifyWrite:
917         case VariableWatchpoint:
918         case VarInjectionWatchpoint:
919         case AllocationProfileWatchpoint:
920         case Call:
921         case Construct:
922         case NewObject:
923         case NewArrayBuffer:
924         case NewRegexp:
925         case Breakpoint:
926         case IsUndefined:
927         case IsBoolean:
928         case IsNumber:
929         case IsObject:
930         case IsFunction:
931         case CreateActivation:
932         case TearOffActivation:
933         case CreateArguments:
934         case PhantomArguments:
935         case TearOffArguments:
936         case GetMyArgumentsLength:
937         case GetMyArgumentsLengthSafe:
938         case CheckArgumentsNotCreated:
939         case NewFunction:
940         case NewFunctionNoCheck:
941         case NewFunctionExpression:
942         case Jump:
943         case Return:
944         case Throw:
945         case ThrowReferenceError:
946         case CountExecution:
947         case ForceOSRExit:
948         case CheckWatchdogTimer:
949         case Unreachable:
950         case ExtractOSREntryLocal:
951         case LoopHint:
952         case FunctionReentryWatchpoint:
953         case TypedArrayWatchpoint:
954             break;
955 #else
956         default:
957             break;
958 #endif
959         }
960         
961         DFG_NODE_DO_TO_CHILDREN(m_graph, node, observeUntypedEdge);
962     }
963     
964     void observeUntypedEdge(Node*, Edge& edge)
965     {
966         if (edge.useKind() != UntypedUse)
967             return;
968         fixEdge<UntypedUse>(edge);
969     }
970     
971     template<UseKind useKind>
972     void createToString(Node* node, Edge& edge)
973     {
974         edge.setNode(m_insertionSet.insertNode(
975             m_indexInBlock, SpecString, ToString, node->codeOrigin,
976             Edge(edge.node(), useKind)));
977     }
978     
979     template<UseKind useKind>
980     void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
981     {
982         ASSERT(arrayMode == ArrayMode(Array::Generic));
983         
984         if (!canOptimizeStringObjectAccess(node->codeOrigin))
985             return;
986         
987         createToString<useKind>(node, node->child1());
988         arrayMode = ArrayMode(Array::String);
989     }
990     
991     template<UseKind useKind>
992     bool isStringObjectUse()
993     {
994         switch (useKind) {
995         case StringObjectUse:
996         case StringOrStringObjectUse:
997             return true;
998         default:
999             return false;
1000         }
1001     }
1002     
1003     template<UseKind useKind>
1004     void convertStringAddUse(Node* node, Edge& edge)
1005     {
1006         if (useKind == StringUse) {
1007             // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
1008             // two edges will always have identical use kinds, which makes the
1009             // decision process much easier.
1010             observeUseKindOnNode<StringUse>(edge.node());
1011             m_insertionSet.insertNode(
1012                 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
1013                 Edge(edge.node(), StringUse));
1014             edge.setUseKind(KnownStringUse);
1015             return;
1016         }
1017         
1018         // FIXME: We ought to be able to have a ToPrimitiveToString node.
1019         
1020         observeUseKindOnNode<useKind>(edge.node());
1021         createToString<useKind>(node, edge);
1022     }
1023     
1024     void convertToMakeRope(Node* node)
1025     {
1026         node->setOpAndDefaultFlags(MakeRope);
1027         fixupMakeRope(node);
1028     }
1029     
1030     void fixupMakeRope(Node* node)
1031     {
1032         for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1033             Edge& edge = node->children.child(i);
1034             if (!edge)
1035                 break;
1036             edge.setUseKind(KnownStringUse);
1037             if (!m_graph.isConstant(edge.node()))
1038                 continue;
1039             JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
1040             if (string->length())
1041                 continue;
1042             
1043             // Don't allow the MakeRope to have zero children.
1044             if (!i && !node->child2())
1045                 break;
1046             
1047             node->children.removeEdge(i--);
1048         }
1049         
1050         if (!node->child2()) {
1051             ASSERT(!node->child3());
1052             node->convertToIdentity();
1053         }
1054     }
1055     
1056     void fixupToPrimitive(Node* node)
1057     {
1058         if (node->child1()->shouldSpeculateInt32()) {
1059             fixEdge<Int32Use>(node->child1());
1060             node->convertToIdentity();
1061             return;
1062         }
1063         
1064         if (node->child1()->shouldSpeculateString()) {
1065             fixEdge<StringUse>(node->child1());
1066             node->convertToIdentity();
1067             return;
1068         }
1069         
1070         if (node->child1()->shouldSpeculateStringObject()
1071             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1072             fixEdge<StringObjectUse>(node->child1());
1073             node->convertToToString();
1074             return;
1075         }
1076         
1077         if (node->child1()->shouldSpeculateStringOrStringObject()
1078             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1079             fixEdge<StringOrStringObjectUse>(node->child1());
1080             node->convertToToString();
1081             return;
1082         }
1083     }
1084     
1085     void fixupToString(Node* node)
1086     {
1087         if (node->child1()->shouldSpeculateString()) {
1088             fixEdge<StringUse>(node->child1());
1089             node->convertToIdentity();
1090             return;
1091         }
1092         
1093         if (node->child1()->shouldSpeculateStringObject()
1094             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1095             fixEdge<StringObjectUse>(node->child1());
1096             return;
1097         }
1098         
1099         if (node->child1()->shouldSpeculateStringOrStringObject()
1100             && canOptimizeStringObjectAccess(node->codeOrigin)) {
1101             fixEdge<StringOrStringObjectUse>(node->child1());
1102             return;
1103         }
1104         
1105         if (node->child1()->shouldSpeculateCell()) {
1106             fixEdge<CellUse>(node->child1());
1107             return;
1108         }
1109     }
1110     
1111     template<UseKind leftUseKind>
1112     bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1113     {
1114         Node* originalLeft = left.node();
1115         Node* originalRight = right.node();
1116         
1117         ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1118         
1119         if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->codeOrigin))
1120             return false;
1121         
1122         convertStringAddUse<leftUseKind>(node, left);
1123         
1124         if (right->shouldSpeculateString())
1125             convertStringAddUse<StringUse>(node, right);
1126         else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
1127             convertStringAddUse<StringObjectUse>(node, right);
1128         else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
1129             convertStringAddUse<StringOrStringObjectUse>(node, right);
1130         else {
1131             // At this point we know that the other operand is something weird. The semantically correct
1132             // way of dealing with this is:
1133             //
1134             // MakeRope(@left, ToString(ToPrimitive(@right)))
1135             //
1136             // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1137             // anything to @right, since ToPrimitive may be effectful.
1138             
1139             Node* toPrimitive = m_insertionSet.insertNode(
1140                 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive, node->codeOrigin,
1141                 Edge(right.node()));
1142             Node* toString = m_insertionSet.insertNode(
1143                 m_indexInBlock, SpecString, ToString, node->codeOrigin, Edge(toPrimitive));
1144             
1145             fixupToPrimitive(toPrimitive);
1146             fixupToString(toString);
1147             
1148             right.setNode(toString);
1149         }
1150         
1151         // We're doing checks up there, so we need to make sure that the
1152         // *original* inputs to the addition are live up to here.
1153         m_insertionSet.insertNode(
1154             m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
1155             Edge(originalLeft), Edge(originalRight));
1156         
1157         convertToMakeRope(node);
1158         return true;
1159     }
1160     
1161     bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid)
1162     {
1163         unsigned attributesUnused;
1164         JSCell* specificValue;
1165         PropertyOffset offset = stringPrototypeStructure->getConcurrently(
1166             vm(), uid, attributesUnused, specificValue);
1167         if (!isValidOffset(offset))
1168             return false;
1169         
1170         if (!specificValue)
1171             return false;
1172         
1173         if (!specificValue->inherits(JSFunction::info()))
1174             return false;
1175         
1176         JSFunction* function = jsCast<JSFunction*>(specificValue);
1177         if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1178             return false;
1179         
1180         return true;
1181     }
1182     
1183     bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1184     {
1185         if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1186             return false;
1187         
1188         Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1189         ASSERT(stringObjectStructure->storedPrototype().isObject());
1190         ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == StringPrototype::info());
1191         
1192         JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1193         Structure* stringPrototypeStructure = stringPrototypeObject->structure();
1194         if (!m_graph.watchpoints().isStillValid(stringPrototypeStructure->transitionWatchpointSet()))
1195             return false;
1196         
1197         if (stringPrototypeStructure->isDictionary())
1198             return false;
1199         
1200         // We're being conservative here. We want DFG's ToString on StringObject to be
1201         // used in both numeric contexts (that would call valueOf()) and string contexts
1202         // (that would call toString()). We don't want the DFG to have to distinguish
1203         // between the two, just because that seems like it would get confusing. So we
1204         // just require both methods to be sane.
1205         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
1206             return false;
1207         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString.impl()))
1208             return false;
1209         
1210         return true;
1211     }
1212     
1213     void fixupSetLocalsInBlock(BasicBlock* block)
1214     {
1215         if (!block)
1216             return;
1217         ASSERT(block->isReachable);
1218         m_block = block;
1219         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1220             Node* node = m_currentNode = block->at(m_indexInBlock);
1221             if (node->op() != SetLocal)
1222                 continue;
1223             
1224             VariableAccessData* variable = node->variableAccessData();
1225             switch (variable->flushFormat()) {
1226             case FlushedJSValue:
1227                 break;
1228             case FlushedDouble:
1229                 fixEdge<NumberUse>(node->child1());
1230                 break;
1231             case FlushedInt32:
1232                 fixEdge<Int32Use>(node->child1());
1233                 break;
1234             case FlushedInt52:
1235                 fixEdge<MachineIntUse>(node->child1());
1236                 break;
1237             case FlushedCell:
1238                 fixEdge<CellUse>(node->child1());
1239                 break;
1240             case FlushedBoolean:
1241                 fixEdge<BooleanUse>(node->child1());
1242                 break;
1243             default:
1244                 RELEASE_ASSERT_NOT_REACHED();
1245                 break;
1246             }
1247         }
1248         m_insertionSet.execute(block);
1249     }
1250     
1251     void fixupUntypedSetLocalsInBlock(BasicBlock* block)
1252     {
1253         if (!block)
1254             return;
1255         ASSERT(block->isReachable);
1256         m_block = block;
1257         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1258             Node* node = m_currentNode = block->at(m_indexInBlock);
1259             if (node->op() != SetLocal)
1260                 continue;
1261             
1262             if (node->child1().useKind() == UntypedUse)
1263                 fixEdge<UntypedUse>(node->child1());
1264         }
1265         m_insertionSet.execute(block);
1266     }
1267     
1268     Node* checkArray(ArrayMode arrayMode, const CodeOrigin& codeOrigin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
1269     {
1270         ASSERT(arrayMode.isSpecific());
1271         
1272         if (arrayMode.type() == Array::String) {
1273             m_insertionSet.insertNode(
1274                 m_indexInBlock, SpecNone, Phantom, codeOrigin,
1275                 Edge(array, StringUse));
1276         } else {
1277             Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
1278         
1279             Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1280         
1281             if (arrayMode.doesConversion()) {
1282                 if (structure) {
1283                     m_insertionSet.insertNode(
1284                         m_indexInBlock, SpecNone, ArrayifyToStructure, codeOrigin,
1285                         OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1286                 } else {
1287                     m_insertionSet.insertNode(
1288                         m_indexInBlock, SpecNone, Arrayify, codeOrigin,
1289                         OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1290                 }
1291             } else {
1292                 if (structure) {
1293                     m_insertionSet.insertNode(
1294                         m_indexInBlock, SpecNone, CheckStructure, codeOrigin,
1295                         OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1296                 } else {
1297                     m_insertionSet.insertNode(
1298                         m_indexInBlock, SpecNone, CheckArray, codeOrigin,
1299                         OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1300                 }
1301             }
1302         }
1303         
1304         if (!storageCheck(arrayMode))
1305             return 0;
1306         
1307         if (arrayMode.usesButterfly()) {
1308             return m_insertionSet.insertNode(
1309                 m_indexInBlock, SpecNone, GetButterfly, codeOrigin, Edge(array, CellUse));
1310         }
1311         
1312         return m_insertionSet.insertNode(
1313             m_indexInBlock, SpecNone, GetIndexedPropertyStorage, codeOrigin,
1314             OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
1315     }
1316     
1317     void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
1318     {
1319         Node* node = m_currentNode;
1320         
1321         switch (node->arrayMode().type()) {
1322         case Array::ForceExit: {
1323             m_insertionSet.insertNode(
1324                 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
1325             return;
1326         }
1327             
1328         case Array::SelectUsingPredictions:
1329         case Array::Unprofiled:
1330             RELEASE_ASSERT_NOT_REACHED();
1331             return;
1332             
1333         case Array::Generic:
1334             return;
1335             
1336         default: {
1337             Node* storage = checkArray(node->arrayMode(), node->codeOrigin, base.node(), index.node());
1338             if (!storage)
1339                 return;
1340             
1341             storageChild = Edge(storage);
1342             return;
1343         } }
1344     }
1345     
1346     bool alwaysUnboxSimplePrimitives()
1347     {
1348 #if USE(JSVALUE64)
1349         return false;
1350 #else
1351         // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1352         // reduces traffic.
1353         return true;
1354 #endif
1355     }
1356
1357     template<UseKind useKind>
1358     void observeUseKindOnNode(Node* node)
1359     {
1360         if (useKind == UntypedUse)
1361             return;
1362         observeUseKindOnNode(node, useKind);
1363     }
1364
1365     void observeUseKindOnEdge(Edge edge)
1366     {
1367         observeUseKindOnNode(edge.node(), edge.useKind());
1368     }
1369
1370     void observeUseKindOnNode(Node* node, UseKind useKind)
1371     {
1372         if (node->op() != GetLocal)
1373             return;
1374         
1375         // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
1376         // https://bugs.webkit.org/show_bug.cgi?id=121518
1377         
1378         VariableAccessData* variable = node->variableAccessData();
1379         switch (useKind) {
1380         case Int32Use:
1381             if (alwaysUnboxSimplePrimitives()
1382                 || isInt32Speculation(variable->prediction()))
1383                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1384             break;
1385         case NumberUse:
1386         case RealNumberUse:
1387             if (variable->doubleFormatState() == UsingDoubleFormat)
1388                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1389             break;
1390         case BooleanUse:
1391             if (alwaysUnboxSimplePrimitives()
1392                 || isBooleanSpeculation(variable->prediction()))
1393                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1394             break;
1395         case MachineIntUse:
1396             if (isMachineIntSpeculation(variable->prediction()))
1397                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1398             break;
1399         case CellUse:
1400         case KnownCellUse:
1401         case ObjectUse:
1402         case StringUse:
1403         case KnownStringUse:
1404         case StringObjectUse:
1405         case StringOrStringObjectUse:
1406             if (alwaysUnboxSimplePrimitives()
1407                 || isCellSpeculation(variable->prediction()))
1408                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1409             break;
1410         default:
1411             break;
1412         }
1413     }
1414     
1415     // Set the use kind of the edge and perform any actions that need to be done for
1416     // that use kind, like inserting intermediate conversion nodes. Never call this
1417     // with useKind = UntypedUse explicitly; edges have UntypedUse implicitly and any
1418     // edge that survives fixup and still has UntypedUse will have this method called
1419     // from observeUntypedEdge(). Also, make sure that if you do change the type of an
1420     // edge, you either call fixEdge() or perform the equivalent functionality
1421     // yourself. Obviously, you should have a really good reason if you do the latter.
1422     template<UseKind useKind>
1423     void fixEdge(Edge& edge)
1424     {
1425         if (isDouble(useKind)) {
1426             if (edge->shouldSpeculateInt32ForArithmetic()) {
1427                 injectInt32ToDoubleNode(edge, useKind, m_currentNode->speculationDirection());
1428                 return;
1429             }
1430             
1431             if (enableInt52() && edge->shouldSpeculateMachineInt()) {
1432                 // Make all double uses of int52 values have an intermediate Int52ToDouble.
1433                 // This is for the same reason as Int52ToValue (see below) except that
1434                 // Int8ToDouble will convert int52's that fit in an int32 into a double
1435                 // rather than trying to create a boxed int32 like Int52ToValue does.
1436                 
1437                 Node* result = m_insertionSet.insertNode(
1438                     m_indexInBlock, SpecInt52AsDouble, Int52ToDouble,
1439                     m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
1440                 result->setSpeculationDirection(m_currentNode->speculationDirection());
1441                 edge = Edge(result, useKind);
1442                 return;
1443             }
1444         }
1445         
1446         if (enableInt52() && useKind != MachineIntUse
1447             && edge->shouldSpeculateMachineInt() && !edge->shouldSpeculateInt32()) {
1448             // We make all non-int52 uses of int52 values have an intermediate Int52ToValue
1449             // node to ensure that we handle this properly:
1450             //
1451             // a: SomeInt52
1452             // b: ArithAdd(@a, ...)
1453             // c: Call(..., @a)
1454             // d: ArithAdd(@a, ...)
1455             //
1456             // Without an intermediate node and just labeling the uses, we will get:
1457             //
1458             // a: SomeInt52
1459             // b: ArithAdd(Int52:@a, ...)
1460             // c: Call(..., Untyped:@a)
1461             // d: ArithAdd(Int52:@a, ...)
1462             //
1463             // And now the c->Untyped:@a edge will box the value of @a into a double. This
1464             // is bad, because now the d->Int52:@a edge will either have to do double-to-int
1465             // conversions, or will have to OSR exit unconditionally. Alternatively we could
1466             // have the c->Untyped:@a edge box the value by copying rather than in-place.
1467             // But these boxings are also costly so this wouldn't be great.
1468             //
1469             // The solution we use is to always have non-Int52 uses of predicted Int52's use
1470             // an intervening Int52ToValue node:
1471             //
1472             // a: SomeInt52
1473             // b: ArithAdd(Int52:@a, ...)
1474             // x: Int52ToValue(Int52:@a)
1475             // c: Call(..., Untyped:@x)
1476             // d: ArithAdd(Int52:@a, ...)
1477             //
1478             // Note that even if we had multiple non-int52 uses of @a, the multiple
1479             // Int52ToValue's would get CSE'd together. So the boxing would only happen once.
1480             // At the same time, @a would continue to be represented as a native int52.
1481             //
1482             // An alternative would have been to insert ToNativeInt52 nodes on int52 uses of
1483             // int52's. This would have handled the above example but would fall over for:
1484             //
1485             // a: SomeInt52
1486             // b: Call(..., @a)
1487             // c: ArithAdd(@a, ...)
1488             //
1489             // But the solution we use handles the above gracefully.
1490             
1491             Node* result = m_insertionSet.insertNode(
1492                 m_indexInBlock, SpecInt52, Int52ToValue,
1493                 m_currentNode->codeOrigin, Edge(edge.node(), UntypedUse));
1494             result->setSpeculationDirection(m_currentNode->speculationDirection());
1495             edge = Edge(result, useKind);
1496             return;
1497         }
1498         
1499         observeUseKindOnNode<useKind>(edge.node());
1500         
1501         edge.setUseKind(useKind);
1502     }
1503     
1504     void fixIntEdge(Edge& edge)
1505     {
1506         Node* node = edge.node();
1507         if (node->op() != ValueToInt32) {
1508             fixEdge<KnownInt32Use>(edge);
1509             return;
1510         }
1511         
1512         Edge newEdge = node->child1();
1513         
1514         if (newEdge.useKind() != Int32Use) {
1515             edge.setUseKind(KnownInt32Use);
1516             return;
1517         }
1518         
1519         ASSERT(newEdge->shouldSpeculateInt32());
1520         edge = newEdge;
1521     }
1522     
1523     void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
1524     {
1525         Node* result = m_insertionSet.insertNode(
1526             m_indexInBlock, SpecInt52AsDouble, Int32ToDouble,
1527             m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
1528         if (direction == ForwardSpeculation)
1529             result->mergeFlags(NodeExitsForward);
1530         
1531         edge = Edge(result, useKind);
1532     }
1533     
1534     void truncateConstantToInt32(Edge& edge)
1535     {
1536         Node* oldNode = edge.node();
1537         
1538         ASSERT(oldNode->hasConstant());
1539         JSValue value = m_graph.valueOfJSConstant(oldNode);
1540         if (value.isInt32())
1541             return;
1542         
1543         value = jsNumber(JSC::toInt32(value.asNumber()));
1544         ASSERT(value.isInt32());
1545         unsigned constantRegister;
1546         if (!codeBlock()->findConstant(value, constantRegister)) {
1547             constantRegister = codeBlock()->addConstantLazily();
1548             initializeLazyWriteBarrierForConstant(
1549                 m_graph.m_plan.writeBarriers,
1550                 codeBlock()->constants()[constantRegister],
1551                 codeBlock(),
1552                 constantRegister,
1553                 codeBlock()->ownerExecutable(),
1554                 value);
1555         }
1556         edge.setNode(m_insertionSet.insertNode(
1557             m_indexInBlock, SpecInt32, JSConstant, m_currentNode->codeOrigin,
1558             OpInfo(constantRegister)));
1559     }
1560     
1561     void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1562     {
1563         if (mode != SpeculateInt32AndTruncateConstants)
1564             return;
1565         
1566         ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1567         if (node->child1()->hasConstant())
1568             truncateConstantToInt32(node->child1());
1569         else
1570             truncateConstantToInt32(node->child2());
1571     }
1572     
1573     bool attemptToMakeIntegerAdd(Node* node)
1574     {
1575         AddSpeculationMode mode = m_graph.addSpeculationMode(node);
1576         if (mode != DontSpeculateInt32) {
1577             truncateConstantsIfNecessary(node, mode);
1578             fixEdge<Int32Use>(node->child1());
1579             fixEdge<Int32Use>(node->child2());
1580             return true;
1581         }
1582         
1583         if (m_graph.addShouldSpeculateMachineInt(node)) {
1584             fixEdge<MachineIntUse>(node->child1());
1585             fixEdge<MachineIntUse>(node->child2());
1586             return true;
1587         }
1588         
1589         return false;
1590     }
1591     
1592     bool attemptToMakeGetArrayLength(Node* node)
1593     {
1594         if (!isInt32Speculation(node->prediction()))
1595             return false;
1596         CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->codeOrigin);
1597         ArrayProfile* arrayProfile = 
1598             profiledBlock->getArrayProfile(node->codeOrigin.bytecodeIndex);
1599         ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
1600         if (arrayProfile) {
1601             ConcurrentJITLocker locker(profiledBlock->m_lock);
1602             arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
1603             arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
1604             if (arrayMode.type() == Array::Unprofiled) {
1605                 // For normal array operations, it makes sense to treat Unprofiled
1606                 // accesses as ForceExit and get more data rather than using
1607                 // predictions and then possibly ending up with a Generic. But here,
1608                 // we treat anything that is Unprofiled as Generic and keep the
1609                 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
1610                 // profit - from treating the Unprofiled case as
1611                 // SelectUsingPredictions.
1612                 arrayMode = ArrayMode(Array::SelectUsingPredictions);
1613             }
1614         }
1615             
1616         arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
1617             
1618         if (arrayMode.type() == Array::Generic) {
1619             // Check if the input is something that we can't get array length for, but for which we
1620             // could insert some conversions in order to transform it into something that we can do it
1621             // for.
1622             if (node->child1()->shouldSpeculateStringObject())
1623                 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
1624             else if (node->child1()->shouldSpeculateStringOrStringObject())
1625                 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
1626         }
1627             
1628         if (!arrayMode.supportsLength())
1629             return false;
1630         
1631         convertToGetArrayLength(node, arrayMode);
1632         return true;
1633     }
1634     
1635     bool attemptToMakeGetTypedArrayByteLength(Node* node)
1636     {
1637         if (!isInt32Speculation(node->prediction()))
1638             return false;
1639         
1640         TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1641         if (!isTypedView(type))
1642             return false;
1643         
1644         if (elementSize(type) == 1) {
1645             convertToGetArrayLength(node, ArrayMode(toArrayType(type)));
1646             return true;
1647         }
1648         
1649         Node* length = prependGetArrayLength(
1650             node->codeOrigin, node->child1().node(), ArrayMode(toArrayType(type)));
1651         
1652         Node* shiftAmount = m_insertionSet.insertNode(
1653             m_indexInBlock, SpecInt32, JSConstant, node->codeOrigin,
1654             OpInfo(m_graph.constantRegisterForConstant(jsNumber(logElementSize(type)))));
1655         
1656         // We can use a BitLShift here because typed arrays will never have a byteLength
1657         // that overflows int32.
1658         node->setOp(BitLShift);
1659         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1660         observeUseKindOnNode(length, Int32Use);
1661         observeUseKindOnNode(shiftAmount, Int32Use);
1662         node->child1() = Edge(length, Int32Use);
1663         node->child2() = Edge(shiftAmount, Int32Use);
1664         return true;
1665     }
1666     
1667     void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
1668     {
1669         node->setOp(GetArrayLength);
1670         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1671         fixEdge<KnownCellUse>(node->child1());
1672         node->setArrayMode(arrayMode);
1673             
1674         Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage);
1675         if (!storage)
1676             return;
1677             
1678         node->child2() = Edge(storage);
1679     }
1680     
1681     Node* prependGetArrayLength(CodeOrigin codeOrigin, Node* child, ArrayMode arrayMode)
1682     {
1683         Node* storage = checkArray(arrayMode, codeOrigin, child, 0, lengthNeedsStorage);
1684         return m_insertionSet.insertNode(
1685             m_indexInBlock, SpecInt32, GetArrayLength, codeOrigin,
1686             OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
1687     }
1688     
1689     bool attemptToMakeGetTypedArrayByteOffset(Node* node)
1690     {
1691         if (!isInt32Speculation(node->prediction()))
1692             return false;
1693         
1694         TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1695         if (!isTypedView(type))
1696             return false;
1697         
1698         checkArray(
1699             ArrayMode(toArrayType(type)), node->codeOrigin, node->child1().node(),
1700             0, neverNeedsStorage);
1701         
1702         node->setOp(GetTypedArrayByteOffset);
1703         node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1704         fixEdge<KnownCellUse>(node->child1());
1705         return true;
1706     }
1707
1708     BasicBlock* m_block;
1709     unsigned m_indexInBlock;
1710     Node* m_currentNode;
1711     InsertionSet m_insertionSet;
1712     bool m_profitabilityChanged;
1713 };
1714     
1715 bool performFixup(Graph& graph)
1716 {
1717     SamplingRegion samplingRegion("DFG Fixup Phase");
1718     return runPhase<FixupPhase>(graph);
1719 }
1720
1721 } } // namespace JSC::DFG
1722
1723 #endif // ENABLE(DFG_JIT)
1724