eef51f29c0f2a02c8c298bd5efbf7f2520448ea3
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLLowerDFGToLLVM.cpp
1 /*
2  * Copyright (C) 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 "FTLLowerDFGToLLVM.h"
28
29 #if ENABLE(FTL_JIT)
30
31 #include "CodeBlockWithJITType.h"
32 #include "DFGAbstractInterpreterInlines.h"
33 #include "DFGInPlaceAbstractState.h"
34 #include "FTLAbstractHeapRepository.h"
35 #include "FTLExitThunkGenerator.h"
36 #include "FTLForOSREntryJITCode.h"
37 #include "FTLFormattedValue.h"
38 #include "FTLLoweredNodeValue.h"
39 #include "FTLOutput.h"
40 #include "FTLThunks.h"
41 #include "FTLValueSource.h"
42 #include "LinkBuffer.h"
43 #include "OperandsInlines.h"
44 #include "Operations.h"
45 #include <wtf/ProcessID.h>
46
47 namespace JSC { namespace FTL {
48
49 using namespace DFG;
50
51 static int compileCounter;
52
53 // Using this instead of typeCheck() helps to reduce the load on LLVM, by creating
54 // significantly less dead code.
55 #define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) do { \
56         FormattedValue _ftc_lowValue = (lowValue);                      \
57         Edge _ftc_highValue = (highValue);                              \
58         SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough);  \
59         if (!m_interpreter.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \
60             break;                                                      \
61         typeCheck(_ftc_lowValue, _ftc_highValue, _ftc_typesPassedThrough, (failCondition)); \
62     } while (false)
63
64 class LowerDFGToLLVM {
65 public:
66     LowerDFGToLLVM(State& state)
67         : m_graph(state.graph)
68         , m_ftlState(state)
69         , m_heaps(state.context)
70         , m_out(state.context)
71         , m_valueSources(OperandsLike, state.graph.block(0)->variablesAtHead)
72         , m_lastSetOperand(std::numeric_limits<int>::max())
73         , m_exitThunkGenerator(state)
74         , m_state(state.graph)
75         , m_interpreter(state.graph, m_state)
76     {
77     }
78     
79     void lower()
80     {
81         CString name;
82         if (verboseCompilationEnabled()) {
83             name = toCString(
84                 "jsBody_", atomicIncrement(&compileCounter), "_", codeBlock()->inferredName(),
85                 "_", codeBlock()->hash());
86         } else
87             name = "jsBody";
88         
89         m_graph.m_dominators.computeIfNecessary(m_graph);
90         
91         m_ftlState.module =
92             LLVMModuleCreateWithNameInContext(name.data(), m_ftlState.context);
93         
94         m_ftlState.function = addFunction(
95             m_ftlState.module, name.data(), functionType(m_out.int64, m_out.intPtr));
96         setFunctionCallingConv(m_ftlState.function, LLVMCCallConv);
97         
98         m_out.initialize(m_ftlState.module, m_ftlState.function, m_heaps);
99         
100         m_prologue = appendBasicBlock(m_ftlState.context, m_ftlState.function);
101         m_out.appendTo(m_prologue);
102         createPhiVariables();
103         
104         m_initialization = appendBasicBlock(m_ftlState.context, m_ftlState.function);
105
106         m_callFrame = m_out.param(0);
107         m_tagTypeNumber = m_out.constInt64(TagTypeNumber);
108         m_tagMask = m_out.constInt64(TagMask);
109         
110         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
111             m_highBlock = m_graph.block(blockIndex);
112             if (!m_highBlock)
113                 continue;
114             m_blocks.add(m_highBlock, FTL_NEW_BLOCK(m_out, ("Block ", *m_highBlock)));
115         }
116         
117         Vector<BasicBlock*> depthFirst;
118         m_graph.getBlocksInDepthFirstOrder(depthFirst);
119         for (unsigned i = 0; i < depthFirst.size(); ++i)
120             compileBlock(depthFirst[i]);
121         
122         // And now complete the initialization block.
123         linkOSRExitsAndCompleteInitializationBlocks();
124
125         if (Options::dumpLLVMIR())
126             dumpModule(m_ftlState.module);
127         
128         if (verboseCompilationEnabled())
129             m_ftlState.dumpState("after lowering");
130         if (validationEnabled())
131             verifyModule(m_ftlState.module);
132     }
133
134 private:
135     
136     void createPhiVariables()
137     {
138         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
139             BasicBlock* block = m_graph.block(blockIndex);
140             if (!block)
141                 continue;
142             for (unsigned nodeIndex = block->size(); nodeIndex--;) {
143                 Node* node = block->at(nodeIndex);
144                 if (node->op() != Phi)
145                     continue;
146                 LType type;
147                 switch (node->flags() & NodeResultMask) {
148                 case NodeResultNumber:
149                     type = m_out.doubleType;
150                     break;
151                 case NodeResultInt32:
152                     type = m_out.int32;
153                     break;
154                 case NodeResultBoolean:
155                     type = m_out.boolean;
156                     break;
157                 case NodeResultJS:
158                     type = m_out.int64;
159                     break;
160                 default:
161                     RELEASE_ASSERT_NOT_REACHED();
162                     break;
163                 }
164                 m_phis.add(node, buildAlloca(m_out.m_builder, type));
165             }
166         }
167     }
168     
169     void compileBlock(BasicBlock* block)
170     {
171         if (!block)
172             return;
173         
174         if (verboseCompilationEnabled())
175             dataLog("Compiling block ", *block, "\n");
176         
177         m_highBlock = block;
178         
179         LBasicBlock lowBlock = m_blocks.get(m_highBlock);
180         
181         m_nextHighBlock = 0;
182         for (BlockIndex nextBlockIndex = m_highBlock->index + 1; nextBlockIndex < m_graph.numBlocks(); ++nextBlockIndex) {
183             m_nextHighBlock = m_graph.block(nextBlockIndex);
184             if (m_nextHighBlock)
185                 break;
186         }
187         m_nextLowBlock = m_nextHighBlock ? m_blocks.get(m_nextHighBlock) : 0;
188         
189         // All of this effort to find the next block gives us the ability to keep the
190         // generated IR in roughly program order. This ought not affect the performance
191         // of the generated code (since we expect LLVM to reorder things) but it will
192         // make IR dumps easier to read.
193         m_out.appendTo(lowBlock, m_nextLowBlock);
194         
195         if (Options::ftlCrashes())
196             m_out.crashNonTerminal();
197         
198         if (!m_highBlock->cfaHasVisited) {
199             m_out.crash();
200             return;
201         }
202         
203         initializeOSRExitStateForBlock();
204         
205         m_live = block->ssa->liveAtHead;
206         
207         m_state.reset();
208         m_state.beginBasicBlock(m_highBlock);
209         
210         for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) {
211             if (!compileNode(m_nodeIndex))
212                 break;
213         }
214     }
215     
216     bool compileNode(unsigned nodeIndex)
217     {
218         if (!m_state.isValid()) {
219             m_out.unreachable();
220             return false;
221         }
222         
223         m_node = m_highBlock->at(nodeIndex);
224         m_codeOriginForExitProfile = m_node->codeOrigin;
225         m_codeOriginForExitTarget = m_node->codeOriginForExitTarget;
226         
227         if (verboseCompilationEnabled())
228             dataLog("Lowering ", m_node, "\n");
229         
230         bool shouldExecuteEffects = m_interpreter.startExecuting(m_node);
231         
232         m_direction = (m_node->flags() & NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation;
233         
234         switch (m_node->op()) {
235         case Upsilon:
236             compileUpsilon();
237             break;
238         case Phi:
239             compilePhi();
240             break;
241         case JSConstant:
242             compileJSConstant();
243             break;
244         case WeakJSConstant:
245             compileWeakJSConstant();
246             break;
247         case GetArgument:
248             compileGetArgument();
249             break;
250         case ExtractOSREntryLocal:
251             compileExtractOSREntryLocal();
252             break;
253         case GetLocal:
254             compileGetLocal();
255             break;
256         case SetLocal:
257             compileSetLocal();
258             break;
259         case MovHint:
260             compileMovHint();
261             break;
262         case ZombieHint:
263             compileZombieHint();
264             break;
265         case MovHintAndCheck:
266             compileMovHintAndCheck();
267             break;
268         case Phantom:
269             compilePhantom();
270             break;
271         case Flush:
272         case PhantomLocal:
273         case SetArgument:
274         case LoopHint:
275             break;
276         case ArithAdd:
277         case ValueAdd:
278             compileAdd();
279             break;
280         case ArithSub:
281             compileArithSub();
282             break;
283         case ArithMul:
284             compileArithMul();
285             break;
286         case ArithDiv:
287             compileArithDiv();
288             break;
289         case ArithMod:
290             compileArithMod();
291             break;
292         case ArithMin:
293         case ArithMax:
294             compileArithMinOrMax();
295             break;
296         case ArithAbs:
297             compileArithAbs();
298             break;
299         case ArithNegate:
300             compileArithNegate();
301             break;
302         case BitAnd:
303             compileBitAnd();
304             break;
305         case BitOr:
306             compileBitOr();
307             break;
308         case BitXor:
309             compileBitXor();
310             break;
311         case BitRShift:
312             compileBitRShift();
313             break;
314         case BitLShift:
315             compileBitLShift();
316             break;
317         case BitURShift:
318             compileBitURShift();
319             break;
320         case UInt32ToNumber:
321             compileUInt32ToNumber();
322             break;
323         case Int32ToDouble:
324             compileInt32ToDouble();
325             break;
326         case CheckStructure:
327             compileCheckStructure();
328             break;
329         case StructureTransitionWatchpoint:
330             compileStructureTransitionWatchpoint();
331             break;
332         case ArrayifyToStructure:
333             compileArrayifyToStructure();
334             break;
335         case PutStructure:
336             compilePutStructure();
337             break;
338         case PhantomPutStructure:
339             compilePhantomPutStructure();
340             break;
341         case GetButterfly:
342             compileGetButterfly();
343             break;
344         case GetArrayLength:
345             compileGetArrayLength();
346             break;
347         case GetByVal:
348             compileGetByVal();
349             break;
350         case PutByVal:
351         case PutByValAlias:
352             compilePutByVal();
353             break;
354         case GetByOffset:
355             compileGetByOffset();
356             break;
357         case PutByOffset:
358             compilePutByOffset();
359             break;
360         case GetGlobalVar:
361             compileGetGlobalVar();
362             break;
363         case PutGlobalVar:
364             compilePutGlobalVar();
365             break;
366         case CompareEq:
367             compileCompareEq();
368             break;
369         case CompareEqConstant:
370             compileCompareEqConstant();
371             break;
372         case CompareStrictEq:
373             compileCompareStrictEq();
374             break;
375         case CompareStrictEqConstant:
376             compileCompareStrictEqConstant();
377             break;
378         case CompareLess:
379             compileCompareLess();
380             break;
381         case CompareLessEq:
382             compileCompareLessEq();
383             break;
384         case CompareGreater:
385             compileCompareGreater();
386             break;
387         case CompareGreaterEq:
388             compileCompareGreaterEq();
389             break;
390         case LogicalNot:
391             compileLogicalNot();
392             break;
393         case Jump:
394             compileJump();
395             break;
396         case Branch:
397             compileBranch();
398             break;
399         case Switch:
400             compileSwitch();
401             break;
402         case Return:
403             compileReturn();
404             break;
405         case ForceOSRExit:
406             compileForceOSRExit();
407             break;
408         default:
409             RELEASE_ASSERT_NOT_REACHED();
410             break;
411         }
412         
413         if (m_node->shouldGenerate())
414             DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, use);
415         
416         if (m_node->adjustedRefCount())
417             m_live.add(m_node);
418         
419         if (shouldExecuteEffects)
420             m_interpreter.executeEffects(nodeIndex);
421         
422         return true;
423     }
424     
425     void compileUpsilon()
426     {
427         LValue destination = m_phis.get(m_node->phi());
428         
429         switch (m_node->child1().useKind()) {
430         case NumberUse:
431             m_out.set(lowDouble(m_node->child1()), destination);
432             break;
433         case Int32Use:
434             m_out.set(lowInt32(m_node->child1()), destination);
435             break;
436         case BooleanUse:
437             m_out.set(lowBoolean(m_node->child1()), destination);
438             break;
439         case CellUse:
440             m_out.set(lowCell(m_node->child1()), destination);
441             break;
442         case UntypedUse:
443             m_out.set(lowJSValue(m_node->child1()), destination);
444             break;
445         default:
446             RELEASE_ASSERT_NOT_REACHED();
447             break;
448         }
449     }
450     
451     void compilePhi()
452     {
453         LValue source = m_phis.get(m_node);
454         
455         switch (m_node->flags() & NodeResultMask) {
456         case NodeResultNumber:
457             setDouble(m_out.get(source));
458             break;
459         case NodeResultInt32:
460             setInt32(m_out.get(source));
461             break;
462         case NodeResultBoolean:
463             setBoolean(m_out.get(source));
464             break;
465         case NodeResultJS:
466             setJSValue(m_out.get(source));
467             break;
468         default:
469             RELEASE_ASSERT_NOT_REACHED();
470             break;
471         }
472     }
473     
474     void compileJSConstant()
475     {
476         JSValue value = m_graph.valueOfJSConstant(m_node);
477         if (value.isDouble())
478             setDouble(m_out.constDouble(value.asDouble()));
479         else
480             setJSValue(m_out.constInt64(JSValue::encode(value)));
481     }
482     
483     void compileWeakJSConstant()
484     {
485         setJSValue(weakPointer(m_node->weakConstant()));
486     }
487     
488     void compileGetArgument()
489     {
490         VariableAccessData* variable = m_node->variableAccessData();
491         int operand = variable->operand();
492
493         LValue jsValue = m_out.load64(addressFor(operand));
494
495         switch (useKindFor(variable->flushFormat())) {
496         case Int32Use:
497             speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotInt32(jsValue));
498             setInt32(unboxInt32(jsValue));
499             break;
500         case CellUse:
501             speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotCell(jsValue));
502             setJSValue(jsValue);
503             break;
504         case BooleanUse:
505             speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotBoolean(jsValue));
506             setBoolean(unboxBoolean(jsValue));
507             break;
508         case UntypedUse:
509             setJSValue(jsValue);
510             break;
511         default:
512             RELEASE_ASSERT_NOT_REACHED();
513             break;
514         }
515     }
516     
517     void compileExtractOSREntryLocal()
518     {
519         EncodedJSValue* buffer = static_cast<EncodedJSValue*>(
520             m_ftlState.jitCode->ftlForOSREntry()->entryBuffer()->dataBuffer());
521         setJSValue(m_out.load64(m_out.absolute(buffer + m_node->unlinkedLocal())));
522     }
523     
524     void compileGetLocal()
525     {
526         // GetLocals arise only for captured variables.
527         
528         VariableAccessData* variable = m_node->variableAccessData();
529         AbstractValue& value = m_state.variables().operand(variable->local());
530         
531         RELEASE_ASSERT(variable->isCaptured());
532         
533         if (isInt32Speculation(value.m_type))
534             setInt32(m_out.load32(payloadFor(variable->local())));
535         else
536             setJSValue(m_out.load64(addressFor(variable->local())));
537     }
538     
539     void compileSetLocal()
540     {
541         observeMovHint(m_node);
542         
543         VariableAccessData* variable = m_node->variableAccessData();
544         SpeculatedType prediction = variable->argumentAwarePrediction();
545         
546         if (variable->shouldUnboxIfPossible()) {
547             if (variable->shouldUseDoubleFormat()) {
548                 LValue value = lowDouble(m_node->child1());
549                 m_out.storeDouble(value, addressFor(variable->local()));
550                 m_valueSources.operand(variable->local()) = ValueSource(DoubleInJSStack);
551                 return;
552             }
553             
554             if (isInt32Speculation(prediction)) {
555                 LValue value = lowInt32(m_node->child1());
556                 m_out.store32(value, payloadFor(variable->local()));
557                 m_valueSources.operand(variable->local()) = ValueSource(Int32InJSStack);
558                 return;
559             }
560             if (isCellSpeculation(prediction)) {
561                 LValue value = lowCell(m_node->child1());
562                 m_out.store64(value, addressFor(variable->local()));
563                 m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack);
564                 return;
565             }
566             if (isBooleanSpeculation(prediction)) {
567                 speculateBoolean(m_node->child1());
568                 m_out.store64(
569                     lowJSValue(m_node->child1(), ManualOperandSpeculation),
570                     addressFor(variable->local()));
571                 m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack);
572                 return;
573             }
574         }
575         
576         LValue value = lowJSValue(m_node->child1());
577         m_out.store64(value, addressFor(variable->local()));
578         m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack);
579     }
580     
581     void compileMovHint()
582     {
583         observeMovHint(m_node);
584     }
585     
586     void compileZombieHint()
587     {
588         VariableAccessData* data = m_node->variableAccessData();
589         m_lastSetOperand = data->local();
590         m_valueSources.operand(data->local()) = ValueSource(SourceIsDead);
591     }
592     
593     void compileMovHintAndCheck()
594     {
595         observeMovHint(m_node);
596         speculate(m_node->child1());
597     }
598     
599     void compilePhantom()
600     {
601         DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
602     }
603     
604     void compileAdd()
605     {
606         switch (m_node->binaryUseKind()) {
607         case Int32Use: {
608             LValue left = lowInt32(m_node->child1());
609             LValue right = lowInt32(m_node->child2());
610             
611             if (nodeCanTruncateInteger(m_node->arithNodeFlags())) {
612                 setInt32(m_out.add(left, right));
613                 break;
614             }
615             
616             LValue result = m_out.addWithOverflow32(left, right);
617             speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1));
618             setInt32(m_out.extractValue(result, 0));
619             break;
620         }
621             
622         case NumberUse: {
623             setDouble(
624                 m_out.doubleAdd(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
625             break;
626         }
627             
628         default:
629             RELEASE_ASSERT_NOT_REACHED();
630             break;
631         }
632     }
633     
634     void compileArithSub()
635     {
636         switch (m_node->binaryUseKind()) {
637         case Int32Use: {
638             LValue left = lowInt32(m_node->child1());
639             LValue right = lowInt32(m_node->child2());
640             
641             if (nodeCanTruncateInteger(m_node->arithNodeFlags())) {
642                 setInt32(m_out.sub(left, right));
643                 break;
644             }
645             
646             LValue result = m_out.subWithOverflow32(left, right);
647             speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1));
648             setInt32(m_out.extractValue(result, 0));
649             break;
650         }
651             
652         case NumberUse: {
653             setDouble(
654                 m_out.doubleSub(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
655             break;
656         }
657             
658         default:
659             RELEASE_ASSERT_NOT_REACHED();
660             break;
661         }
662     }
663     
664     void compileArithMul()
665     {
666         switch (m_node->binaryUseKind()) {
667         case Int32Use: {
668             LValue left = lowInt32(m_node->child1());
669             LValue right = lowInt32(m_node->child2());
670             
671             LValue result;
672             if (nodeCanTruncateInteger(m_node->arithNodeFlags()))
673                 result = m_out.mul(left, right);
674             else {
675                 LValue overflowResult = m_out.mulWithOverflow32(left, right);
676                 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
677                 result = m_out.extractValue(overflowResult, 0);
678             }
679             
680             if (!nodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
681                 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
682                 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
683                 
684                 m_out.branch(m_out.notZero32(result), continuation, slowCase);
685                 
686                 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
687                 speculate(NegativeZero, noValue(), 0, m_out.lessThan(left, m_out.int32Zero));
688                 speculate(NegativeZero, noValue(), 0, m_out.lessThan(right, m_out.int32Zero));
689                 m_out.jump(continuation);
690                 m_out.appendTo(continuation, lastNext);
691             }
692             
693             setInt32(result);
694             break;
695         }
696             
697         case NumberUse: {
698             setDouble(
699                 m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
700             break;
701         }
702             
703         default:
704             RELEASE_ASSERT_NOT_REACHED();
705             break;
706         }
707     }
708     
709     void compileArithDiv()
710     {
711         switch (m_node->binaryUseKind()) {
712         case Int32Use: {
713             LValue numerator = lowInt32(m_node->child1());
714             LValue denominator = lowInt32(m_node->child2());
715             
716             LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDiv unsafe denominator"));
717             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDiv continuation"));
718             LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDiv done"));
719             
720             Vector<ValueFromBlock, 3> results;
721             
722             LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
723             
724             m_out.branch(m_out.above(adjustedDenominator, m_out.int32One), continuation, unsafeDenominator);
725             
726             LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
727             
728             LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
729             
730             if (nodeUsedAsNumber(m_node->arithNodeFlags())) {
731                 speculate(Overflow, noValue(), 0, m_out.isZero32(denominator));
732                 speculate(Overflow, noValue(), 0, m_out.equal(numerator, neg2ToThe31));
733                 m_out.jump(continuation);
734             } else {
735                 // This is the case where we convert the result to an int after we're done. So,
736                 // if the denominator is zero, then the result should be result should be zero.
737                 // If the denominator is not zero (i.e. it's -1 because we're guarded by the
738                 // check above) and the numerator is -2^31 then the result should be -2^31.
739                 
740                 LBasicBlock divByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv divide by zero"));
741                 LBasicBlock notDivByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv not divide by zero"));
742                 LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithDiv -2^31/-1"));
743                 
744                 m_out.branch(m_out.isZero32(denominator), divByZero, notDivByZero);
745                 
746                 m_out.appendTo(divByZero, notDivByZero);
747                 results.append(m_out.anchor(m_out.int32Zero));
748                 m_out.jump(done);
749                 
750                 m_out.appendTo(notDivByZero, neg2ToThe31ByNeg1);
751                 m_out.branch(m_out.equal(numerator, neg2ToThe31), neg2ToThe31ByNeg1, continuation);
752                 
753                 m_out.appendTo(neg2ToThe31ByNeg1, continuation);
754                 results.append(m_out.anchor(neg2ToThe31));
755                 m_out.jump(done);
756             }
757             
758             m_out.appendTo(continuation, done);
759             
760             if (!nodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
761                 LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDiv zero numerator"));
762                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDiv numerator continuation"));
763                 
764                 m_out.branch(m_out.isZero32(numerator), zeroNumerator, numeratorContinuation);
765                 
766                 LBasicBlock innerLastNext = m_out.appendTo(zeroNumerator, numeratorContinuation);
767                 
768                 speculate(
769                     NegativeZero, noValue(), 0, m_out.lessThan(denominator, m_out.int32Zero));
770                 
771                 m_out.jump(numeratorContinuation);
772                 
773                 m_out.appendTo(numeratorContinuation, innerLastNext);
774             }
775             
776             LValue divisionResult = m_out.div(numerator, denominator);
777             
778             if (nodeUsedAsNumber(m_node->arithNodeFlags())) {
779                 speculate(
780                     Overflow, noValue(), 0,
781                     m_out.notEqual(m_out.mul(divisionResult, denominator), numerator));
782             }
783             
784             results.append(m_out.anchor(divisionResult));
785             m_out.jump(done);
786             
787             m_out.appendTo(done, lastNext);
788             
789             setInt32(m_out.phi(m_out.int32, results));
790             break;
791         }
792             
793         case NumberUse: {
794             setDouble(
795                 m_out.doubleDiv(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
796             break;
797         }
798             
799         default:
800             RELEASE_ASSERT_NOT_REACHED();
801             break;
802         }
803     }
804     
805     void compileArithMod()
806     {
807         switch (m_node->binaryUseKind()) {
808         case Int32Use: {
809             LValue numerator = lowInt32(m_node->child1());
810             LValue denominator = lowInt32(m_node->child2());
811             
812             LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator"));
813             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation"));
814             LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithMod done"));
815             
816             Vector<ValueFromBlock, 3> results;
817             
818             LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
819             
820             m_out.branch(m_out.above(adjustedDenominator, m_out.int32One), continuation, unsafeDenominator);
821             
822             LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
823             
824             LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
825             
826             // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a
827             // separate case for that. But it probably doesn't matter so much.
828             if (nodeUsedAsNumber(m_node->arithNodeFlags())) {
829                 speculate(Overflow, noValue(), 0, m_out.isZero32(denominator));
830                 speculate(Overflow, noValue(), 0, m_out.equal(numerator, neg2ToThe31));
831                 m_out.jump(continuation);
832             } else {
833                 // This is the case where we convert the result to an int after we're done. So,
834                 // if the denominator is zero, then the result should be result should be zero.
835                 // If the denominator is not zero (i.e. it's -1 because we're guarded by the
836                 // check above) and the numerator is -2^31 then the result should be -2^31.
837                 
838                 LBasicBlock modByZero = FTL_NEW_BLOCK(m_out, ("ArithMod modulo by zero"));
839                 LBasicBlock notModByZero = FTL_NEW_BLOCK(m_out, ("ArithMod not modulo by zero"));
840                 LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithMod -2^31/-1"));
841                 
842                 m_out.branch(m_out.isZero32(denominator), modByZero, notModByZero);
843                 
844                 m_out.appendTo(modByZero, notModByZero);
845                 results.append(m_out.anchor(m_out.int32Zero));
846                 m_out.jump(done);
847                 
848                 m_out.appendTo(notModByZero, neg2ToThe31ByNeg1);
849                 m_out.branch(m_out.equal(numerator, neg2ToThe31), neg2ToThe31ByNeg1, continuation);
850                 
851                 m_out.appendTo(neg2ToThe31ByNeg1, continuation);
852                 results.append(m_out.anchor(m_out.int32Zero));
853                 m_out.jump(done);
854             }
855             
856             m_out.appendTo(continuation, done);
857             
858             if (!nodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
859                 LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod zero numerator"));
860                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation"));
861                 
862                 m_out.branch(m_out.isZero32(numerator), zeroNumerator, numeratorContinuation);
863                 
864                 LBasicBlock innerLastNext = m_out.appendTo(zeroNumerator, numeratorContinuation);
865                 
866                 speculate(
867                     NegativeZero, noValue(), 0, m_out.lessThan(denominator, m_out.int32Zero));
868                 
869                 m_out.jump(numeratorContinuation);
870                 
871                 m_out.appendTo(numeratorContinuation, innerLastNext);
872             }
873             
874             results.append(m_out.anchor(m_out.rem(numerator, denominator)));
875             m_out.jump(done);
876             
877             m_out.appendTo(done, lastNext);
878             
879             setInt32(m_out.phi(m_out.int32, results));
880             break;
881         }
882             
883         case NumberUse: {
884             setDouble(
885                 m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
886             break;
887         }
888             
889         default:
890             RELEASE_ASSERT_NOT_REACHED();
891             break;
892         }
893     }
894
895     void compileArithMinOrMax()
896     {
897         switch (m_node->binaryUseKind()) {
898         case Int32Use: {
899             LValue left = lowInt32(m_node->child1());
900             LValue right = lowInt32(m_node->child2());
901             
902             setInt32(
903                 m_out.select(
904                     m_node->op() == ArithMin
905                         ? m_out.lessThan(left, right)
906                         : m_out.lessThan(right, left),
907                     left, right));
908             break;
909         }
910             
911         case NumberUse: {
912             LValue left = lowDouble(m_node->child1());
913             LValue right = lowDouble(m_node->child2());
914             
915             LBasicBlock notLessThan = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax not less than"));
916             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax continuation"));
917             
918             Vector<ValueFromBlock, 2> results;
919             
920             results.append(m_out.anchor(left));
921             m_out.branch(
922                 m_node->op() == ArithMin
923                     ? m_out.doubleLessThan(left, right)
924                     : m_out.doubleGreaterThan(left, right),
925                 continuation, notLessThan);
926             
927             LBasicBlock lastNext = m_out.appendTo(notLessThan, continuation);
928             results.append(m_out.anchor(m_out.select(
929                 m_node->op() == ArithMin
930                     ? m_out.doubleGreaterThanOrEqual(left, right)
931                     : m_out.doubleLessThanOrEqual(left, right),
932                 right, m_out.constDouble(0.0 / 0.0))));
933             m_out.jump(continuation);
934             
935             m_out.appendTo(continuation, lastNext);
936             setDouble(m_out.phi(m_out.doubleType, results));
937             break;
938         }
939             
940         default:
941             RELEASE_ASSERT_NOT_REACHED();
942             break;
943         }
944     }
945     
946     void compileArithAbs()
947     {
948         switch (m_node->child1().useKind()) {
949         case Int32Use: {
950             LValue value = lowInt32(m_node->child1());
951             
952             LValue mask = m_out.aShr(value, m_out.constInt32(31));
953             LValue result = m_out.bitXor(mask, m_out.add(mask, value));
954             
955             speculate(Overflow, noValue(), 0, m_out.equal(result, m_out.constInt32(1 << 31)));
956             
957             setInt32(result);
958             break;
959         }
960             
961         case NumberUse: {
962             setDouble(m_out.doubleAbs(lowDouble(m_node->child1())));
963             break;
964         }
965             
966         default:
967             RELEASE_ASSERT_NOT_REACHED();
968             break;
969         }
970     }
971     
972     void compileArithNegate()
973     {
974         switch (m_node->child1().useKind()) {
975         case Int32Use: {
976             LValue value = lowInt32(m_node->child1());
977             
978             LValue result;
979             if (nodeCanTruncateInteger(m_node->arithNodeFlags()))
980                 result = m_out.neg(value);
981             else {
982                 // We don't have a negate-with-overflow intrinsic. Hopefully this
983                 // does the trick, though.
984                 LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
985                 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
986                 result = m_out.extractValue(overflowResult, 0);
987                 speculate(NegativeZero, noValue(), 0, m_out.isZero32(result));
988             }
989             
990             setInt32(result);
991             break;
992         }
993             
994         case NumberUse: {
995             setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
996             break;
997         }
998             
999         default:
1000             RELEASE_ASSERT_NOT_REACHED();
1001             break;
1002         }
1003     }
1004     
1005     void compileBitAnd()
1006     {
1007         setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1008     }
1009     
1010     void compileBitOr()
1011     {
1012         setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1013     }
1014     
1015     void compileBitXor()
1016     {
1017         setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1018     }
1019     
1020     void compileBitRShift()
1021     {
1022         setInt32(m_out.aShr(
1023             lowInt32(m_node->child1()),
1024             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1025     }
1026     
1027     void compileBitLShift()
1028     {
1029         setInt32(m_out.shl(
1030             lowInt32(m_node->child1()),
1031             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1032     }
1033     
1034     void compileBitURShift()
1035     {
1036         setInt32(m_out.lShr(
1037             lowInt32(m_node->child1()),
1038             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1039     }
1040     
1041     void compileUInt32ToNumber()
1042     {
1043         LValue value = lowInt32(m_node->child1());
1044
1045         if (!nodeCanSpeculateInteger(m_node->arithNodeFlags())) {
1046             setDouble(m_out.unsignedToDouble(value));
1047             return;
1048         }
1049         
1050         speculateForward(
1051             Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero),
1052             FormattedValue(ValueFormatUInt32, value));
1053         setInt32(value);
1054     }
1055     
1056     void compileInt32ToDouble()
1057     {
1058         // This node is tricky to compile in the DFG backend because it tries to
1059         // avoid converting child1 to a double in-place, as that would make subsequent
1060         // int uses of of child1 fail. But the FTL needs no such special magic, since
1061         // unlike the DFG backend, the FTL allows each node to have multiple
1062         // contemporaneous low-level representations. So, this gives child1 a double
1063         // representation and then forwards that representation to m_node.
1064         
1065         setDouble(lowDouble(m_node->child1()));
1066     }
1067     
1068     void compileCheckStructure()
1069     {
1070         LValue cell = lowCell(m_node->child1());
1071         
1072         ExitKind exitKind;
1073         if (m_node->child1()->op() == WeakJSConstant)
1074             exitKind = BadWeakConstantCache;
1075         else
1076             exitKind = BadCache;
1077         
1078         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1079         
1080         if (m_node->structureSet().size() == 1) {
1081             speculate(
1082                 exitKind, jsValueValue(cell), 0,
1083                 m_out.notEqual(structure, weakPointer(m_node->structureSet()[0])));
1084             return;
1085         }
1086         
1087         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure continuation"));
1088         
1089         LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
1090         for (unsigned i = 0; i < m_node->structureSet().size() - 1; ++i) {
1091             LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("CheckStructure nextStructure"));
1092             m_out.branch(
1093                 m_out.equal(structure, weakPointer(m_node->structureSet()[i])),
1094                 continuation, nextStructure);
1095             m_out.appendTo(nextStructure);
1096         }
1097         
1098         speculate(
1099             exitKind, jsValueValue(cell), 0,
1100             m_out.notEqual(structure, weakPointer(m_node->structureSet().last())));
1101         
1102         m_out.jump(continuation);
1103         m_out.appendTo(continuation, lastNext);
1104     }
1105     
1106     void compileStructureTransitionWatchpoint()
1107     {
1108         addWeakReference(m_node->structure());
1109         
1110         // FIXME: Implement structure transition watchpoints.
1111         // https://bugs.webkit.org/show_bug.cgi?id=113647
1112         
1113         speculateCell(m_node->child1());
1114     }
1115     
1116     void compileArrayifyToStructure()
1117     {
1118         LValue cell = lowCell(m_node->child1());
1119         LValue property = !!m_node->child2() ? lowInt32(m_node->child2()) : 0;
1120         
1121         LBasicBlock unexpectedStructure = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure unexpected structure"));
1122         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure continuation"));
1123         
1124         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1125         
1126         m_out.branch(
1127             m_out.notEqual(structure, weakPointer(m_node->structure())),
1128             unexpectedStructure, continuation);
1129         
1130         LBasicBlock lastNext = m_out.appendTo(unexpectedStructure, continuation);
1131         
1132         if (property) {
1133             switch (m_node->arrayMode().type()) {
1134             case Array::Int32:
1135             case Array::Double:
1136             case Array::Contiguous:
1137                 speculate(
1138                     Uncountable, noValue(), 0,
1139                     m_out.aboveOrEqual(property, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)));
1140                 break;
1141             default:
1142                 break;
1143             }
1144         }
1145         
1146         switch (m_node->arrayMode().type()) {
1147         case Array::Int32:
1148             vmCall(m_out.operation(operationEnsureInt32), m_callFrame, cell);
1149             break;
1150         case Array::Double:
1151             vmCall(m_out.operation(operationEnsureDouble), m_callFrame, cell);
1152             break;
1153         case Array::Contiguous:
1154             if (m_node->arrayMode().conversion() == Array::RageConvert)
1155                 vmCall(m_out.operation(operationRageEnsureContiguous), m_callFrame, cell);
1156             else
1157                 vmCall(m_out.operation(operationEnsureContiguous), m_callFrame, cell);
1158             break;
1159         case Array::ArrayStorage:
1160         case Array::SlowPutArrayStorage:
1161             vmCall(m_out.operation(operationEnsureArrayStorage), m_callFrame, cell);
1162             break;
1163         default:
1164             RELEASE_ASSERT_NOT_REACHED();
1165             break;
1166         }
1167         
1168         structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1169         speculate(
1170             BadIndexingType, jsValueValue(cell), 0,
1171             m_out.notEqual(structure, weakPointer(m_node->structure())));
1172         m_out.jump(continuation);
1173         
1174         m_out.appendTo(continuation, lastNext);
1175     }
1176     
1177     void compilePutStructure()
1178     {
1179         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1180         
1181         m_out.store64(
1182             m_out.constIntPtr(m_node->structureTransitionData().newStructure),
1183             lowCell(m_node->child1()), m_heaps.JSCell_structure);
1184     }
1185     
1186     void compilePhantomPutStructure()
1187     {
1188         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1189     }
1190     
1191     void compileGetButterfly()
1192     {
1193         setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly));
1194     }
1195     
1196     void compileGetArrayLength()
1197     {
1198         switch (m_node->arrayMode().type()) {
1199         case Array::Int32:
1200         case Array::Double:
1201         case Array::Contiguous: {
1202             setInt32(m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
1203             break;
1204         }
1205             
1206         default:
1207             RELEASE_ASSERT_NOT_REACHED();
1208             break;
1209         }
1210     }
1211     
1212     void compileGetByVal()
1213     {
1214         LValue index = lowInt32(m_node->child2());
1215         LValue storage = lowStorage(m_node->child3());
1216         
1217         switch (m_node->arrayMode().type()) {
1218         case Array::Int32:
1219         case Array::Contiguous: {
1220             if (m_node->arrayMode().isInBounds()) {
1221                 speculate(
1222                     OutOfBounds, noValue(), 0,
1223                     m_out.aboveOrEqual(
1224                         index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
1225                 
1226                 LValue result = m_out.load64(m_out.baseIndex(
1227                     m_node->arrayMode().type() == Array::Int32 ?
1228                         m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
1229                     storage, m_out.zeroExt(index, m_out.intPtr),
1230                     m_state.forNode(m_node->child2()).m_value));
1231                 speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result));
1232                 setJSValue(result);
1233                 return;
1234             }
1235             
1236             // FIXME: Implement hole/OOB loads in the FTL.
1237             // https://bugs.webkit.org/show_bug.cgi?id=118077
1238             RELEASE_ASSERT_NOT_REACHED();
1239             return;
1240         }
1241             
1242         case Array::Double: {
1243             if (m_node->arrayMode().isInBounds()) {
1244                 if (m_node->arrayMode().isSaneChain()) {
1245                     // FIXME: Implement structure transition watchpoints.
1246                     // https://bugs.webkit.org/show_bug.cgi?id=113647
1247                 }
1248             
1249                 speculate(
1250                     OutOfBounds, noValue(), 0,
1251                     m_out.aboveOrEqual(
1252                         index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
1253                 
1254                 LValue result = m_out.loadDouble(m_out.baseIndex(
1255                     m_heaps.indexedDoubleProperties,
1256                     storage, m_out.zeroExt(index, m_out.intPtr),
1257                     m_state.forNode(m_node->child2()).m_value));
1258                 
1259                 if (!m_node->arrayMode().isSaneChain()) {
1260                     speculate(
1261                         LoadFromHole, noValue(), 0,
1262                         m_out.doubleNotEqualOrUnordered(result, result));
1263                 }
1264                 setDouble(result);
1265                 break;
1266             }
1267             
1268             // FIXME: Implement hole/OOB loads in the FTL.
1269             // https://bugs.webkit.org/show_bug.cgi?id=118077
1270             RELEASE_ASSERT_NOT_REACHED();
1271             return;
1272         }
1273             
1274         default:
1275             RELEASE_ASSERT_NOT_REACHED();
1276             return;
1277         }
1278     }
1279     
1280     void compilePutByVal()
1281     {
1282         Edge child1 = m_graph.varArgChild(m_node, 0);
1283         Edge child2 = m_graph.varArgChild(m_node, 1);
1284         Edge child3 = m_graph.varArgChild(m_node, 2);
1285         Edge child4 = m_graph.varArgChild(m_node, 3);
1286
1287         LValue base = lowCell(child1);
1288         LValue index = lowInt32(child2);
1289         LValue storage = lowStorage(child4);
1290         
1291         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
1292         LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
1293             
1294         switch (m_node->arrayMode().type()) {
1295         case Array::Int32:
1296         case Array::Contiguous: {
1297             LValue value = lowJSValue(child3, ManualOperandSpeculation);
1298             
1299             if (m_node->arrayMode().type() == Array::Int32)
1300                 FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
1301             
1302             TypedPointer elementPointer = m_out.baseIndex(
1303                 m_node->arrayMode().type() == Array::Int32 ?
1304                 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
1305                 storage, m_out.zeroExt(index, m_out.intPtr),
1306                 m_state.forNode(child2).m_value);
1307             
1308             if (m_node->op() == PutByValAlias) {
1309                 m_out.store64(value, elementPointer);
1310                 break;
1311             }
1312             
1313             contiguousPutByValOutOfBounds(
1314                 codeBlock()->isStrictMode()
1315                     ? operationPutByValBeyondArrayBoundsStrict
1316                     : operationPutByValBeyondArrayBoundsNonStrict,
1317                 base, storage, index, value, continuation);
1318             
1319             m_out.store64(value, elementPointer);
1320             break;
1321         }
1322             
1323         case Array::Double: {
1324             LValue value = lowDouble(child3);
1325             
1326             FTL_TYPE_CHECK(
1327                 doubleValue(value), child3, SpecRealNumber,
1328                 m_out.doubleNotEqualOrUnordered(value, value));
1329             
1330             TypedPointer elementPointer = m_out.baseIndex(
1331                 m_heaps.indexedDoubleProperties,
1332                 storage, m_out.zeroExt(index, m_out.intPtr),
1333                 m_state.forNode(child2).m_value);
1334
1335             if (m_node->op() == PutByValAlias) {
1336                 m_out.storeDouble(value, elementPointer);
1337                 break;
1338             }
1339             
1340             contiguousPutByValOutOfBounds(
1341                 codeBlock()->isStrictMode()
1342                     ? operationPutDoubleByValBeyondArrayBoundsStrict
1343                     : operationPutDoubleByValBeyondArrayBoundsNonStrict,
1344                 base, storage, index, value, continuation);
1345             
1346             m_out.storeDouble(value, elementPointer);
1347             break;
1348         }
1349             
1350         default:
1351             RELEASE_ASSERT_NOT_REACHED();
1352             break;
1353         }
1354
1355         m_out.jump(continuation);
1356         m_out.appendTo(continuation, outerLastNext);
1357     }
1358     
1359     void compileGetByOffset()
1360     {
1361         StorageAccessData& data =
1362             m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
1363         
1364         setJSValue(
1365             m_out.load64(
1366                 m_out.address(
1367                     m_heaps.properties[data.identifierNumber],
1368                     lowStorage(m_node->child1()),
1369                     offsetRelativeToBase(data.offset))));
1370     }
1371     
1372     void compilePutByOffset()
1373     {
1374         StorageAccessData& data =
1375             m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
1376         
1377         m_out.store64(
1378             lowJSValue(m_node->child3()),
1379             m_out.address(
1380                 m_heaps.properties[data.identifierNumber],
1381                 lowStorage(m_node->child1()),
1382                 offsetRelativeToBase(data.offset)));
1383     }
1384     
1385     void compileGetGlobalVar()
1386     {
1387         setJSValue(m_out.load64(m_out.absolute(m_node->registerPointer())));
1388     }
1389     
1390     void compilePutGlobalVar()
1391     {
1392         m_out.store64(
1393             lowJSValue(m_node->child1()), m_out.absolute(m_node->registerPointer()));
1394     }
1395     
1396     void compileCompareEq()
1397     {
1398         if (m_node->isBinaryUseKind(Int32Use)
1399             || m_node->isBinaryUseKind(NumberUse)
1400             || m_node->isBinaryUseKind(ObjectUse)) {
1401             compileCompareStrictEq();
1402             return;
1403         }
1404         
1405         RELEASE_ASSERT_NOT_REACHED();
1406     }
1407     
1408     void compileCompareEqConstant()
1409     {
1410         ASSERT(m_graph.valueOfJSConstant(m_node->child2().node()).isNull());
1411         masqueradesAsUndefinedWatchpointIfIsStillValid();
1412         setBoolean(
1413             equalNullOrUndefined(
1414                 m_node->child1(), AllCellsAreFalse, EqualNullOrUndefined));
1415     }
1416     
1417     void compileCompareStrictEq()
1418     {
1419         if (m_node->isBinaryUseKind(Int32Use)) {
1420             setBoolean(
1421                 m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1422             return;
1423         }
1424         
1425         if (m_node->isBinaryUseKind(NumberUse)) {
1426             setBoolean(
1427                 m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1428         }
1429         
1430         if (m_node->isBinaryUseKind(ObjectUse)) {
1431             masqueradesAsUndefinedWatchpointIfIsStillValid();
1432             setBoolean(
1433                 m_out.equal(
1434                     lowNonNullObject(m_node->child1()),
1435                     lowNonNullObject(m_node->child2())));
1436             return;
1437         }
1438         
1439         RELEASE_ASSERT_NOT_REACHED();
1440     }
1441     
1442     void compileCompareStrictEqConstant()
1443     {
1444         JSValue constant = m_graph.valueOfJSConstant(m_node->child2().node());
1445
1446         if (constant.isUndefinedOrNull()
1447             && !masqueradesAsUndefinedWatchpointIfIsStillValid()) {
1448             if (constant.isNull()) {
1449                 setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualNull));
1450                 return;
1451             }
1452         
1453             ASSERT(constant.isUndefined());
1454             setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualUndefined));
1455             return;
1456         }
1457         
1458         setBoolean(
1459             m_out.equal(
1460                 lowJSValue(m_node->child1()),
1461                 m_out.constInt64(JSValue::encode(constant))));
1462     }
1463     
1464     void compileCompareLess()
1465     {
1466         if (m_node->isBinaryUseKind(Int32Use)) {
1467             setBoolean(
1468                 m_out.lessThan(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1469             return;
1470         }
1471         
1472         if (m_node->isBinaryUseKind(NumberUse)) {
1473             setBoolean(
1474                 m_out.doubleLessThan(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1475             return;
1476         }
1477         
1478         RELEASE_ASSERT_NOT_REACHED();
1479     }
1480     
1481     void compileCompareLessEq()
1482     {
1483         if (m_node->isBinaryUseKind(Int32Use)) {
1484             setBoolean(
1485                 m_out.lessThanOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1486             return;
1487         }
1488         
1489         if (m_node->isBinaryUseKind(NumberUse)) {
1490             setBoolean(
1491                 m_out.doubleLessThanOrEqual(
1492                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1493             return;
1494         }
1495         
1496         RELEASE_ASSERT_NOT_REACHED();
1497     }
1498     
1499     void compileCompareGreater()
1500     {
1501         if (m_node->isBinaryUseKind(Int32Use)) {
1502             setBoolean(
1503                 m_out.greaterThan(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1504             return;
1505         }
1506         
1507         if (m_node->isBinaryUseKind(NumberUse)) {
1508             setBoolean(
1509                 m_out.doubleGreaterThan(
1510                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1511             return;
1512         }
1513         
1514         RELEASE_ASSERT_NOT_REACHED();
1515     }
1516     
1517     void compileCompareGreaterEq()
1518     {
1519         if (m_node->isBinaryUseKind(Int32Use)) {
1520             setBoolean(
1521                 m_out.greaterThanOrEqual(
1522                     lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1523             return;
1524         }
1525         
1526         if (m_node->isBinaryUseKind(NumberUse)) {
1527             setBoolean(
1528                 m_out.doubleGreaterThanOrEqual(
1529                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1530             return;
1531         }
1532         
1533         RELEASE_ASSERT_NOT_REACHED();
1534     }
1535     
1536     void compileLogicalNot()
1537     {
1538         setBoolean(m_out.bitNot(boolify(m_node->child1())));
1539     }
1540     
1541     void compileJump()
1542     {
1543         m_out.jump(lowBlock(m_node->takenBlock()));
1544     }
1545     
1546     void compileBranch()
1547     {
1548         m_out.branch(
1549             boolify(m_node->child1()),
1550             lowBlock(m_node->takenBlock()),
1551             lowBlock(m_node->notTakenBlock()));
1552     }
1553     
1554     void compileSwitch()
1555     {
1556         SwitchData* data = m_node->switchData();
1557         switch (data->kind) {
1558         case SwitchImm: {
1559             Vector<ValueFromBlock, 2> intValues;
1560             LBasicBlock switchOnInts = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm int case"));
1561             
1562             LBasicBlock lastNext = m_out.appendTo(m_out.m_block, switchOnInts);
1563             
1564             switch (m_node->child1().useKind()) {
1565             case Int32Use: {
1566                 intValues.append(m_out.anchor(lowInt32(m_node->child1())));
1567                 m_out.jump(switchOnInts);
1568                 break;
1569             }
1570                 
1571             case UntypedUse: {
1572                 LBasicBlock isInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is int"));
1573                 LBasicBlock isNotInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is not int"));
1574                 LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is double"));
1575                 
1576                 LValue boxedValue = lowJSValue(m_node->child1());
1577                 m_out.branch(isNotInt32(boxedValue), isNotInt, isInt);
1578                 
1579                 LBasicBlock innerLastNext = m_out.appendTo(isInt, isNotInt);
1580                 
1581                 intValues.append(m_out.anchor(unboxInt32(boxedValue)));
1582                 m_out.jump(switchOnInts);
1583                 
1584                 m_out.appendTo(isNotInt, isDouble);
1585                 m_out.branch(
1586                     isCellOrMisc(boxedValue), lowBlock(data->fallThrough), isDouble);
1587                 
1588                 m_out.appendTo(isDouble, innerLastNext);
1589                 LValue doubleValue = unboxDouble(boxedValue);
1590                 LValue intInDouble = m_out.fpToInt32(doubleValue);
1591                 intValues.append(m_out.anchor(intInDouble));
1592                 m_out.branch(
1593                     m_out.doubleEqual(m_out.intToDouble(intInDouble), doubleValue),
1594                     switchOnInts, lowBlock(data->fallThrough));
1595                 break;
1596             }
1597                 
1598             default:
1599                 RELEASE_ASSERT_NOT_REACHED();
1600                 break;
1601             }
1602             
1603             m_out.appendTo(switchOnInts, lastNext);
1604             buildSwitch(data, m_out.int32, m_out.phi(m_out.int32, intValues));
1605             return;
1606         }
1607         
1608         case SwitchChar: {
1609             LValue stringValue;
1610             
1611             switch (m_node->child1().useKind()) {
1612             case StringUse: {
1613                 stringValue = lowString(m_node->child1());
1614                 break;
1615             }
1616                 
1617             case UntypedUse: {
1618                 LValue unboxedValue = lowJSValue(m_node->child1());
1619                 
1620                 LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar is cell"));
1621                 LBasicBlock isStringCase = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar is string"));
1622                 
1623                 m_out.branch(
1624                     isNotCell(unboxedValue), lowBlock(data->fallThrough), isCellCase);
1625                 
1626                 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
1627                 LValue cellValue = unboxedValue;
1628                 m_out.branch(isNotString(cellValue), lowBlock(data->fallThrough), isStringCase);
1629                 
1630                 m_out.appendTo(isStringCase, lastNext);
1631                 stringValue = cellValue;
1632                 break;
1633             }
1634                 
1635             default:
1636                 RELEASE_ASSERT_NOT_REACHED();
1637                 break;
1638             }
1639             
1640             LBasicBlock lengthIs1 = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar length is 1"));
1641             LBasicBlock needResolution = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar resolution"));
1642             LBasicBlock resolved = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar resolved"));
1643             LBasicBlock is8Bit = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar 8bit"));
1644             LBasicBlock is16Bit = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar 16bit"));
1645             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar continuation"));
1646             
1647             m_out.branch(
1648                 m_out.notEqual(
1649                     m_out.load32(stringValue, m_heaps.JSString_length),
1650                     m_out.int32One),
1651                 lowBlock(data->fallThrough), lengthIs1);
1652             
1653             LBasicBlock lastNext = m_out.appendTo(lengthIs1, needResolution);
1654             Vector<ValueFromBlock, 2> values;
1655             LValue fastValue = m_out.loadPtr(stringValue, m_heaps.JSString_value);
1656             values.append(m_out.anchor(fastValue));
1657             m_out.branch(m_out.isNull(fastValue), needResolution, resolved);
1658             
1659             m_out.appendTo(needResolution, resolved);
1660             values.append(m_out.anchor(
1661                 vmCall(m_out.operation(operationResolveRope), m_callFrame, stringValue)));
1662             m_out.jump(resolved);
1663             
1664             m_out.appendTo(resolved, is8Bit);
1665             LValue value = m_out.phi(m_out.intPtr, values);
1666             LValue characterData = m_out.loadPtr(value, m_heaps.StringImpl_data);
1667             m_out.branch(
1668                 m_out.testNonZero32(
1669                     m_out.load32(value, m_heaps.StringImpl_hashAndFlags),
1670                     m_out.constInt32(StringImpl::flagIs8Bit())),
1671                 is8Bit, is16Bit);
1672             
1673             Vector<ValueFromBlock, 2> characters;
1674             m_out.appendTo(is8Bit, is16Bit);
1675             characters.append(m_out.anchor(
1676                 m_out.zeroExt(m_out.load8(characterData, m_heaps.characters8[0]), m_out.int16)));
1677             m_out.jump(continuation);
1678             
1679             m_out.appendTo(is16Bit, continuation);
1680             characters.append(m_out.anchor(m_out.load16(characterData, m_heaps.characters16[0])));
1681             m_out.jump(continuation);
1682             
1683             m_out.appendTo(continuation, lastNext);
1684             buildSwitch(data, m_out.int16, m_out.phi(m_out.int16, characters));
1685             return;
1686         }
1687         
1688         case SwitchString:
1689             RELEASE_ASSERT_NOT_REACHED();
1690             break;
1691         }
1692         
1693         RELEASE_ASSERT_NOT_REACHED();
1694     }
1695     
1696     void compileReturn()
1697     {
1698         // FIXME: have a real epilogue when we switch to using our calling convention.
1699         // https://bugs.webkit.org/show_bug.cgi?id=113621
1700         m_out.ret(lowJSValue(m_node->child1()));
1701     }
1702     
1703     void compileForceOSRExit()
1704     {
1705         terminate(InadequateCoverage);
1706     }
1707     
1708     LValue boolify(Edge edge)
1709     {
1710         switch (edge.useKind()) {
1711         case BooleanUse:
1712             return lowBoolean(m_node->child1());
1713         case Int32Use:
1714             return m_out.notZero32(lowInt32(m_node->child1()));
1715         case NumberUse:
1716             return m_out.doubleNotEqual(lowDouble(edge), m_out.doubleZero);
1717         case ObjectOrOtherUse:
1718             return m_out.bitNot(
1719                 equalNullOrUndefined(
1720                     edge, CellCaseSpeculatesObject, SpeculateNullOrUndefined,
1721                     ManualOperandSpeculation));
1722         default:
1723             RELEASE_ASSERT_NOT_REACHED();
1724             return 0;
1725         }
1726     }
1727     
1728     enum StringOrObjectMode {
1729         AllCellsAreFalse,
1730         CellCaseSpeculatesObject
1731     };
1732     enum EqualNullOrUndefinedMode {
1733         EqualNull,
1734         EqualUndefined,
1735         EqualNullOrUndefined,
1736         SpeculateNullOrUndefined
1737     };
1738     LValue equalNullOrUndefined(
1739         Edge edge, StringOrObjectMode cellMode, EqualNullOrUndefinedMode primitiveMode,
1740         OperandSpeculationMode operandMode = AutomaticOperandSpeculation)
1741     {
1742         bool validWatchpoint = masqueradesAsUndefinedWatchpointIfIsStillValid();
1743         
1744         LValue value = lowJSValue(edge, operandMode);
1745         
1746         LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined cell case"));
1747         LBasicBlock primitiveCase = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined primitive case"));
1748         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined continuation"));
1749         
1750         m_out.branch(isNotCell(value), primitiveCase, cellCase);
1751         
1752         LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
1753         
1754         Vector<ValueFromBlock, 3> results;
1755         
1756         switch (cellMode) {
1757         case AllCellsAreFalse:
1758             break;
1759         case CellCaseSpeculatesObject:
1760             FTL_TYPE_CHECK(
1761                 jsValueValue(value), edge, (~SpecCell) | SpecObject,
1762                 m_out.equal(
1763                     m_out.loadPtr(value, m_heaps.JSCell_structure),
1764                     m_out.constIntPtr(vm().stringStructure.get())));
1765             break;
1766         }
1767         
1768         if (validWatchpoint) {
1769             results.append(m_out.anchor(m_out.booleanFalse));
1770             m_out.jump(continuation);
1771         } else {
1772             LBasicBlock masqueradesCase =
1773                 FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined masquerades case"));
1774                 
1775             LValue structure = m_out.loadPtr(value, m_heaps.JSCell_structure);
1776             
1777             results.append(m_out.anchor(m_out.booleanFalse));
1778             
1779             m_out.branch(
1780                 m_out.testNonZero8(
1781                     m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
1782                     m_out.constInt8(MasqueradesAsUndefined)),
1783                 masqueradesCase, continuation);
1784             
1785             m_out.appendTo(masqueradesCase, primitiveCase);
1786             
1787             results.append(m_out.anchor(
1788                 m_out.equal(
1789                     m_out.constIntPtr(m_graph.globalObjectFor(m_node->codeOrigin)),
1790                     m_out.loadPtr(structure, m_heaps.Structure_globalObject))));
1791             m_out.jump(continuation);
1792         }
1793         
1794         m_out.appendTo(primitiveCase, continuation);
1795         
1796         LValue primitiveResult;
1797         switch (primitiveMode) {
1798         case EqualNull:
1799             primitiveResult = m_out.equal(value, m_out.constInt64(ValueNull));
1800             break;
1801         case EqualUndefined:
1802             primitiveResult = m_out.equal(value, m_out.constInt64(ValueUndefined));
1803             break;
1804         case EqualNullOrUndefined:
1805             primitiveResult = m_out.equal(
1806                 m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
1807                 m_out.constInt64(ValueNull));
1808             break;
1809         case SpeculateNullOrUndefined:
1810             FTL_TYPE_CHECK(
1811                 jsValueValue(value), edge, SpecCell | SpecOther,
1812                 m_out.notEqual(
1813                     m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
1814                     m_out.constInt64(ValueNull)));
1815             primitiveResult = m_out.booleanTrue;
1816             break;
1817         }
1818         results.append(m_out.anchor(primitiveResult));
1819         m_out.jump(continuation);
1820         
1821         m_out.appendTo(continuation, lastNext);
1822         
1823         return m_out.phi(m_out.boolean, results);
1824     }
1825     
1826     template<typename FunctionType>
1827     void contiguousPutByValOutOfBounds(
1828         FunctionType slowPathFunction,
1829         LValue base, LValue storage, LValue index, LValue value,
1830         LBasicBlock continuation)
1831     {
1832         LValue isNotInBounds = m_out.aboveOrEqual(
1833             index, m_out.load32(storage, m_heaps.Butterfly_publicLength));
1834         if (m_node->arrayMode().isInBounds())
1835             speculate(StoreToHoleOrOutOfBounds, noValue(), 0, isNotInBounds);
1836         else {
1837             LBasicBlock notInBoundsCase =
1838                 FTL_NEW_BLOCK(m_out, ("PutByVal not in bounds"));
1839             LBasicBlock performStore =
1840                 FTL_NEW_BLOCK(m_out, ("PutByVal perform store"));
1841                 
1842             m_out.branch(isNotInBounds, notInBoundsCase, performStore);
1843                 
1844             LBasicBlock lastNext = m_out.appendTo(notInBoundsCase, performStore);
1845                 
1846             LValue isOutOfBounds = m_out.aboveOrEqual(
1847                 index, m_out.load32(storage, m_heaps.Butterfly_vectorLength));
1848                 
1849             if (!m_node->arrayMode().isOutOfBounds())
1850                 speculate(OutOfBounds, noValue(), 0, isOutOfBounds);
1851             else {
1852                 LBasicBlock outOfBoundsCase =
1853                     FTL_NEW_BLOCK(m_out, ("PutByVal out of bounds"));
1854                 LBasicBlock holeCase =
1855                     FTL_NEW_BLOCK(m_out, ("PutByVal hole case"));
1856                     
1857                 m_out.branch(isOutOfBounds, outOfBoundsCase, holeCase);
1858                     
1859                 LBasicBlock innerLastNext = m_out.appendTo(outOfBoundsCase, holeCase);
1860                     
1861                 vmCall(
1862                     m_out.operation(slowPathFunction),
1863                     m_callFrame, base, index, value);
1864                     
1865                 m_out.jump(continuation);
1866                     
1867                 m_out.appendTo(holeCase, innerLastNext);
1868             }
1869             
1870             m_out.store32(
1871                 m_out.add(index, m_out.int32One),
1872                 storage, m_heaps.Butterfly_publicLength);
1873                 
1874             m_out.jump(performStore);
1875             m_out.appendTo(performStore, lastNext);
1876         }
1877     }
1878     
1879     void buildSwitch(SwitchData* data, LType type, LValue switchValue)
1880     {
1881         Vector<SwitchCase> cases;
1882         for (unsigned i = 0; i < data->cases.size(); ++i) {
1883             cases.append(SwitchCase(
1884                 constInt(type, data->cases[i].value.switchLookupValue()),
1885                 lowBlock(data->cases[i].target)));
1886         }
1887         
1888         m_out.switchInstruction(switchValue, cases, lowBlock(data->fallThrough));
1889     }
1890     
1891     void speculateBackward(
1892         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
1893     {
1894         appendOSRExit(
1895             kind, lowValue, highValue, failCondition, BackwardSpeculation, FormattedValue());
1896     }
1897     
1898     void speculateForward(
1899         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
1900         const FormattedValue& recovery)
1901     {
1902         appendOSRExit(
1903             kind, lowValue, highValue, failCondition, ForwardSpeculation, recovery);
1904     }
1905     
1906     void speculate(
1907         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
1908     {
1909         appendOSRExit(
1910             kind, lowValue, highValue, failCondition, m_direction, FormattedValue());
1911     }
1912     
1913     void terminate(ExitKind kind)
1914     {
1915         speculate(kind, noValue(), 0, m_out.booleanTrue);
1916     }
1917     
1918     void backwardTypeCheck(
1919         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
1920         LValue failCondition)
1921     {
1922         appendTypeCheck(
1923             lowValue, highValue, typesPassedThrough, failCondition, BackwardSpeculation,
1924             FormattedValue());
1925     }
1926     
1927     void forwardTypeCheck(
1928         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
1929         LValue failCondition)
1930     {
1931         appendTypeCheck(
1932             lowValue, highValue, typesPassedThrough, failCondition, ForwardSpeculation,
1933             FormattedValue());
1934     }
1935     
1936     void typeCheck(
1937         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
1938         LValue failCondition)
1939     {
1940         appendTypeCheck(
1941             lowValue, highValue, typesPassedThrough, failCondition, m_direction,
1942             FormattedValue());
1943     }
1944     
1945     void appendTypeCheck(
1946         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
1947         LValue failCondition, SpeculationDirection direction, FormattedValue recovery)
1948     {
1949         if (!m_interpreter.needsTypeCheck(highValue, typesPassedThrough))
1950             return;
1951         ASSERT(mayHaveTypeCheck(highValue.useKind()));
1952         appendOSRExit(BadType, lowValue, highValue.node(), failCondition, direction, recovery);
1953         m_interpreter.filter(highValue, typesPassedThrough);
1954     }
1955     
1956     LValue lowInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1957     {
1958         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
1959         
1960         LoweredNodeValue value = m_int32Values.get(edge.node());
1961         if (isValid(value))
1962             return value.value();
1963         
1964         value = m_jsValueValues.get(edge.node());
1965         if (isValid(value)) {
1966             LValue boxedResult = value.value();
1967             FTL_TYPE_CHECK(
1968                 jsValueValue(boxedResult), edge, SpecInt32, isNotInt32(boxedResult));
1969             LValue result = unboxInt32(boxedResult);
1970             setInt32(edge.node(), result);
1971             return result;
1972         }
1973
1974         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt32));
1975         terminate(Uncountable);
1976         return m_out.int32Zero;
1977     }
1978     
1979     LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1980     {
1981         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind()));
1982         
1983         LoweredNodeValue value = m_jsValueValues.get(edge.node());
1984         if (isValid(value)) {
1985             LValue uncheckedValue = value.value();
1986             FTL_TYPE_CHECK(
1987                 jsValueValue(uncheckedValue), edge, SpecCell, isNotCell(uncheckedValue));
1988             return uncheckedValue;
1989         }
1990         
1991         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecCell));
1992         terminate(Uncountable);
1993         return m_out.intPtrZero;
1994     }
1995     
1996     LValue lowObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1997     {
1998         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
1999         
2000         LValue result = lowCell(edge, mode);
2001         speculateObject(edge, result);
2002         return result;
2003     }
2004     
2005     LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2006     {
2007         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringUse || edge.useKind() == KnownStringUse);
2008         
2009         LValue result = lowCell(edge, mode);
2010         speculateString(edge, result);
2011         return result;
2012     }
2013     
2014     LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2015     {
2016         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
2017         
2018         LValue result = lowCell(edge, mode);
2019         speculateNonNullObject(edge, result);
2020         return result;
2021     }
2022     
2023     LValue lowBoolean(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2024     {
2025         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
2026         
2027         LoweredNodeValue value = m_booleanValues.get(edge.node());
2028         if (isValid(value))
2029             return value.value();
2030         
2031         value = m_jsValueValues.get(edge.node());
2032         if (isValid(value)) {
2033             LValue unboxedResult = value.value();
2034             FTL_TYPE_CHECK(
2035                 jsValueValue(unboxedResult), edge, SpecBoolean, isNotBoolean(unboxedResult));
2036             LValue result = unboxBoolean(unboxedResult);
2037             setBoolean(edge.node(), result);
2038             return result;
2039         }
2040         
2041         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecBoolean));
2042         terminate(Uncountable);
2043         return m_out.booleanFalse;
2044     }
2045     
2046     LValue lowDouble(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2047     {
2048         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind()));
2049         
2050         LoweredNodeValue value = m_doubleValues.get(edge.node());
2051         if (isValid(value))
2052             return value.value();
2053         
2054         value = m_int32Values.get(edge.node());
2055         if (isValid(value)) {
2056             LValue result = m_out.intToDouble(value.value());
2057             setDouble(edge.node(), result);
2058             return result;
2059         }
2060         
2061         value = m_jsValueValues.get(edge.node());
2062         if (isValid(value)) {
2063             LValue boxedResult = value.value();
2064             
2065             LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("Double unboxing int case"));
2066             LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("Double unboxing double case"));
2067             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Double unboxing continuation"));
2068             
2069             m_out.branch(isNotInt32(boxedResult), doubleCase, intCase);
2070             
2071             LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
2072             
2073             ValueFromBlock intToDouble = m_out.anchor(
2074                 m_out.intToDouble(unboxInt32(boxedResult)));
2075             m_out.jump(continuation);
2076             
2077             m_out.appendTo(doubleCase, continuation);
2078             
2079             FTL_TYPE_CHECK(
2080                 jsValueValue(boxedResult), edge, SpecNumber, isCellOrMisc(boxedResult));
2081             
2082             ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedResult));
2083             m_out.jump(continuation);
2084             
2085             m_out.appendTo(continuation, lastNext);
2086             
2087             LValue result = m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
2088             
2089             setDouble(edge.node(), result);
2090             return result;
2091         }
2092         
2093         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecNumber));
2094         terminate(Uncountable);
2095         return m_out.doubleZero;
2096     }
2097     
2098     LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2099     {
2100         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
2101         
2102         LoweredNodeValue value = m_jsValueValues.get(edge.node());
2103         if (isValid(value))
2104             return value.value();
2105         
2106         value = m_int32Values.get(edge.node());
2107         if (isValid(value)) {
2108             LValue result = boxInt32(value.value());
2109             setJSValue(edge.node(), result);
2110             return result;
2111         }
2112         
2113         value = m_booleanValues.get(edge.node());
2114         if (isValid(value)) {
2115             LValue result = boxBoolean(value.value());
2116             setJSValue(edge.node(), result);
2117             return result;
2118         }
2119         
2120         value = m_doubleValues.get(edge.node());
2121         if (isValid(value)) {
2122             LValue result = boxDouble(value.value());
2123             setJSValue(edge.node(), result);
2124             return result;
2125         }
2126         
2127         RELEASE_ASSERT_NOT_REACHED();
2128         return 0;
2129     }
2130     
2131     LValue lowStorage(Edge edge)
2132     {
2133         LoweredNodeValue value = m_storageValues.get(edge.node());
2134         if (isValid(value))
2135             return value.value();
2136         
2137         LValue result = lowCell(edge);
2138         setStorage(edge.node(), result);
2139         return result;
2140     }
2141     
2142     LValue isNotInt32(LValue jsValue)
2143     {
2144         return m_out.below(jsValue, m_tagTypeNumber);
2145     }
2146     LValue unboxInt32(LValue jsValue)
2147     {
2148         return m_out.castToInt32(jsValue);
2149     }
2150     LValue boxInt32(LValue value)
2151     {
2152         return m_out.add(m_out.zeroExt(value, m_out.int64), m_tagTypeNumber);
2153     }
2154     
2155     LValue isCellOrMisc(LValue jsValue)
2156     {
2157         return m_out.testIsZero64(jsValue, m_tagTypeNumber);
2158     }
2159     LValue unboxDouble(LValue jsValue)
2160     {
2161         return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType);
2162     }
2163     LValue boxDouble(LValue doubleValue)
2164     {
2165         return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber);
2166     }
2167     
2168     LValue isNotCell(LValue jsValue)
2169     {
2170         return m_out.testNonZero64(jsValue, m_tagMask);
2171     }
2172     
2173     LValue isNotBoolean(LValue jsValue)
2174     {
2175         return m_out.testNonZero64(
2176             m_out.bitXor(jsValue, m_out.constInt64(ValueFalse)),
2177             m_out.constInt64(~1));
2178     }
2179     LValue unboxBoolean(LValue jsValue)
2180     {
2181         // We want to use a cast that guarantees that LLVM knows that even the integer
2182         // value is just 0 or 1. But for now we do it the dumb way.
2183         return m_out.notZero64(m_out.bitAnd(jsValue, m_out.constInt64(1)));
2184     }
2185     LValue boxBoolean(LValue value)
2186     {
2187         return m_out.select(
2188             value, m_out.constInt64(ValueTrue), m_out.constInt64(ValueFalse));
2189     }
2190
2191     void speculate(Edge edge)
2192     {
2193         switch (edge.useKind()) {
2194         case UntypedUse:
2195             break;
2196         case KnownInt32Use:
2197         case KnownNumberUse:
2198             ASSERT(!m_interpreter.needsTypeCheck(edge));
2199             break;
2200         case Int32Use:
2201             speculateInt32(edge);
2202             break;
2203         case CellUse:
2204             speculateCell(edge);
2205             break;
2206         case KnownCellUse:
2207             ASSERT(!m_interpreter.needsTypeCheck(edge));
2208             break;
2209         case ObjectUse:
2210             speculateObject(edge);
2211             break;
2212         case StringUse:
2213             speculateString(edge);
2214             break;
2215         case RealNumberUse:
2216             speculateRealNumber(edge);
2217             break;
2218         case NumberUse:
2219             speculateNumber(edge);
2220             break;
2221         case BooleanUse:
2222             speculateBoolean(edge);
2223             break;
2224         default:
2225             RELEASE_ASSERT_NOT_REACHED();
2226         }
2227     }
2228     
2229     void speculate(Node*, Edge edge)
2230     {
2231         speculate(edge);
2232     }
2233     
2234     void speculateInt32(Edge edge)
2235     {
2236         lowInt32(edge);
2237     }
2238     
2239     void speculateCell(Edge edge)
2240     {
2241         lowCell(edge);
2242     }
2243     
2244     LValue isObject(LValue cell)
2245     {
2246         return m_out.notEqual(
2247             m_out.loadPtr(cell, m_heaps.JSCell_structure),
2248             m_out.constIntPtr(vm().stringStructure.get()));
2249     }
2250     
2251     LValue isNotString(LValue cell)
2252     {
2253         return isObject(cell);
2254     }
2255     
2256     LValue isString(LValue cell)
2257     {
2258         return m_out.equal(
2259             m_out.loadPtr(cell, m_heaps.JSCell_structure),
2260             m_out.constIntPtr(vm().stringStructure.get()));
2261     }
2262     
2263     LValue isNotObject(LValue cell)
2264     {
2265         return isString(cell);
2266     }
2267     
2268     void speculateObject(Edge edge, LValue cell)
2269     {
2270         FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecObject, isNotObject(cell));
2271     }
2272     
2273     void speculateObject(Edge edge)
2274     {
2275         speculateObject(edge, lowCell(edge));
2276     }
2277     
2278     void speculateString(Edge edge, LValue cell)
2279     {
2280         FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecString, isNotString(cell));
2281     }
2282     
2283     void speculateString(Edge edge)
2284     {
2285         speculateString(edge, lowCell(edge));
2286     }
2287     
2288     void speculateNonNullObject(Edge edge, LValue cell)
2289     {
2290         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
2291         FTL_TYPE_CHECK(
2292             jsValueValue(cell), edge, SpecObject, 
2293             m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())));
2294         if (masqueradesAsUndefinedWatchpointIfIsStillValid())
2295             return;
2296         
2297         speculate(
2298             BadType, jsValueValue(cell), edge.node(),
2299             m_out.testNonZero8(
2300                 m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
2301                 m_out.constInt8(MasqueradesAsUndefined)));
2302     }
2303     
2304     void speculateNumber(Edge edge)
2305     {
2306         // Do an early return here because lowDouble() can create a lot of control flow.
2307         if (!m_interpreter.needsTypeCheck(edge))
2308             return;
2309         
2310         lowDouble(edge);
2311     }
2312     
2313     void speculateRealNumber(Edge edge)
2314     {
2315         // Do an early return here because lowDouble() can create a lot of control flow.
2316         if (!m_interpreter.needsTypeCheck(edge))
2317             return;
2318         
2319         LValue value = lowDouble(edge);
2320         FTL_TYPE_CHECK(
2321             doubleValue(value), edge, SpecRealNumber,
2322             m_out.doubleNotEqualOrUnordered(value, value));
2323     }
2324     
2325     void speculateBoolean(Edge edge)
2326     {
2327         lowBoolean(edge);
2328     }
2329
2330     bool masqueradesAsUndefinedWatchpointIsStillValid()
2331     {
2332         return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->codeOrigin);
2333     }
2334     
2335     bool masqueradesAsUndefinedWatchpointIfIsStillValid()
2336     {
2337         if (!masqueradesAsUndefinedWatchpointIsStillValid())
2338             return false;
2339         
2340         // FIXME: Implement masquerades-as-undefined watchpoints.
2341         // https://bugs.webkit.org/show_bug.cgi?id=113647
2342         return true;
2343     }
2344     
2345     enum ExceptionCheckMode { NoExceptions, CheckExceptions };
2346     
2347     LValue vmCall(LValue function, ExceptionCheckMode mode = CheckExceptions)
2348     {
2349         callPreflight();
2350         LValue result = m_out.call(function);
2351         callCheck(mode);
2352         return result;
2353     }
2354     LValue vmCall(LValue function, LValue arg1, ExceptionCheckMode mode = CheckExceptions)
2355     {
2356         callPreflight();
2357         LValue result = m_out.call(function, arg1);
2358         callCheck(mode);
2359         return result;
2360     }
2361     LValue vmCall(LValue function, LValue arg1, LValue arg2, ExceptionCheckMode mode = CheckExceptions)
2362     {
2363         callPreflight();
2364         LValue result = m_out.call(function, arg1, arg2);
2365         callCheck(mode);
2366         return result;
2367     }
2368     LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, ExceptionCheckMode mode = CheckExceptions)
2369     {
2370         callPreflight();
2371         LValue result = m_out.call(function, arg1, arg2, arg3);
2372         callCheck(mode);
2373         return result;
2374     }
2375     LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, ExceptionCheckMode mode = CheckExceptions)
2376     {
2377         callPreflight();
2378         LValue result = m_out.call(function, arg1, arg2, arg3, arg4);
2379         callCheck(mode);
2380         return result;
2381     }
2382     
2383     void callPreflight(CodeOrigin codeOrigin)
2384     {
2385         m_out.store32(
2386             m_out.constInt32(
2387                 CallFrame::Location::encodeAsCodeOriginIndex(
2388                     codeBlock()->addCodeOrigin(codeOrigin))), 
2389             tagFor(JSStack::ArgumentCount));
2390     }
2391     void callPreflight()
2392     {
2393         callPreflight(m_node->codeOrigin);
2394     }
2395     
2396     void callCheck(ExceptionCheckMode mode = CheckExceptions)
2397     {
2398         if (mode == NoExceptions)
2399             return;
2400         
2401         LBasicBlock didHaveException = FTL_NEW_BLOCK(m_out, ("Did have exception"));
2402         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Exception check continuation"));
2403         
2404         m_out.branch(
2405             m_out.notZero64(m_out.load64(m_out.absolute(vm().addressOfException()))),
2406             didHaveException, continuation);
2407         
2408         LBasicBlock lastNext = m_out.appendTo(didHaveException, continuation);
2409         // FIXME: Handle exceptions. https://bugs.webkit.org/show_bug.cgi?id=113622
2410         m_out.crash();
2411         
2412         m_out.appendTo(continuation, lastNext);
2413     }
2414     
2415     bool isLive(Node* node)
2416     {
2417         return m_live.contains(node);
2418     }
2419     
2420     void use(Edge edge)
2421     {
2422         ASSERT(edge->hasResult());
2423         if (!edge.doesKill())
2424             return;
2425         m_live.remove(edge.node());
2426     }
2427     
2428     // Wrapper used only for DFG_NODE_DO_TO_CHILDREN
2429     void use(Node*, Edge edge)
2430     {
2431         use(edge);
2432     }
2433     
2434     LBasicBlock lowBlock(BasicBlock* block)
2435     {
2436         return m_blocks.get(block);
2437     }
2438     
2439     void initializeOSRExitStateForBlock()
2440     {
2441         for (unsigned i = m_valueSources.size(); i--;) {
2442             FlushFormat format = m_highBlock->ssa->flushFormatAtHead[i];
2443             switch (format) {
2444             case DeadFlush: {
2445                 // Must consider available nodes instead.
2446                 Node* node = m_highBlock->ssa->availabilityAtHead[i];
2447                 if (!node) {
2448                     m_valueSources[i] = ValueSource(SourceIsDead);
2449                     break;
2450                 }
2451                 
2452                 m_valueSources[i] = ValueSource(node);
2453                 break;
2454             }
2455                 
2456             case FlushedInt32:
2457                 m_valueSources[i] = ValueSource(Int32InJSStack);
2458                 break;
2459                 
2460             case FlushedDouble:
2461                 m_valueSources[i] = ValueSource(DoubleInJSStack);
2462                 break;
2463                 
2464             case FlushedCell:
2465             case FlushedBoolean:
2466             case FlushedJSValue:
2467                 m_valueSources[i] = ValueSource(ValueInJSStack);
2468                 break;
2469             }
2470         }
2471     }
2472     
2473     void appendOSRExit(
2474         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
2475         SpeculationDirection direction, FormattedValue recovery)
2476     {
2477         if (Options::ftlTrapsOnOSRExit()) {
2478             LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("OSR exit failCase for ", m_node));
2479             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("OSR exit continuation for ", m_node));
2480             
2481             m_out.branch(failCondition, failCase, continuation);
2482             
2483             LBasicBlock lastNext = m_out.appendTo(failCase, continuation);
2484             m_out.trap();
2485             m_out.unreachable();
2486             
2487             m_out.appendTo(continuation, lastNext);
2488             return;
2489         }
2490         
2491         if (verboseCompilationEnabled())
2492             dataLog("    OSR exit with value sources: ", m_valueSources, "\n");
2493         
2494         ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.osrExit.size());
2495         unsigned index = m_ftlState.osrExit.size();
2496         
2497         m_ftlState.jitCode->osrExit.append(OSRExit(
2498             kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
2499             m_codeOriginForExitTarget, m_codeOriginForExitProfile, m_lastSetOperand,
2500             m_valueSources.numberOfArguments(), m_valueSources.numberOfLocals()));
2501         m_ftlState.osrExit.append(OSRExitCompilationInfo());
2502         
2503         OSRExit& exit = m_ftlState.jitCode->osrExit.last();
2504         OSRExitCompilationInfo& info = m_ftlState.osrExit.last();
2505
2506         LBasicBlock lastNext = 0;
2507         LBasicBlock continuation = 0;
2508         
2509         if (!Options::useLLVMOSRExitIntrinsic()) {
2510             LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("OSR exit failCase for ", m_node));
2511             continuation = FTL_NEW_BLOCK(m_out, ("OSR exit continuation for ", m_node));
2512             
2513             m_out.branch(failCondition, failCase, continuation);
2514
2515             m_out.appendTo(m_prologue);
2516             info.m_thunkAddress = buildAlloca(m_out.m_builder, m_out.intPtr);
2517         
2518             lastNext = m_out.appendTo(failCase, continuation);
2519         }
2520         
2521         if (Options::ftlOSRExitOmitsMarshalling()) {
2522             m_out.call(
2523                 m_out.intToPtr(
2524                     m_out.get(info.m_thunkAddress),
2525                     pointerType(functionType(m_out.voidType))));
2526         } else
2527             emitOSRExitCall(failCondition, index, exit, info, lowValue, direction, recovery);
2528         
2529         if (!Options::useLLVMOSRExitIntrinsic()) {
2530             m_out.unreachable();
2531             
2532             m_out.appendTo(continuation, lastNext);
2533         
2534             m_exitThunkGenerator.emitThunk(index);
2535         }
2536     }
2537     
2538     void emitOSRExitCall(
2539         LValue failCondition, unsigned index, OSRExit& exit, OSRExitCompilationInfo& info,
2540         FormattedValue lowValue, SpeculationDirection direction, FormattedValue recovery)
2541     {
2542         ExitArgumentList arguments;
2543         
2544         if (Options::useLLVMOSRExitIntrinsic()) {
2545             arguments.append(failCondition);
2546             arguments.append(m_out.constInt32(index));
2547         }
2548         
2549         arguments.append(m_callFrame);
2550         if (!!lowValue)
2551             arguments.append(lowValue.value());
2552         
2553         for (unsigned i = 0; i < exit.m_values.size(); ++i) {
2554             ValueSource source = m_valueSources[i];
2555             
2556             switch (source.kind()) {
2557             case ValueInJSStack:
2558                 exit.m_values[i] = ExitValue::inJSStack();
2559                 break;
2560             case Int32InJSStack:
2561                 exit.m_values[i] = ExitValue::inJSStackAsInt32();
2562                 break;
2563             case DoubleInJSStack:
2564                 exit.m_values[i] = ExitValue::inJSStackAsDouble();
2565                 break;
2566             case SourceIsDead:
2567                 exit.m_values[i] = ExitValue::dead();
2568                 break;
2569             case HaveNode:
2570                 addExitArgumentForNode(exit, arguments, i, source.node());
2571                 break;
2572             default:
2573                 RELEASE_ASSERT_NOT_REACHED();
2574                 break;
2575             }
2576         }
2577         
2578         if (verboseCompilationEnabled())
2579             dataLog("        Exit values: ", exit.m_values, "\n");
2580         
2581         if (direction == ForwardSpeculation) {
2582             ASSERT(m_node);
2583             exit.convertToForward(m_highBlock, m_node, m_nodeIndex, recovery, arguments);
2584         }
2585         
2586         // So, the really lame thing here is that we have to build an LLVM function type.
2587         // Booo.
2588         Vector<LType, 16> argumentTypes;
2589         for (unsigned i = 0; i < arguments.size(); ++i)
2590             argumentTypes.append(typeOf(arguments[i]));
2591         
2592         if (Options::useLLVMOSRExitIntrinsic()) {
2593             m_out.call(m_out.osrExitIntrinsic(), arguments);
2594             return;
2595         }
2596         
2597         m_out.call(
2598             m_out.intToPtr(
2599                 m_out.get(info.m_thunkAddress),
2600                 pointerType(functionType(m_out.voidType, argumentTypes))),
2601             arguments);
2602     }
2603     
2604     void addExitArgumentForNode(
2605         OSRExit& exit, ExitArgumentList& arguments, unsigned index, Node* node)
2606     {
2607         ASSERT(node->shouldGenerate());
2608         ASSERT(node->hasResult());
2609
2610         if (tryToSetConstantExitArgument(exit, index, node))
2611             return;
2612         
2613         if (!isLive(node)) {
2614             bool found = false;
2615             
2616             if (needsOSRBackwardRewiring(node->op())) {
2617                 node = node->child1().node();
2618                 if (tryToSetConstantExitArgument(exit, index, node))
2619                     return;
2620                 if (isLive(node))
2621                     found = true;
2622             }
2623             
2624             if (!found) {
2625                 Node* int32ToDouble = 0;
2626                 Node* valueToInt32 = 0;
2627                 Node* uint32ToNumber = 0;
2628                 Node* doubleAsInt32 = 0;
2629                 
2630                 HashSet<Node*>::iterator iter = m_live.begin();
2631                 HashSet<Node*>::iterator end = m_live.end();
2632                 for (; iter != end; ++iter) {
2633                     Node* candidate = *iter;
2634                     if (!candidate->child1())
2635                         continue;
2636                     if (candidate->child1() != node)
2637                         continue;
2638                     switch (candidate->op()) {
2639                     case Int32ToDouble:
2640                         int32ToDouble = candidate;
2641                         break;
2642                     case ValueToInt32:
2643                         valueToInt32 = candidate;
2644                         break;
2645                     case UInt32ToNumber:
2646                         uint32ToNumber = candidate;
2647                         break;
2648                     case DoubleAsInt32:
2649                         uint32ToNumber = candidate;
2650                         break;
2651                     default:
2652                         ASSERT(!needsOSRForwardRewiring(candidate->op()));
2653                         break;
2654                     }
2655                 }
2656                 
2657                 if (doubleAsInt32)
2658                     node = doubleAsInt32;
2659                 else if (int32ToDouble)
2660                     node = int32ToDouble;
2661                 else if (valueToInt32)
2662                     node = valueToInt32;
2663                 else if (uint32ToNumber)
2664                     node = uint32ToNumber;
2665                 
2666                 if (isLive(node))
2667                     found = true;
2668             }
2669             
2670             if (!found) {
2671                 exit.m_values[index] = ExitValue::dead();
2672                 return;
2673             }
2674         }
2675         
2676         ASSERT(isLive(node));
2677
2678         LoweredNodeValue value = m_int32Values.get(node);
2679         if (isValid(value)) {
2680             addExitArgument(exit, arguments, index, ValueFormatInt32, value.value());
2681             return;
2682         }
2683         
2684         value = m_booleanValues.get(node);
2685         if (isValid(value)) {
2686             addExitArgument(exit, arguments, index, ValueFormatBoolean, value.value());
2687             return;
2688         }
2689         
2690         value = m_jsValueValues.get(node);
2691         if (isValid(value)) {
2692             addExitArgument(exit, arguments, index, ValueFormatJSValue, value.value());
2693             return;
2694         }
2695         
2696         value = m_doubleValues.get(node);
2697         if (isValid(value)) {
2698             addExitArgument(exit, arguments, index, ValueFormatDouble, value.value());
2699             return;
2700         }
2701
2702         dataLog("Cannot find value for node: ", node, "\n");
2703         RELEASE_ASSERT_NOT_REACHED();
2704     }
2705     
2706     bool tryToSetConstantExitArgument(OSRExit& exit, unsigned index, Node* node)
2707     {
2708         if (!node)
2709             return false;
2710         
2711         switch (node->op()) {
2712         case JSConstant:
2713         case WeakJSConstant:
2714             exit.m_values[index] = ExitValue::constant(m_graph.valueOfJSConstant(node));
2715             return true;
2716         case PhantomArguments:
2717             // FIXME: implement PhantomArguments.
2718             // https://bugs.webkit.org/show_bug.cgi?id=113986
2719             RELEASE_ASSERT_NOT_REACHED();
2720             return true;
2721         default:
2722             return false;
2723         }
2724     }
2725     
2726     void addExitArgument(
2727         OSRExit& exit, ExitArgumentList& arguments, unsigned index, ValueFormat format,
2728         LValue value)
2729     {
2730         exit.m_values[index] = ExitValue::exitArgument(ExitArgument(format, arguments.size()));
2731         arguments.append(value);
2732     }
2733     
2734     void linkOSRExitsAndCompleteInitializationBlocks()
2735     {
2736         MacroAssemblerCodeRef osrExitThunk =
2737             vm().getCTIStub(osrExitGenerationThunkGenerator);
2738         CodeLocationLabel target = CodeLocationLabel(osrExitThunk.code());
2739         
2740         m_out.appendTo(m_prologue);
2741         m_out.jump(m_initialization);
2742         
2743         m_out.appendTo(m_initialization);
2744         
2745         if (m_exitThunkGenerator.didThings()) {
2746             OwnPtr<LinkBuffer> linkBuffer = adoptPtr(new LinkBuffer(
2747                 vm(), &m_exitThunkGenerator, m_ftlState.graph.m_codeBlock,
2748                 JITCompilationMustSucceed));
2749         
2750             ASSERT(m_ftlState.osrExit.size() == m_ftlState.jitCode->osrExit.size());
2751         
2752             for (unsigned i = 0; i < m_ftlState.osrExit.size(); ++i) {
2753                 OSRExitCompilationInfo& info = m_ftlState.osrExit[i];
2754                 OSRExit& exit = m_ftlState.jitCode->osrExit[i];
2755             
2756                 linkBuffer->link(info.m_thunkJump, target);
2757             
2758                 m_out.set(
2759                     m_out.constIntPtr(
2760                         linkBuffer->locationOf(info.m_thunkLabel).executableAddress()),
2761                     info.m_thunkAddress);
2762             
2763                 exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump);
2764             }
2765         
2766             m_ftlState.finalizer->initializeExitThunksLinkBuffer(linkBuffer.release());
2767         }
2768
2769         m_out.jump(lowBlock(m_graph.block(0)));
2770     }
2771     
2772     void observeMovHint(Node* node)
2773     {
2774         ASSERT(node->containsMovHint());
2775         ASSERT(node->op() != ZombieHint);
2776         
2777         int operand = node->local();
2778         
2779         m_lastSetOperand = operand;
2780         m_valueSources.operand(operand) = ValueSource(node->child1().node());
2781     }
2782     
2783     void setInt32(Node* node, LValue value)
2784     {
2785         m_int32Values.set(node, LoweredNodeValue(value, m_highBlock));
2786     }
2787     void setJSValue(Node* node, LValue value)
2788     {
2789         m_jsValueValues.set(node, LoweredNodeValue(value, m_highBlock));
2790     }
2791     void setBoolean(Node* node, LValue value)
2792     {
2793         m_booleanValues.set(node, LoweredNodeValue(value, m_highBlock));
2794     }
2795     void setStorage(Node* node, LValue value)
2796     {
2797         m_storageValues.set(node, LoweredNodeValue(value, m_highBlock));
2798     }
2799     void setDouble(Node* node, LValue value)
2800     {
2801         m_doubleValues.set(node, LoweredNodeValue(value, m_highBlock));
2802     }
2803
2804     void setInt32(LValue value)
2805     {
2806         setInt32(m_node, value);
2807     }
2808     void setJSValue(LValue value)
2809     {
2810         setJSValue(m_node, value);
2811     }
2812     void setBoolean(LValue value)
2813     {
2814         setBoolean(m_node, value);
2815     }
2816     void setStorage(LValue value)
2817     {
2818         setStorage(m_node, value);
2819     }
2820     void setDouble(LValue value)
2821     {
2822         setDouble(m_node, value);
2823     }
2824     
2825     bool isValid(const LoweredNodeValue& value)
2826     {
2827         if (!value)
2828             return false;
2829         if (!m_graph.m_dominators.dominates(value.block(), m_highBlock))
2830             return false;
2831         return true;
2832     }
2833     
2834     void addWeakReference(JSCell* target)
2835     {
2836         m_graph.m_plan.weakReferences.addLazily(target);
2837     }
2838     
2839     LValue weakPointer(JSCell* pointer)
2840     {
2841         addWeakReference(pointer);
2842         return m_out.constIntPtr(pointer);
2843     }
2844     
2845     TypedPointer addressFor(LValue base, int operand, ptrdiff_t offset = 0)
2846     {
2847         return m_out.address(base, m_heaps.variables[operand], offset);
2848     }
2849     TypedPointer payloadFor(LValue base, int operand)
2850     {
2851         return addressFor(base, operand, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
2852     }
2853     TypedPointer tagFor(LValue base, int operand)
2854     {
2855         return addressFor(base, operand, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
2856     }
2857     TypedPointer addressFor(int operand)
2858     {
2859         return addressFor(m_callFrame, operand);
2860     }
2861     TypedPointer payloadFor(int operand)
2862     {
2863         return payloadFor(m_callFrame, operand);
2864     }
2865     TypedPointer tagFor(int operand)
2866     {
2867         return tagFor(m_callFrame, operand);
2868     }
2869     
2870     VM& vm() { return m_graph.m_vm; }
2871     CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
2872     
2873     Graph& m_graph;
2874     State& m_ftlState;
2875     AbstractHeapRepository m_heaps;
2876     Output m_out;
2877     
2878     LBasicBlock m_prologue;
2879     LBasicBlock m_initialization;
2880     HashMap<BasicBlock*, LBasicBlock> m_blocks;
2881     
2882     LValue m_callFrame;
2883     LValue m_tagTypeNumber;
2884     LValue m_tagMask;
2885     
2886     HashMap<Node*, LoweredNodeValue> m_int32Values;
2887     HashMap<Node*, LoweredNodeValue> m_jsValueValues;
2888     HashMap<Node*, LoweredNodeValue> m_booleanValues;
2889     HashMap<Node*, LoweredNodeValue> m_storageValues;
2890     HashMap<Node*, LoweredNodeValue> m_doubleValues;
2891     HashSet<Node*> m_live;
2892     
2893     HashMap<Node*, LValue> m_phis;
2894     
2895     Operands<ValueSource> m_valueSources;
2896     int m_lastSetOperand;
2897     ExitThunkGenerator m_exitThunkGenerator;
2898     
2899     InPlaceAbstractState m_state;
2900     AbstractInterpreter<InPlaceAbstractState> m_interpreter;
2901     BasicBlock* m_highBlock;
2902     BasicBlock* m_nextHighBlock;
2903     LBasicBlock m_nextLowBlock;
2904     
2905     CodeOrigin m_codeOriginForExitTarget;
2906     CodeOrigin m_codeOriginForExitProfile;
2907     unsigned m_nodeIndex;
2908     Node* m_node;
2909     SpeculationDirection m_direction;
2910 };
2911
2912 void lowerDFGToLLVM(State& state)
2913 {
2914     LowerDFGToLLVM lowering(state);
2915     lowering.lower();
2916 }
2917
2918 } } // namespace JSC::FTL
2919
2920 #endif // ENABLE(FTL_JIT)
2921