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