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