FTL ArithMod Int32Use doesn't check for negative zero correctly
[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             LValue remainder = m_out.rem(numerator, denominator);
859             
860             if (!nodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
861                 LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod negative numerator"));
862                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation"));
863                 
864                 m_out.branch(
865                     m_out.lessThan(numerator, m_out.int32Zero),
866                     negativeNumerator, numeratorContinuation);
867                 
868                 LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
869                 
870                 speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
871                 
872                 m_out.jump(numeratorContinuation);
873                 
874                 m_out.appendTo(numeratorContinuation, innerLastNext);
875             }
876             
877             results.append(m_out.anchor(remainder));
878             m_out.jump(done);
879             
880             m_out.appendTo(done, lastNext);
881             
882             setInt32(m_out.phi(m_out.int32, results));
883             break;
884         }
885             
886         case NumberUse: {
887             setDouble(
888                 m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
889             break;
890         }
891             
892         default:
893             RELEASE_ASSERT_NOT_REACHED();
894             break;
895         }
896     }
897
898     void compileArithMinOrMax()
899     {
900         switch (m_node->binaryUseKind()) {
901         case Int32Use: {
902             LValue left = lowInt32(m_node->child1());
903             LValue right = lowInt32(m_node->child2());
904             
905             setInt32(
906                 m_out.select(
907                     m_node->op() == ArithMin
908                         ? m_out.lessThan(left, right)
909                         : m_out.lessThan(right, left),
910                     left, right));
911             break;
912         }
913             
914         case NumberUse: {
915             LValue left = lowDouble(m_node->child1());
916             LValue right = lowDouble(m_node->child2());
917             
918             LBasicBlock notLessThan = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax not less than"));
919             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax continuation"));
920             
921             Vector<ValueFromBlock, 2> results;
922             
923             results.append(m_out.anchor(left));
924             m_out.branch(
925                 m_node->op() == ArithMin
926                     ? m_out.doubleLessThan(left, right)
927                     : m_out.doubleGreaterThan(left, right),
928                 continuation, notLessThan);
929             
930             LBasicBlock lastNext = m_out.appendTo(notLessThan, continuation);
931             results.append(m_out.anchor(m_out.select(
932                 m_node->op() == ArithMin
933                     ? m_out.doubleGreaterThanOrEqual(left, right)
934                     : m_out.doubleLessThanOrEqual(left, right),
935                 right, m_out.constDouble(0.0 / 0.0))));
936             m_out.jump(continuation);
937             
938             m_out.appendTo(continuation, lastNext);
939             setDouble(m_out.phi(m_out.doubleType, results));
940             break;
941         }
942             
943         default:
944             RELEASE_ASSERT_NOT_REACHED();
945             break;
946         }
947     }
948     
949     void compileArithAbs()
950     {
951         switch (m_node->child1().useKind()) {
952         case Int32Use: {
953             LValue value = lowInt32(m_node->child1());
954             
955             LValue mask = m_out.aShr(value, m_out.constInt32(31));
956             LValue result = m_out.bitXor(mask, m_out.add(mask, value));
957             
958             speculate(Overflow, noValue(), 0, m_out.equal(result, m_out.constInt32(1 << 31)));
959             
960             setInt32(result);
961             break;
962         }
963             
964         case NumberUse: {
965             setDouble(m_out.doubleAbs(lowDouble(m_node->child1())));
966             break;
967         }
968             
969         default:
970             RELEASE_ASSERT_NOT_REACHED();
971             break;
972         }
973     }
974     
975     void compileArithNegate()
976     {
977         switch (m_node->child1().useKind()) {
978         case Int32Use: {
979             LValue value = lowInt32(m_node->child1());
980             
981             LValue result;
982             if (nodeCanTruncateInteger(m_node->arithNodeFlags()))
983                 result = m_out.neg(value);
984             else {
985                 // We don't have a negate-with-overflow intrinsic. Hopefully this
986                 // does the trick, though.
987                 LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
988                 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
989                 result = m_out.extractValue(overflowResult, 0);
990                 speculate(NegativeZero, noValue(), 0, m_out.isZero32(result));
991             }
992             
993             setInt32(result);
994             break;
995         }
996             
997         case NumberUse: {
998             setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
999             break;
1000         }
1001             
1002         default:
1003             RELEASE_ASSERT_NOT_REACHED();
1004             break;
1005         }
1006     }
1007     
1008     void compileBitAnd()
1009     {
1010         setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1011     }
1012     
1013     void compileBitOr()
1014     {
1015         setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1016     }
1017     
1018     void compileBitXor()
1019     {
1020         setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1021     }
1022     
1023     void compileBitRShift()
1024     {
1025         setInt32(m_out.aShr(
1026             lowInt32(m_node->child1()),
1027             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1028     }
1029     
1030     void compileBitLShift()
1031     {
1032         setInt32(m_out.shl(
1033             lowInt32(m_node->child1()),
1034             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1035     }
1036     
1037     void compileBitURShift()
1038     {
1039         setInt32(m_out.lShr(
1040             lowInt32(m_node->child1()),
1041             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1042     }
1043     
1044     void compileUInt32ToNumber()
1045     {
1046         LValue value = lowInt32(m_node->child1());
1047
1048         if (!nodeCanSpeculateInteger(m_node->arithNodeFlags())) {
1049             setDouble(m_out.unsignedToDouble(value));
1050             return;
1051         }
1052         
1053         speculateForward(
1054             Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero),
1055             FormattedValue(ValueFormatUInt32, value));
1056         setInt32(value);
1057     }
1058     
1059     void compileInt32ToDouble()
1060     {
1061         // This node is tricky to compile in the DFG backend because it tries to
1062         // avoid converting child1 to a double in-place, as that would make subsequent
1063         // int uses of of child1 fail. But the FTL needs no such special magic, since
1064         // unlike the DFG backend, the FTL allows each node to have multiple
1065         // contemporaneous low-level representations. So, this gives child1 a double
1066         // representation and then forwards that representation to m_node.
1067         
1068         setDouble(lowDouble(m_node->child1()));
1069     }
1070     
1071     void compileCheckStructure()
1072     {
1073         LValue cell = lowCell(m_node->child1());
1074         
1075         ExitKind exitKind;
1076         if (m_node->child1()->op() == WeakJSConstant)
1077             exitKind = BadWeakConstantCache;
1078         else
1079             exitKind = BadCache;
1080         
1081         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1082         
1083         if (m_node->structureSet().size() == 1) {
1084             speculate(
1085                 exitKind, jsValueValue(cell), 0,
1086                 m_out.notEqual(structure, weakPointer(m_node->structureSet()[0])));
1087             return;
1088         }
1089         
1090         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure continuation"));
1091         
1092         LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
1093         for (unsigned i = 0; i < m_node->structureSet().size() - 1; ++i) {
1094             LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("CheckStructure nextStructure"));
1095             m_out.branch(
1096                 m_out.equal(structure, weakPointer(m_node->structureSet()[i])),
1097                 continuation, nextStructure);
1098             m_out.appendTo(nextStructure);
1099         }
1100         
1101         speculate(
1102             exitKind, jsValueValue(cell), 0,
1103             m_out.notEqual(structure, weakPointer(m_node->structureSet().last())));
1104         
1105         m_out.jump(continuation);
1106         m_out.appendTo(continuation, lastNext);
1107     }
1108     
1109     void compileStructureTransitionWatchpoint()
1110     {
1111         addWeakReference(m_node->structure());
1112         
1113         // FIXME: Implement structure transition watchpoints.
1114         // https://bugs.webkit.org/show_bug.cgi?id=113647
1115         
1116         speculateCell(m_node->child1());
1117     }
1118     
1119     void compileArrayifyToStructure()
1120     {
1121         LValue cell = lowCell(m_node->child1());
1122         LValue property = !!m_node->child2() ? lowInt32(m_node->child2()) : 0;
1123         
1124         LBasicBlock unexpectedStructure = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure unexpected structure"));
1125         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure continuation"));
1126         
1127         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1128         
1129         m_out.branch(
1130             m_out.notEqual(structure, weakPointer(m_node->structure())),
1131             unexpectedStructure, continuation);
1132         
1133         LBasicBlock lastNext = m_out.appendTo(unexpectedStructure, continuation);
1134         
1135         if (property) {
1136             switch (m_node->arrayMode().type()) {
1137             case Array::Int32:
1138             case Array::Double:
1139             case Array::Contiguous:
1140                 speculate(
1141                     Uncountable, noValue(), 0,
1142                     m_out.aboveOrEqual(property, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)));
1143                 break;
1144             default:
1145                 break;
1146             }
1147         }
1148         
1149         switch (m_node->arrayMode().type()) {
1150         case Array::Int32:
1151             vmCall(m_out.operation(operationEnsureInt32), m_callFrame, cell);
1152             break;
1153         case Array::Double:
1154             vmCall(m_out.operation(operationEnsureDouble), m_callFrame, cell);
1155             break;
1156         case Array::Contiguous:
1157             if (m_node->arrayMode().conversion() == Array::RageConvert)
1158                 vmCall(m_out.operation(operationRageEnsureContiguous), m_callFrame, cell);
1159             else
1160                 vmCall(m_out.operation(operationEnsureContiguous), m_callFrame, cell);
1161             break;
1162         case Array::ArrayStorage:
1163         case Array::SlowPutArrayStorage:
1164             vmCall(m_out.operation(operationEnsureArrayStorage), m_callFrame, cell);
1165             break;
1166         default:
1167             RELEASE_ASSERT_NOT_REACHED();
1168             break;
1169         }
1170         
1171         structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1172         speculate(
1173             BadIndexingType, jsValueValue(cell), 0,
1174             m_out.notEqual(structure, weakPointer(m_node->structure())));
1175         m_out.jump(continuation);
1176         
1177         m_out.appendTo(continuation, lastNext);
1178     }
1179     
1180     void compilePutStructure()
1181     {
1182         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1183         
1184         m_out.store64(
1185             m_out.constIntPtr(m_node->structureTransitionData().newStructure),
1186             lowCell(m_node->child1()), m_heaps.JSCell_structure);
1187     }
1188     
1189     void compilePhantomPutStructure()
1190     {
1191         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1192     }
1193     
1194     void compileGetButterfly()
1195     {
1196         setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly));
1197     }
1198     
1199     void compileGetArrayLength()
1200     {
1201         switch (m_node->arrayMode().type()) {
1202         case Array::Int32:
1203         case Array::Double:
1204         case Array::Contiguous: {
1205             setInt32(m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
1206             break;
1207         }
1208             
1209         default:
1210             RELEASE_ASSERT_NOT_REACHED();
1211             break;
1212         }
1213     }
1214     
1215     void compileGetByVal()
1216     {
1217         LValue index = lowInt32(m_node->child2());
1218         LValue storage = lowStorage(m_node->child3());
1219         
1220         switch (m_node->arrayMode().type()) {
1221         case Array::Int32:
1222         case Array::Contiguous: {
1223             if (m_node->arrayMode().isInBounds()) {
1224                 speculate(
1225                     OutOfBounds, noValue(), 0,
1226                     m_out.aboveOrEqual(
1227                         index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
1228                 
1229                 LValue result = m_out.load64(m_out.baseIndex(
1230                     m_node->arrayMode().type() == Array::Int32 ?
1231                         m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
1232                     storage, m_out.zeroExt(index, m_out.intPtr),
1233                     m_state.forNode(m_node->child2()).m_value));
1234                 speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result));
1235                 setJSValue(result);
1236                 return;
1237             }
1238             
1239             // FIXME: Implement hole/OOB loads in the FTL.
1240             // https://bugs.webkit.org/show_bug.cgi?id=118077
1241             RELEASE_ASSERT_NOT_REACHED();
1242             return;
1243         }
1244             
1245         case Array::Double: {
1246             if (m_node->arrayMode().isInBounds()) {
1247                 if (m_node->arrayMode().isSaneChain()) {
1248                     // FIXME: Implement structure transition watchpoints.
1249                     // https://bugs.webkit.org/show_bug.cgi?id=113647
1250                 }
1251             
1252                 speculate(
1253                     OutOfBounds, noValue(), 0,
1254                     m_out.aboveOrEqual(
1255                         index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
1256                 
1257                 LValue result = m_out.loadDouble(m_out.baseIndex(
1258                     m_heaps.indexedDoubleProperties,
1259                     storage, m_out.zeroExt(index, m_out.intPtr),
1260                     m_state.forNode(m_node->child2()).m_value));
1261                 
1262                 if (!m_node->arrayMode().isSaneChain()) {
1263                     speculate(
1264                         LoadFromHole, noValue(), 0,
1265                         m_out.doubleNotEqualOrUnordered(result, result));
1266                 }
1267                 setDouble(result);
1268                 break;
1269             }
1270             
1271             // FIXME: Implement hole/OOB loads in the FTL.
1272             // https://bugs.webkit.org/show_bug.cgi?id=118077
1273             RELEASE_ASSERT_NOT_REACHED();
1274             return;
1275         }
1276             
1277         default:
1278             RELEASE_ASSERT_NOT_REACHED();
1279             return;
1280         }
1281     }
1282     
1283     void compilePutByVal()
1284     {
1285         Edge child1 = m_graph.varArgChild(m_node, 0);
1286         Edge child2 = m_graph.varArgChild(m_node, 1);
1287         Edge child3 = m_graph.varArgChild(m_node, 2);
1288         Edge child4 = m_graph.varArgChild(m_node, 3);
1289
1290         LValue base = lowCell(child1);
1291         LValue index = lowInt32(child2);
1292         LValue storage = lowStorage(child4);
1293         
1294         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
1295         LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
1296             
1297         switch (m_node->arrayMode().type()) {
1298         case Array::Int32:
1299         case Array::Contiguous: {
1300             LValue value = lowJSValue(child3, ManualOperandSpeculation);
1301             
1302             if (m_node->arrayMode().type() == Array::Int32)
1303                 FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
1304             
1305             TypedPointer elementPointer = m_out.baseIndex(
1306                 m_node->arrayMode().type() == Array::Int32 ?
1307                 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
1308                 storage, m_out.zeroExt(index, m_out.intPtr),
1309                 m_state.forNode(child2).m_value);
1310             
1311             if (m_node->op() == PutByValAlias) {
1312                 m_out.store64(value, elementPointer);
1313                 break;
1314             }
1315             
1316             contiguousPutByValOutOfBounds(
1317                 codeBlock()->isStrictMode()
1318                     ? operationPutByValBeyondArrayBoundsStrict
1319                     : operationPutByValBeyondArrayBoundsNonStrict,
1320                 base, storage, index, value, continuation);
1321             
1322             m_out.store64(value, elementPointer);
1323             break;
1324         }
1325             
1326         case Array::Double: {
1327             LValue value = lowDouble(child3);
1328             
1329             FTL_TYPE_CHECK(
1330                 doubleValue(value), child3, SpecRealNumber,
1331                 m_out.doubleNotEqualOrUnordered(value, value));
1332             
1333             TypedPointer elementPointer = m_out.baseIndex(
1334                 m_heaps.indexedDoubleProperties,
1335                 storage, m_out.zeroExt(index, m_out.intPtr),
1336                 m_state.forNode(child2).m_value);
1337
1338             if (m_node->op() == PutByValAlias) {
1339                 m_out.storeDouble(value, elementPointer);
1340                 break;
1341             }
1342             
1343             contiguousPutByValOutOfBounds(
1344                 codeBlock()->isStrictMode()
1345                     ? operationPutDoubleByValBeyondArrayBoundsStrict
1346                     : operationPutDoubleByValBeyondArrayBoundsNonStrict,
1347                 base, storage, index, value, continuation);
1348             
1349             m_out.storeDouble(value, elementPointer);
1350             break;
1351         }
1352             
1353         default:
1354             RELEASE_ASSERT_NOT_REACHED();
1355             break;
1356         }
1357
1358         m_out.jump(continuation);
1359         m_out.appendTo(continuation, outerLastNext);
1360     }
1361     
1362     void compileGetByOffset()
1363     {
1364         StorageAccessData& data =
1365             m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
1366         
1367         setJSValue(
1368             m_out.load64(
1369                 m_out.address(
1370                     m_heaps.properties[data.identifierNumber],
1371                     lowStorage(m_node->child1()),
1372                     offsetRelativeToBase(data.offset))));
1373     }
1374     
1375     void compilePutByOffset()
1376     {
1377         StorageAccessData& data =
1378             m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
1379         
1380         m_out.store64(
1381             lowJSValue(m_node->child3()),
1382             m_out.address(
1383                 m_heaps.properties[data.identifierNumber],
1384                 lowStorage(m_node->child1()),
1385                 offsetRelativeToBase(data.offset)));
1386     }
1387     
1388     void compileGetGlobalVar()
1389     {
1390         setJSValue(m_out.load64(m_out.absolute(m_node->registerPointer())));
1391     }
1392     
1393     void compilePutGlobalVar()
1394     {
1395         m_out.store64(
1396             lowJSValue(m_node->child1()), m_out.absolute(m_node->registerPointer()));
1397     }
1398     
1399     void compileCompareEq()
1400     {
1401         if (m_node->isBinaryUseKind(Int32Use)
1402             || m_node->isBinaryUseKind(NumberUse)
1403             || m_node->isBinaryUseKind(ObjectUse)) {
1404             compileCompareStrictEq();
1405             return;
1406         }
1407         
1408         RELEASE_ASSERT_NOT_REACHED();
1409     }
1410     
1411     void compileCompareEqConstant()
1412     {
1413         ASSERT(m_graph.valueOfJSConstant(m_node->child2().node()).isNull());
1414         masqueradesAsUndefinedWatchpointIfIsStillValid();
1415         setBoolean(
1416             equalNullOrUndefined(
1417                 m_node->child1(), AllCellsAreFalse, EqualNullOrUndefined));
1418     }
1419     
1420     void compileCompareStrictEq()
1421     {
1422         if (m_node->isBinaryUseKind(Int32Use)) {
1423             setBoolean(
1424                 m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1425             return;
1426         }
1427         
1428         if (m_node->isBinaryUseKind(NumberUse)) {
1429             setBoolean(
1430                 m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1431         }
1432         
1433         if (m_node->isBinaryUseKind(ObjectUse)) {
1434             masqueradesAsUndefinedWatchpointIfIsStillValid();
1435             setBoolean(
1436                 m_out.equal(
1437                     lowNonNullObject(m_node->child1()),
1438                     lowNonNullObject(m_node->child2())));
1439             return;
1440         }
1441         
1442         RELEASE_ASSERT_NOT_REACHED();
1443     }
1444     
1445     void compileCompareStrictEqConstant()
1446     {
1447         JSValue constant = m_graph.valueOfJSConstant(m_node->child2().node());
1448
1449         if (constant.isUndefinedOrNull()
1450             && !masqueradesAsUndefinedWatchpointIfIsStillValid()) {
1451             if (constant.isNull()) {
1452                 setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualNull));
1453                 return;
1454             }
1455         
1456             ASSERT(constant.isUndefined());
1457             setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualUndefined));
1458             return;
1459         }
1460         
1461         setBoolean(
1462             m_out.equal(
1463                 lowJSValue(m_node->child1()),
1464                 m_out.constInt64(JSValue::encode(constant))));
1465     }
1466     
1467     void compileCompareLess()
1468     {
1469         if (m_node->isBinaryUseKind(Int32Use)) {
1470             setBoolean(
1471                 m_out.lessThan(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1472             return;
1473         }
1474         
1475         if (m_node->isBinaryUseKind(NumberUse)) {
1476             setBoolean(
1477                 m_out.doubleLessThan(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1478             return;
1479         }
1480         
1481         RELEASE_ASSERT_NOT_REACHED();
1482     }
1483     
1484     void compileCompareLessEq()
1485     {
1486         if (m_node->isBinaryUseKind(Int32Use)) {
1487             setBoolean(
1488                 m_out.lessThanOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1489             return;
1490         }
1491         
1492         if (m_node->isBinaryUseKind(NumberUse)) {
1493             setBoolean(
1494                 m_out.doubleLessThanOrEqual(
1495                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1496             return;
1497         }
1498         
1499         RELEASE_ASSERT_NOT_REACHED();
1500     }
1501     
1502     void compileCompareGreater()
1503     {
1504         if (m_node->isBinaryUseKind(Int32Use)) {
1505             setBoolean(
1506                 m_out.greaterThan(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1507             return;
1508         }
1509         
1510         if (m_node->isBinaryUseKind(NumberUse)) {
1511             setBoolean(
1512                 m_out.doubleGreaterThan(
1513                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1514             return;
1515         }
1516         
1517         RELEASE_ASSERT_NOT_REACHED();
1518     }
1519     
1520     void compileCompareGreaterEq()
1521     {
1522         if (m_node->isBinaryUseKind(Int32Use)) {
1523             setBoolean(
1524                 m_out.greaterThanOrEqual(
1525                     lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1526             return;
1527         }
1528         
1529         if (m_node->isBinaryUseKind(NumberUse)) {
1530             setBoolean(
1531                 m_out.doubleGreaterThanOrEqual(
1532                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1533             return;
1534         }
1535         
1536         RELEASE_ASSERT_NOT_REACHED();
1537     }
1538     
1539     void compileLogicalNot()
1540     {
1541         setBoolean(m_out.bitNot(boolify(m_node->child1())));
1542     }
1543     
1544     void compileJump()
1545     {
1546         m_out.jump(lowBlock(m_node->takenBlock()));
1547     }
1548     
1549     void compileBranch()
1550     {
1551         m_out.branch(
1552             boolify(m_node->child1()),
1553             lowBlock(m_node->takenBlock()),
1554             lowBlock(m_node->notTakenBlock()));
1555     }
1556     
1557     void compileSwitch()
1558     {
1559         SwitchData* data = m_node->switchData();
1560         switch (data->kind) {
1561         case SwitchImm: {
1562             Vector<ValueFromBlock, 2> intValues;
1563             LBasicBlock switchOnInts = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm int case"));
1564             
1565             LBasicBlock lastNext = m_out.appendTo(m_out.m_block, switchOnInts);
1566             
1567             switch (m_node->child1().useKind()) {
1568             case Int32Use: {
1569                 intValues.append(m_out.anchor(lowInt32(m_node->child1())));
1570                 m_out.jump(switchOnInts);
1571                 break;
1572             }
1573                 
1574             case UntypedUse: {
1575                 LBasicBlock isInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is int"));
1576                 LBasicBlock isNotInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is not int"));
1577                 LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is double"));
1578                 
1579                 LValue boxedValue = lowJSValue(m_node->child1());
1580                 m_out.branch(isNotInt32(boxedValue), isNotInt, isInt);
1581                 
1582                 LBasicBlock innerLastNext = m_out.appendTo(isInt, isNotInt);
1583                 
1584                 intValues.append(m_out.anchor(unboxInt32(boxedValue)));
1585                 m_out.jump(switchOnInts);
1586                 
1587                 m_out.appendTo(isNotInt, isDouble);
1588                 m_out.branch(
1589                     isCellOrMisc(boxedValue), lowBlock(data->fallThrough), isDouble);
1590                 
1591                 m_out.appendTo(isDouble, innerLastNext);
1592                 LValue doubleValue = unboxDouble(boxedValue);
1593                 LValue intInDouble = m_out.fpToInt32(doubleValue);
1594                 intValues.append(m_out.anchor(intInDouble));
1595                 m_out.branch(
1596                     m_out.doubleEqual(m_out.intToDouble(intInDouble), doubleValue),
1597                     switchOnInts, lowBlock(data->fallThrough));
1598                 break;
1599             }
1600                 
1601             default:
1602                 RELEASE_ASSERT_NOT_REACHED();
1603                 break;
1604             }
1605             
1606             m_out.appendTo(switchOnInts, lastNext);
1607             buildSwitch(data, m_out.int32, m_out.phi(m_out.int32, intValues));
1608             return;
1609         }
1610         
1611         case SwitchChar: {
1612             LValue stringValue;
1613             
1614             switch (m_node->child1().useKind()) {
1615             case StringUse: {
1616                 stringValue = lowString(m_node->child1());
1617                 break;
1618             }
1619                 
1620             case UntypedUse: {
1621                 LValue unboxedValue = lowJSValue(m_node->child1());
1622                 
1623                 LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar is cell"));
1624                 LBasicBlock isStringCase = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar is string"));
1625                 
1626                 m_out.branch(
1627                     isNotCell(unboxedValue), lowBlock(data->fallThrough), isCellCase);
1628                 
1629                 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
1630                 LValue cellValue = unboxedValue;
1631                 m_out.branch(isNotString(cellValue), lowBlock(data->fallThrough), isStringCase);
1632                 
1633                 m_out.appendTo(isStringCase, lastNext);
1634                 stringValue = cellValue;
1635                 break;
1636             }
1637                 
1638             default:
1639                 RELEASE_ASSERT_NOT_REACHED();
1640                 break;
1641             }
1642             
1643             LBasicBlock lengthIs1 = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar length is 1"));
1644             LBasicBlock needResolution = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar resolution"));
1645             LBasicBlock resolved = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar resolved"));
1646             LBasicBlock is8Bit = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar 8bit"));
1647             LBasicBlock is16Bit = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar 16bit"));
1648             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar continuation"));
1649             
1650             m_out.branch(
1651                 m_out.notEqual(
1652                     m_out.load32(stringValue, m_heaps.JSString_length),
1653                     m_out.int32One),
1654                 lowBlock(data->fallThrough), lengthIs1);
1655             
1656             LBasicBlock lastNext = m_out.appendTo(lengthIs1, needResolution);
1657             Vector<ValueFromBlock, 2> values;
1658             LValue fastValue = m_out.loadPtr(stringValue, m_heaps.JSString_value);
1659             values.append(m_out.anchor(fastValue));
1660             m_out.branch(m_out.isNull(fastValue), needResolution, resolved);
1661             
1662             m_out.appendTo(needResolution, resolved);
1663             values.append(m_out.anchor(
1664                 vmCall(m_out.operation(operationResolveRope), m_callFrame, stringValue)));
1665             m_out.jump(resolved);
1666             
1667             m_out.appendTo(resolved, is8Bit);
1668             LValue value = m_out.phi(m_out.intPtr, values);
1669             LValue characterData = m_out.loadPtr(value, m_heaps.StringImpl_data);
1670             m_out.branch(
1671                 m_out.testNonZero32(
1672                     m_out.load32(value, m_heaps.StringImpl_hashAndFlags),
1673                     m_out.constInt32(StringImpl::flagIs8Bit())),
1674                 is8Bit, is16Bit);
1675             
1676             Vector<ValueFromBlock, 2> characters;
1677             m_out.appendTo(is8Bit, is16Bit);
1678             characters.append(m_out.anchor(
1679                 m_out.zeroExt(m_out.load8(characterData, m_heaps.characters8[0]), m_out.int16)));
1680             m_out.jump(continuation);
1681             
1682             m_out.appendTo(is16Bit, continuation);
1683             characters.append(m_out.anchor(m_out.load16(characterData, m_heaps.characters16[0])));
1684             m_out.jump(continuation);
1685             
1686             m_out.appendTo(continuation, lastNext);
1687             buildSwitch(data, m_out.int16, m_out.phi(m_out.int16, characters));
1688             return;
1689         }
1690         
1691         case SwitchString:
1692             RELEASE_ASSERT_NOT_REACHED();
1693             break;
1694         }
1695         
1696         RELEASE_ASSERT_NOT_REACHED();
1697     }
1698     
1699     void compileReturn()
1700     {
1701         // FIXME: have a real epilogue when we switch to using our calling convention.
1702         // https://bugs.webkit.org/show_bug.cgi?id=113621
1703         m_out.ret(lowJSValue(m_node->child1()));
1704     }
1705     
1706     void compileForceOSRExit()
1707     {
1708         terminate(InadequateCoverage);
1709     }
1710     
1711     LValue boolify(Edge edge)
1712     {
1713         switch (edge.useKind()) {
1714         case BooleanUse:
1715             return lowBoolean(m_node->child1());
1716         case Int32Use:
1717             return m_out.notZero32(lowInt32(m_node->child1()));
1718         case NumberUse:
1719             return m_out.doubleNotEqual(lowDouble(edge), m_out.doubleZero);
1720         case ObjectOrOtherUse:
1721             return m_out.bitNot(
1722                 equalNullOrUndefined(
1723                     edge, CellCaseSpeculatesObject, SpeculateNullOrUndefined,
1724                     ManualOperandSpeculation));
1725         default:
1726             RELEASE_ASSERT_NOT_REACHED();
1727             return 0;
1728         }
1729     }
1730     
1731     enum StringOrObjectMode {
1732         AllCellsAreFalse,
1733         CellCaseSpeculatesObject
1734     };
1735     enum EqualNullOrUndefinedMode {
1736         EqualNull,
1737         EqualUndefined,
1738         EqualNullOrUndefined,
1739         SpeculateNullOrUndefined
1740     };
1741     LValue equalNullOrUndefined(
1742         Edge edge, StringOrObjectMode cellMode, EqualNullOrUndefinedMode primitiveMode,
1743         OperandSpeculationMode operandMode = AutomaticOperandSpeculation)
1744     {
1745         bool validWatchpoint = masqueradesAsUndefinedWatchpointIfIsStillValid();
1746         
1747         LValue value = lowJSValue(edge, operandMode);
1748         
1749         LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined cell case"));
1750         LBasicBlock primitiveCase = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined primitive case"));
1751         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined continuation"));
1752         
1753         m_out.branch(isNotCell(value), primitiveCase, cellCase);
1754         
1755         LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
1756         
1757         Vector<ValueFromBlock, 3> results;
1758         
1759         switch (cellMode) {
1760         case AllCellsAreFalse:
1761             break;
1762         case CellCaseSpeculatesObject:
1763             FTL_TYPE_CHECK(
1764                 jsValueValue(value), edge, (~SpecCell) | SpecObject,
1765                 m_out.equal(
1766                     m_out.loadPtr(value, m_heaps.JSCell_structure),
1767                     m_out.constIntPtr(vm().stringStructure.get())));
1768             break;
1769         }
1770         
1771         if (validWatchpoint) {
1772             results.append(m_out.anchor(m_out.booleanFalse));
1773             m_out.jump(continuation);
1774         } else {
1775             LBasicBlock masqueradesCase =
1776                 FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined masquerades case"));
1777                 
1778             LValue structure = m_out.loadPtr(value, m_heaps.JSCell_structure);
1779             
1780             results.append(m_out.anchor(m_out.booleanFalse));
1781             
1782             m_out.branch(
1783                 m_out.testNonZero8(
1784                     m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
1785                     m_out.constInt8(MasqueradesAsUndefined)),
1786                 masqueradesCase, continuation);
1787             
1788             m_out.appendTo(masqueradesCase, primitiveCase);
1789             
1790             results.append(m_out.anchor(
1791                 m_out.equal(
1792                     m_out.constIntPtr(m_graph.globalObjectFor(m_node->codeOrigin)),
1793                     m_out.loadPtr(structure, m_heaps.Structure_globalObject))));
1794             m_out.jump(continuation);
1795         }
1796         
1797         m_out.appendTo(primitiveCase, continuation);
1798         
1799         LValue primitiveResult;
1800         switch (primitiveMode) {
1801         case EqualNull:
1802             primitiveResult = m_out.equal(value, m_out.constInt64(ValueNull));
1803             break;
1804         case EqualUndefined:
1805             primitiveResult = m_out.equal(value, m_out.constInt64(ValueUndefined));
1806             break;
1807         case EqualNullOrUndefined:
1808             primitiveResult = m_out.equal(
1809                 m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
1810                 m_out.constInt64(ValueNull));
1811             break;
1812         case SpeculateNullOrUndefined:
1813             FTL_TYPE_CHECK(
1814                 jsValueValue(value), edge, SpecCell | SpecOther,
1815                 m_out.notEqual(
1816                     m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
1817                     m_out.constInt64(ValueNull)));
1818             primitiveResult = m_out.booleanTrue;
1819             break;
1820         }
1821         results.append(m_out.anchor(primitiveResult));
1822         m_out.jump(continuation);
1823         
1824         m_out.appendTo(continuation, lastNext);
1825         
1826         return m_out.phi(m_out.boolean, results);
1827     }
1828     
1829     template<typename FunctionType>
1830     void contiguousPutByValOutOfBounds(
1831         FunctionType slowPathFunction,
1832         LValue base, LValue storage, LValue index, LValue value,
1833         LBasicBlock continuation)
1834     {
1835         LValue isNotInBounds = m_out.aboveOrEqual(
1836             index, m_out.load32(storage, m_heaps.Butterfly_publicLength));
1837         if (m_node->arrayMode().isInBounds())
1838             speculate(StoreToHoleOrOutOfBounds, noValue(), 0, isNotInBounds);
1839         else {
1840             LBasicBlock notInBoundsCase =
1841                 FTL_NEW_BLOCK(m_out, ("PutByVal not in bounds"));
1842             LBasicBlock performStore =
1843                 FTL_NEW_BLOCK(m_out, ("PutByVal perform store"));
1844                 
1845             m_out.branch(isNotInBounds, notInBoundsCase, performStore);
1846                 
1847             LBasicBlock lastNext = m_out.appendTo(notInBoundsCase, performStore);
1848                 
1849             LValue isOutOfBounds = m_out.aboveOrEqual(
1850                 index, m_out.load32(storage, m_heaps.Butterfly_vectorLength));
1851                 
1852             if (!m_node->arrayMode().isOutOfBounds())
1853                 speculate(OutOfBounds, noValue(), 0, isOutOfBounds);
1854             else {
1855                 LBasicBlock outOfBoundsCase =
1856                     FTL_NEW_BLOCK(m_out, ("PutByVal out of bounds"));
1857                 LBasicBlock holeCase =
1858                     FTL_NEW_BLOCK(m_out, ("PutByVal hole case"));
1859                     
1860                 m_out.branch(isOutOfBounds, outOfBoundsCase, holeCase);
1861                     
1862                 LBasicBlock innerLastNext = m_out.appendTo(outOfBoundsCase, holeCase);
1863                     
1864                 vmCall(
1865                     m_out.operation(slowPathFunction),
1866                     m_callFrame, base, index, value);
1867                     
1868                 m_out.jump(continuation);
1869                     
1870                 m_out.appendTo(holeCase, innerLastNext);
1871             }
1872             
1873             m_out.store32(
1874                 m_out.add(index, m_out.int32One),
1875                 storage, m_heaps.Butterfly_publicLength);
1876                 
1877             m_out.jump(performStore);
1878             m_out.appendTo(performStore, lastNext);
1879         }
1880     }
1881     
1882     void buildSwitch(SwitchData* data, LType type, LValue switchValue)
1883     {
1884         Vector<SwitchCase> cases;
1885         for (unsigned i = 0; i < data->cases.size(); ++i) {
1886             cases.append(SwitchCase(
1887                 constInt(type, data->cases[i].value.switchLookupValue()),
1888                 lowBlock(data->cases[i].target)));
1889         }
1890         
1891         m_out.switchInstruction(switchValue, cases, lowBlock(data->fallThrough));
1892     }
1893     
1894     void speculateBackward(
1895         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
1896     {
1897         appendOSRExit(
1898             kind, lowValue, highValue, failCondition, BackwardSpeculation, FormattedValue());
1899     }
1900     
1901     void speculateForward(
1902         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
1903         const FormattedValue& recovery)
1904     {
1905         appendOSRExit(
1906             kind, lowValue, highValue, failCondition, ForwardSpeculation, recovery);
1907     }
1908     
1909     void speculate(
1910         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
1911     {
1912         appendOSRExit(
1913             kind, lowValue, highValue, failCondition, m_direction, FormattedValue());
1914     }
1915     
1916     void terminate(ExitKind kind)
1917     {
1918         speculate(kind, noValue(), 0, m_out.booleanTrue);
1919     }
1920     
1921     void backwardTypeCheck(
1922         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
1923         LValue failCondition)
1924     {
1925         appendTypeCheck(
1926             lowValue, highValue, typesPassedThrough, failCondition, BackwardSpeculation,
1927             FormattedValue());
1928     }
1929     
1930     void forwardTypeCheck(
1931         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
1932         LValue failCondition)
1933     {
1934         appendTypeCheck(
1935             lowValue, highValue, typesPassedThrough, failCondition, ForwardSpeculation,
1936             FormattedValue());
1937     }
1938     
1939     void typeCheck(
1940         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
1941         LValue failCondition)
1942     {
1943         appendTypeCheck(
1944             lowValue, highValue, typesPassedThrough, failCondition, m_direction,
1945             FormattedValue());
1946     }
1947     
1948     void appendTypeCheck(
1949         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
1950         LValue failCondition, SpeculationDirection direction, FormattedValue recovery)
1951     {
1952         if (!m_interpreter.needsTypeCheck(highValue, typesPassedThrough))
1953             return;
1954         ASSERT(mayHaveTypeCheck(highValue.useKind()));
1955         appendOSRExit(BadType, lowValue, highValue.node(), failCondition, direction, recovery);
1956         m_interpreter.filter(highValue, typesPassedThrough);
1957     }
1958     
1959     LValue lowInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1960     {
1961         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
1962         
1963         LoweredNodeValue value = m_int32Values.get(edge.node());
1964         if (isValid(value))
1965             return value.value();
1966         
1967         value = m_jsValueValues.get(edge.node());
1968         if (isValid(value)) {
1969             LValue boxedResult = value.value();
1970             FTL_TYPE_CHECK(
1971                 jsValueValue(boxedResult), edge, SpecInt32, isNotInt32(boxedResult));
1972             LValue result = unboxInt32(boxedResult);
1973             setInt32(edge.node(), result);
1974             return result;
1975         }
1976
1977         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt32));
1978         terminate(Uncountable);
1979         return m_out.int32Zero;
1980     }
1981     
1982     LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1983     {
1984         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind()));
1985         
1986         LoweredNodeValue value = m_jsValueValues.get(edge.node());
1987         if (isValid(value)) {
1988             LValue uncheckedValue = value.value();
1989             FTL_TYPE_CHECK(
1990                 jsValueValue(uncheckedValue), edge, SpecCell, isNotCell(uncheckedValue));
1991             return uncheckedValue;
1992         }
1993         
1994         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecCell));
1995         terminate(Uncountable);
1996         return m_out.intPtrZero;
1997     }
1998     
1999     LValue lowObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2000     {
2001         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
2002         
2003         LValue result = lowCell(edge, mode);
2004         speculateObject(edge, result);
2005         return result;
2006     }
2007     
2008     LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2009     {
2010         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringUse || edge.useKind() == KnownStringUse);
2011         
2012         LValue result = lowCell(edge, mode);
2013         speculateString(edge, result);
2014         return result;
2015     }
2016     
2017     LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2018     {
2019         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
2020         
2021         LValue result = lowCell(edge, mode);
2022         speculateNonNullObject(edge, result);
2023         return result;
2024     }
2025     
2026     LValue lowBoolean(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2027     {
2028         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
2029         
2030         LoweredNodeValue value = m_booleanValues.get(edge.node());
2031         if (isValid(value))
2032             return value.value();
2033         
2034         value = m_jsValueValues.get(edge.node());
2035         if (isValid(value)) {
2036             LValue unboxedResult = value.value();
2037             FTL_TYPE_CHECK(
2038                 jsValueValue(unboxedResult), edge, SpecBoolean, isNotBoolean(unboxedResult));
2039             LValue result = unboxBoolean(unboxedResult);
2040             setBoolean(edge.node(), result);
2041             return result;
2042         }
2043         
2044         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecBoolean));
2045         terminate(Uncountable);
2046         return m_out.booleanFalse;
2047     }
2048     
2049     LValue lowDouble(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2050     {
2051         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind()));
2052         
2053         LoweredNodeValue value = m_doubleValues.get(edge.node());
2054         if (isValid(value))
2055             return value.value();
2056         
2057         value = m_int32Values.get(edge.node());
2058         if (isValid(value)) {
2059             LValue result = m_out.intToDouble(value.value());
2060             setDouble(edge.node(), result);
2061             return result;
2062         }
2063         
2064         value = m_jsValueValues.get(edge.node());
2065         if (isValid(value)) {
2066             LValue boxedResult = value.value();
2067             
2068             LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("Double unboxing int case"));
2069             LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("Double unboxing double case"));
2070             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Double unboxing continuation"));
2071             
2072             m_out.branch(isNotInt32(boxedResult), doubleCase, intCase);
2073             
2074             LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
2075             
2076             ValueFromBlock intToDouble = m_out.anchor(
2077                 m_out.intToDouble(unboxInt32(boxedResult)));
2078             m_out.jump(continuation);
2079             
2080             m_out.appendTo(doubleCase, continuation);
2081             
2082             FTL_TYPE_CHECK(
2083                 jsValueValue(boxedResult), edge, SpecNumber, isCellOrMisc(boxedResult));
2084             
2085             ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedResult));
2086             m_out.jump(continuation);
2087             
2088             m_out.appendTo(continuation, lastNext);
2089             
2090             LValue result = m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
2091             
2092             setDouble(edge.node(), result);
2093             return result;
2094         }
2095         
2096         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecNumber));
2097         terminate(Uncountable);
2098         return m_out.doubleZero;
2099     }
2100     
2101     LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2102     {
2103         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
2104         
2105         LoweredNodeValue value = m_jsValueValues.get(edge.node());
2106         if (isValid(value))
2107             return value.value();
2108         
2109         value = m_int32Values.get(edge.node());
2110         if (isValid(value)) {
2111             LValue result = boxInt32(value.value());
2112             setJSValue(edge.node(), result);
2113             return result;
2114         }
2115         
2116         value = m_booleanValues.get(edge.node());
2117         if (isValid(value)) {
2118             LValue result = boxBoolean(value.value());
2119             setJSValue(edge.node(), result);
2120             return result;
2121         }
2122         
2123         value = m_doubleValues.get(edge.node());
2124         if (isValid(value)) {
2125             LValue result = boxDouble(value.value());
2126             setJSValue(edge.node(), result);
2127             return result;
2128         }
2129         
2130         RELEASE_ASSERT_NOT_REACHED();
2131         return 0;
2132     }
2133     
2134     LValue lowStorage(Edge edge)
2135     {
2136         LoweredNodeValue value = m_storageValues.get(edge.node());
2137         if (isValid(value))
2138             return value.value();
2139         
2140         LValue result = lowCell(edge);
2141         setStorage(edge.node(), result);
2142         return result;
2143     }
2144     
2145     LValue isNotInt32(LValue jsValue)
2146     {
2147         return m_out.below(jsValue, m_tagTypeNumber);
2148     }
2149     LValue unboxInt32(LValue jsValue)
2150     {
2151         return m_out.castToInt32(jsValue);
2152     }
2153     LValue boxInt32(LValue value)
2154     {
2155         return m_out.add(m_out.zeroExt(value, m_out.int64), m_tagTypeNumber);
2156     }
2157     
2158     LValue isCellOrMisc(LValue jsValue)
2159     {
2160         return m_out.testIsZero64(jsValue, m_tagTypeNumber);
2161     }
2162     LValue unboxDouble(LValue jsValue)
2163     {
2164         return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType);
2165     }
2166     LValue boxDouble(LValue doubleValue)
2167     {
2168         return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber);
2169     }
2170     
2171     LValue isNotCell(LValue jsValue)
2172     {
2173         return m_out.testNonZero64(jsValue, m_tagMask);
2174     }
2175     
2176     LValue isNotBoolean(LValue jsValue)
2177     {
2178         return m_out.testNonZero64(
2179             m_out.bitXor(jsValue, m_out.constInt64(ValueFalse)),
2180             m_out.constInt64(~1));
2181     }
2182     LValue unboxBoolean(LValue jsValue)
2183     {
2184         // We want to use a cast that guarantees that LLVM knows that even the integer
2185         // value is just 0 or 1. But for now we do it the dumb way.
2186         return m_out.notZero64(m_out.bitAnd(jsValue, m_out.constInt64(1)));
2187     }
2188     LValue boxBoolean(LValue value)
2189     {
2190         return m_out.select(
2191             value, m_out.constInt64(ValueTrue), m_out.constInt64(ValueFalse));
2192     }
2193
2194     void speculate(Edge edge)
2195     {
2196         switch (edge.useKind()) {
2197         case UntypedUse:
2198             break;
2199         case KnownInt32Use:
2200         case KnownNumberUse:
2201             ASSERT(!m_interpreter.needsTypeCheck(edge));
2202             break;
2203         case Int32Use:
2204             speculateInt32(edge);
2205             break;
2206         case CellUse:
2207             speculateCell(edge);
2208             break;
2209         case KnownCellUse:
2210             ASSERT(!m_interpreter.needsTypeCheck(edge));
2211             break;
2212         case ObjectUse:
2213             speculateObject(edge);
2214             break;
2215         case StringUse:
2216             speculateString(edge);
2217             break;
2218         case RealNumberUse:
2219             speculateRealNumber(edge);
2220             break;
2221         case NumberUse:
2222             speculateNumber(edge);
2223             break;
2224         case BooleanUse:
2225             speculateBoolean(edge);
2226             break;
2227         default:
2228             RELEASE_ASSERT_NOT_REACHED();
2229         }
2230     }
2231     
2232     void speculate(Node*, Edge edge)
2233     {
2234         speculate(edge);
2235     }
2236     
2237     void speculateInt32(Edge edge)
2238     {
2239         lowInt32(edge);
2240     }
2241     
2242     void speculateCell(Edge edge)
2243     {
2244         lowCell(edge);
2245     }
2246     
2247     LValue isObject(LValue cell)
2248     {
2249         return m_out.notEqual(
2250             m_out.loadPtr(cell, m_heaps.JSCell_structure),
2251             m_out.constIntPtr(vm().stringStructure.get()));
2252     }
2253     
2254     LValue isNotString(LValue cell)
2255     {
2256         return isObject(cell);
2257     }
2258     
2259     LValue isString(LValue cell)
2260     {
2261         return m_out.equal(
2262             m_out.loadPtr(cell, m_heaps.JSCell_structure),
2263             m_out.constIntPtr(vm().stringStructure.get()));
2264     }
2265     
2266     LValue isNotObject(LValue cell)
2267     {
2268         return isString(cell);
2269     }
2270     
2271     void speculateObject(Edge edge, LValue cell)
2272     {
2273         FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecObject, isNotObject(cell));
2274     }
2275     
2276     void speculateObject(Edge edge)
2277     {
2278         speculateObject(edge, lowCell(edge));
2279     }
2280     
2281     void speculateString(Edge edge, LValue cell)
2282     {
2283         FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecString, isNotString(cell));
2284     }
2285     
2286     void speculateString(Edge edge)
2287     {
2288         speculateString(edge, lowCell(edge));
2289     }
2290     
2291     void speculateNonNullObject(Edge edge, LValue cell)
2292     {
2293         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
2294         FTL_TYPE_CHECK(
2295             jsValueValue(cell), edge, SpecObject, 
2296             m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())));
2297         if (masqueradesAsUndefinedWatchpointIfIsStillValid())
2298             return;
2299         
2300         speculate(
2301             BadType, jsValueValue(cell), edge.node(),
2302             m_out.testNonZero8(
2303                 m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
2304                 m_out.constInt8(MasqueradesAsUndefined)));
2305     }
2306     
2307     void speculateNumber(Edge edge)
2308     {
2309         // Do an early return here because lowDouble() can create a lot of control flow.
2310         if (!m_interpreter.needsTypeCheck(edge))
2311             return;
2312         
2313         lowDouble(edge);
2314     }
2315     
2316     void speculateRealNumber(Edge edge)
2317     {
2318         // Do an early return here because lowDouble() can create a lot of control flow.
2319         if (!m_interpreter.needsTypeCheck(edge))
2320             return;
2321         
2322         LValue value = lowDouble(edge);
2323         FTL_TYPE_CHECK(
2324             doubleValue(value), edge, SpecRealNumber,
2325             m_out.doubleNotEqualOrUnordered(value, value));
2326     }
2327     
2328     void speculateBoolean(Edge edge)
2329     {
2330         lowBoolean(edge);
2331     }
2332
2333     bool masqueradesAsUndefinedWatchpointIsStillValid()
2334     {
2335         return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->codeOrigin);
2336     }
2337     
2338     bool masqueradesAsUndefinedWatchpointIfIsStillValid()
2339     {
2340         if (!masqueradesAsUndefinedWatchpointIsStillValid())
2341             return false;
2342         
2343         // FIXME: Implement masquerades-as-undefined watchpoints.
2344         // https://bugs.webkit.org/show_bug.cgi?id=113647
2345         return true;
2346     }
2347     
2348     enum ExceptionCheckMode { NoExceptions, CheckExceptions };
2349     
2350     LValue vmCall(LValue function, ExceptionCheckMode mode = CheckExceptions)
2351     {
2352         callPreflight();
2353         LValue result = m_out.call(function);
2354         callCheck(mode);
2355         return result;
2356     }
2357     LValue vmCall(LValue function, LValue arg1, ExceptionCheckMode mode = CheckExceptions)
2358     {
2359         callPreflight();
2360         LValue result = m_out.call(function, arg1);
2361         callCheck(mode);
2362         return result;
2363     }
2364     LValue vmCall(LValue function, LValue arg1, LValue arg2, ExceptionCheckMode mode = CheckExceptions)
2365     {
2366         callPreflight();
2367         LValue result = m_out.call(function, arg1, arg2);
2368         callCheck(mode);
2369         return result;
2370     }
2371     LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, ExceptionCheckMode mode = CheckExceptions)
2372     {
2373         callPreflight();
2374         LValue result = m_out.call(function, arg1, arg2, arg3);
2375         callCheck(mode);
2376         return result;
2377     }
2378     LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, ExceptionCheckMode mode = CheckExceptions)
2379     {
2380         callPreflight();
2381         LValue result = m_out.call(function, arg1, arg2, arg3, arg4);
2382         callCheck(mode);
2383         return result;
2384     }
2385     
2386     void callPreflight(CodeOrigin codeOrigin)
2387     {
2388         m_out.store32(
2389             m_out.constInt32(
2390                 CallFrame::Location::encodeAsCodeOriginIndex(
2391                     codeBlock()->addCodeOrigin(codeOrigin))), 
2392             tagFor(JSStack::ArgumentCount));
2393     }
2394     void callPreflight()
2395     {
2396         callPreflight(m_node->codeOrigin);
2397     }
2398     
2399     void callCheck(ExceptionCheckMode mode = CheckExceptions)
2400     {
2401         if (mode == NoExceptions)
2402             return;
2403         
2404         LBasicBlock didHaveException = FTL_NEW_BLOCK(m_out, ("Did have exception"));
2405         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Exception check continuation"));
2406         
2407         m_out.branch(
2408             m_out.notZero64(m_out.load64(m_out.absolute(vm().addressOfException()))),
2409             didHaveException, continuation);
2410         
2411         LBasicBlock lastNext = m_out.appendTo(didHaveException, continuation);
2412         // FIXME: Handle exceptions. https://bugs.webkit.org/show_bug.cgi?id=113622
2413         m_out.crash();
2414         
2415         m_out.appendTo(continuation, lastNext);
2416     }
2417     
2418     bool isLive(Node* node)
2419     {
2420         return m_live.contains(node);
2421     }
2422     
2423     void use(Edge edge)
2424     {
2425         ASSERT(edge->hasResult());
2426         if (!edge.doesKill())
2427             return;
2428         m_live.remove(edge.node());
2429     }
2430     
2431     // Wrapper used only for DFG_NODE_DO_TO_CHILDREN
2432     void use(Node*, Edge edge)
2433     {
2434         use(edge);
2435     }
2436     
2437     LBasicBlock lowBlock(BasicBlock* block)
2438     {
2439         return m_blocks.get(block);
2440     }
2441     
2442     void initializeOSRExitStateForBlock()
2443     {
2444         for (unsigned i = m_valueSources.size(); i--;) {
2445             FlushFormat format = m_highBlock->ssa->flushFormatAtHead[i];
2446             switch (format) {
2447             case DeadFlush: {
2448                 // Must consider available nodes instead.
2449                 Node* node = m_highBlock->ssa->availabilityAtHead[i];
2450                 if (!node) {
2451                     m_valueSources[i] = ValueSource(SourceIsDead);
2452                     break;
2453                 }
2454                 
2455                 m_valueSources[i] = ValueSource(node);
2456                 break;
2457             }
2458                 
2459             case FlushedInt32:
2460                 m_valueSources[i] = ValueSource(Int32InJSStack);
2461                 break;
2462                 
2463             case FlushedDouble:
2464                 m_valueSources[i] = ValueSource(DoubleInJSStack);
2465                 break;
2466                 
2467             case FlushedCell:
2468             case FlushedBoolean:
2469             case FlushedJSValue:
2470                 m_valueSources[i] = ValueSource(ValueInJSStack);
2471                 break;
2472             }
2473         }
2474     }
2475     
2476     void appendOSRExit(
2477         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
2478         SpeculationDirection direction, FormattedValue recovery)
2479     {
2480         if (Options::ftlTrapsOnOSRExit()) {
2481             LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("OSR exit failCase for ", m_node));
2482             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("OSR exit continuation for ", m_node));
2483             
2484             m_out.branch(failCondition, failCase, continuation);
2485             
2486             LBasicBlock lastNext = m_out.appendTo(failCase, continuation);
2487             m_out.trap();
2488             m_out.unreachable();
2489             
2490             m_out.appendTo(continuation, lastNext);
2491             return;
2492         }
2493         
2494         if (verboseCompilationEnabled())
2495             dataLog("    OSR exit with value sources: ", m_valueSources, "\n");
2496         
2497         ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.osrExit.size());
2498         unsigned index = m_ftlState.osrExit.size();
2499         
2500         m_ftlState.jitCode->osrExit.append(OSRExit(
2501             kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
2502             m_codeOriginForExitTarget, m_codeOriginForExitProfile, m_lastSetOperand,
2503             m_valueSources.numberOfArguments(), m_valueSources.numberOfLocals()));
2504         m_ftlState.osrExit.append(OSRExitCompilationInfo());
2505         
2506         OSRExit& exit = m_ftlState.jitCode->osrExit.last();
2507         OSRExitCompilationInfo& info = m_ftlState.osrExit.last();
2508
2509         LBasicBlock lastNext = 0;
2510         LBasicBlock continuation = 0;
2511         
2512         if (!Options::useLLVMOSRExitIntrinsic()) {
2513             LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("OSR exit failCase for ", m_node));
2514             continuation = FTL_NEW_BLOCK(m_out, ("OSR exit continuation for ", m_node));
2515             
2516             m_out.branch(failCondition, failCase, continuation);
2517
2518             m_out.appendTo(m_prologue);
2519             info.m_thunkAddress = buildAlloca(m_out.m_builder, m_out.intPtr);
2520         
2521             lastNext = m_out.appendTo(failCase, continuation);
2522         }
2523         
2524         if (Options::ftlOSRExitOmitsMarshalling()) {
2525             m_out.call(
2526                 m_out.intToPtr(
2527                     m_out.get(info.m_thunkAddress),
2528                     pointerType(functionType(m_out.voidType))));
2529         } else
2530             emitOSRExitCall(failCondition, index, exit, info, lowValue, direction, recovery);
2531         
2532         if (!Options::useLLVMOSRExitIntrinsic()) {
2533             m_out.unreachable();
2534             
2535             m_out.appendTo(continuation, lastNext);
2536         
2537             m_exitThunkGenerator.emitThunk(index);
2538         }
2539     }
2540     
2541     void emitOSRExitCall(
2542         LValue failCondition, unsigned index, OSRExit& exit, OSRExitCompilationInfo& info,
2543         FormattedValue lowValue, SpeculationDirection direction, FormattedValue recovery)
2544     {
2545         ExitArgumentList arguments;
2546         
2547         if (Options::useLLVMOSRExitIntrinsic()) {
2548             arguments.append(failCondition);
2549             arguments.append(m_out.constInt32(index));
2550         }
2551         
2552         arguments.append(m_callFrame);
2553         if (!!lowValue)
2554             arguments.append(lowValue.value());
2555         
2556         for (unsigned i = 0; i < exit.m_values.size(); ++i) {
2557             ValueSource source = m_valueSources[i];
2558             
2559             switch (source.kind()) {
2560             case ValueInJSStack:
2561                 exit.m_values[i] = ExitValue::inJSStack();
2562                 break;
2563             case Int32InJSStack:
2564                 exit.m_values[i] = ExitValue::inJSStackAsInt32();
2565                 break;
2566             case DoubleInJSStack:
2567                 exit.m_values[i] = ExitValue::inJSStackAsDouble();
2568                 break;
2569             case SourceIsDead:
2570                 exit.m_values[i] = ExitValue::dead();
2571                 break;
2572             case HaveNode:
2573                 addExitArgumentForNode(exit, arguments, i, source.node());
2574                 break;
2575             default:
2576                 RELEASE_ASSERT_NOT_REACHED();
2577                 break;
2578             }
2579         }
2580         
2581         if (verboseCompilationEnabled())
2582             dataLog("        Exit values: ", exit.m_values, "\n");
2583         
2584         if (direction == ForwardSpeculation) {
2585             ASSERT(m_node);
2586             exit.convertToForward(m_highBlock, m_node, m_nodeIndex, recovery, arguments);
2587         }
2588         
2589         // So, the really lame thing here is that we have to build an LLVM function type.
2590         // Booo.
2591         Vector<LType, 16> argumentTypes;
2592         for (unsigned i = 0; i < arguments.size(); ++i)
2593             argumentTypes.append(typeOf(arguments[i]));
2594         
2595         if (Options::useLLVMOSRExitIntrinsic()) {
2596             m_out.call(m_out.osrExitIntrinsic(), arguments);
2597             return;
2598         }
2599         
2600         m_out.call(
2601             m_out.intToPtr(
2602                 m_out.get(info.m_thunkAddress),
2603                 pointerType(functionType(m_out.voidType, argumentTypes))),
2604             arguments);
2605     }
2606     
2607     void addExitArgumentForNode(
2608         OSRExit& exit, ExitArgumentList& arguments, unsigned index, Node* node)
2609     {
2610         ASSERT(node->shouldGenerate());
2611         ASSERT(node->hasResult());
2612
2613         if (tryToSetConstantExitArgument(exit, index, node))
2614             return;
2615         
2616         if (!isLive(node)) {
2617             bool found = false;
2618             
2619             if (needsOSRBackwardRewiring(node->op())) {
2620                 node = node->child1().node();
2621                 if (tryToSetConstantExitArgument(exit, index, node))
2622                     return;
2623                 if (isLive(node))
2624                     found = true;
2625             }
2626             
2627             if (!found) {
2628                 Node* int32ToDouble = 0;
2629                 Node* valueToInt32 = 0;
2630                 Node* uint32ToNumber = 0;
2631                 Node* doubleAsInt32 = 0;
2632                 
2633                 HashSet<Node*>::iterator iter = m_live.begin();
2634                 HashSet<Node*>::iterator end = m_live.end();
2635                 for (; iter != end; ++iter) {
2636                     Node* candidate = *iter;
2637                     if (!candidate->child1())
2638                         continue;
2639                     if (candidate->child1() != node)
2640                         continue;
2641                     switch (candidate->op()) {
2642                     case Int32ToDouble:
2643                         int32ToDouble = candidate;
2644                         break;
2645                     case ValueToInt32:
2646                         valueToInt32 = candidate;
2647                         break;
2648                     case UInt32ToNumber:
2649                         uint32ToNumber = candidate;
2650                         break;
2651                     case DoubleAsInt32:
2652                         uint32ToNumber = candidate;
2653                         break;
2654                     default:
2655                         ASSERT(!needsOSRForwardRewiring(candidate->op()));
2656                         break;
2657                     }
2658                 }
2659                 
2660                 if (doubleAsInt32)
2661                     node = doubleAsInt32;
2662                 else if (int32ToDouble)
2663                     node = int32ToDouble;
2664                 else if (valueToInt32)
2665                     node = valueToInt32;
2666                 else if (uint32ToNumber)
2667                     node = uint32ToNumber;
2668                 
2669                 if (isLive(node))
2670                     found = true;
2671             }
2672             
2673             if (!found) {
2674                 exit.m_values[index] = ExitValue::dead();
2675                 return;
2676             }
2677         }
2678         
2679         ASSERT(isLive(node));
2680
2681         LoweredNodeValue value = m_int32Values.get(node);
2682         if (isValid(value)) {
2683             addExitArgument(exit, arguments, index, ValueFormatInt32, value.value());
2684             return;
2685         }
2686         
2687         value = m_booleanValues.get(node);
2688         if (isValid(value)) {
2689             addExitArgument(exit, arguments, index, ValueFormatBoolean, value.value());
2690             return;
2691         }
2692         
2693         value = m_jsValueValues.get(node);
2694         if (isValid(value)) {
2695             addExitArgument(exit, arguments, index, ValueFormatJSValue, value.value());
2696             return;
2697         }
2698         
2699         value = m_doubleValues.get(node);
2700         if (isValid(value)) {
2701             addExitArgument(exit, arguments, index, ValueFormatDouble, value.value());
2702             return;
2703         }
2704
2705         dataLog("Cannot find value for node: ", node, "\n");
2706         RELEASE_ASSERT_NOT_REACHED();
2707     }
2708     
2709     bool tryToSetConstantExitArgument(OSRExit& exit, unsigned index, Node* node)
2710     {
2711         if (!node)
2712             return false;
2713         
2714         switch (node->op()) {
2715         case JSConstant:
2716         case WeakJSConstant:
2717             exit.m_values[index] = ExitValue::constant(m_graph.valueOfJSConstant(node));
2718             return true;
2719         case PhantomArguments:
2720             // FIXME: implement PhantomArguments.
2721             // https://bugs.webkit.org/show_bug.cgi?id=113986
2722             RELEASE_ASSERT_NOT_REACHED();
2723             return true;
2724         default:
2725             return false;
2726         }
2727     }
2728     
2729     void addExitArgument(
2730         OSRExit& exit, ExitArgumentList& arguments, unsigned index, ValueFormat format,
2731         LValue value)
2732     {
2733         exit.m_values[index] = ExitValue::exitArgument(ExitArgument(format, arguments.size()));
2734         arguments.append(value);
2735     }
2736     
2737     void linkOSRExitsAndCompleteInitializationBlocks()
2738     {
2739         MacroAssemblerCodeRef osrExitThunk =
2740             vm().getCTIStub(osrExitGenerationThunkGenerator);
2741         CodeLocationLabel target = CodeLocationLabel(osrExitThunk.code());
2742         
2743         m_out.appendTo(m_prologue);
2744         m_out.jump(m_initialization);
2745         
2746         m_out.appendTo(m_initialization);
2747         
2748         if (m_exitThunkGenerator.didThings()) {
2749             OwnPtr<LinkBuffer> linkBuffer = adoptPtr(new LinkBuffer(
2750                 vm(), &m_exitThunkGenerator, m_ftlState.graph.m_codeBlock,
2751                 JITCompilationMustSucceed));
2752         
2753             ASSERT(m_ftlState.osrExit.size() == m_ftlState.jitCode->osrExit.size());
2754         
2755             for (unsigned i = 0; i < m_ftlState.osrExit.size(); ++i) {
2756                 OSRExitCompilationInfo& info = m_ftlState.osrExit[i];
2757                 OSRExit& exit = m_ftlState.jitCode->osrExit[i];
2758             
2759                 linkBuffer->link(info.m_thunkJump, target);
2760             
2761                 m_out.set(
2762                     m_out.constIntPtr(
2763                         linkBuffer->locationOf(info.m_thunkLabel).executableAddress()),
2764                     info.m_thunkAddress);
2765             
2766                 exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump);
2767             }
2768         
2769             m_ftlState.finalizer->initializeExitThunksLinkBuffer(linkBuffer.release());
2770         }
2771
2772         m_out.jump(lowBlock(m_graph.block(0)));
2773     }
2774     
2775     void observeMovHint(Node* node)
2776     {
2777         ASSERT(node->containsMovHint());
2778         ASSERT(node->op() != ZombieHint);
2779         
2780         int operand = node->local();
2781         
2782         m_lastSetOperand = operand;
2783         m_valueSources.operand(operand) = ValueSource(node->child1().node());
2784     }
2785     
2786     void setInt32(Node* node, LValue value)
2787     {
2788         m_int32Values.set(node, LoweredNodeValue(value, m_highBlock));
2789     }
2790     void setJSValue(Node* node, LValue value)
2791     {
2792         m_jsValueValues.set(node, LoweredNodeValue(value, m_highBlock));
2793     }
2794     void setBoolean(Node* node, LValue value)
2795     {
2796         m_booleanValues.set(node, LoweredNodeValue(value, m_highBlock));
2797     }
2798     void setStorage(Node* node, LValue value)
2799     {
2800         m_storageValues.set(node, LoweredNodeValue(value, m_highBlock));
2801     }
2802     void setDouble(Node* node, LValue value)
2803     {
2804         m_doubleValues.set(node, LoweredNodeValue(value, m_highBlock));
2805     }
2806
2807     void setInt32(LValue value)
2808     {
2809         setInt32(m_node, value);
2810     }
2811     void setJSValue(LValue value)
2812     {
2813         setJSValue(m_node, value);
2814     }
2815     void setBoolean(LValue value)
2816     {
2817         setBoolean(m_node, value);
2818     }
2819     void setStorage(LValue value)
2820     {
2821         setStorage(m_node, value);
2822     }
2823     void setDouble(LValue value)
2824     {
2825         setDouble(m_node, value);
2826     }
2827     
2828     bool isValid(const LoweredNodeValue& value)
2829     {
2830         if (!value)
2831             return false;
2832         if (!m_graph.m_dominators.dominates(value.block(), m_highBlock))
2833             return false;
2834         return true;
2835     }
2836     
2837     void addWeakReference(JSCell* target)
2838     {
2839         m_graph.m_plan.weakReferences.addLazily(target);
2840     }
2841     
2842     LValue weakPointer(JSCell* pointer)
2843     {
2844         addWeakReference(pointer);
2845         return m_out.constIntPtr(pointer);
2846     }
2847     
2848     TypedPointer addressFor(LValue base, int operand, ptrdiff_t offset = 0)
2849     {
2850         return m_out.address(base, m_heaps.variables[operand], offset);
2851     }
2852     TypedPointer payloadFor(LValue base, int operand)
2853     {
2854         return addressFor(base, operand, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
2855     }
2856     TypedPointer tagFor(LValue base, int operand)
2857     {
2858         return addressFor(base, operand, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
2859     }
2860     TypedPointer addressFor(int operand)
2861     {
2862         return addressFor(m_callFrame, operand);
2863     }
2864     TypedPointer payloadFor(int operand)
2865     {
2866         return payloadFor(m_callFrame, operand);
2867     }
2868     TypedPointer tagFor(int operand)
2869     {
2870         return tagFor(m_callFrame, operand);
2871     }
2872     
2873     VM& vm() { return m_graph.m_vm; }
2874     CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
2875     
2876     Graph& m_graph;
2877     State& m_ftlState;
2878     AbstractHeapRepository m_heaps;
2879     Output m_out;
2880     
2881     LBasicBlock m_prologue;
2882     LBasicBlock m_initialization;
2883     HashMap<BasicBlock*, LBasicBlock> m_blocks;
2884     
2885     LValue m_callFrame;
2886     LValue m_tagTypeNumber;
2887     LValue m_tagMask;
2888     
2889     HashMap<Node*, LoweredNodeValue> m_int32Values;
2890     HashMap<Node*, LoweredNodeValue> m_jsValueValues;
2891     HashMap<Node*, LoweredNodeValue> m_booleanValues;
2892     HashMap<Node*, LoweredNodeValue> m_storageValues;
2893     HashMap<Node*, LoweredNodeValue> m_doubleValues;
2894     HashSet<Node*> m_live;
2895     
2896     HashMap<Node*, LValue> m_phis;
2897     
2898     Operands<ValueSource> m_valueSources;
2899     int m_lastSetOperand;
2900     ExitThunkGenerator m_exitThunkGenerator;
2901     
2902     InPlaceAbstractState m_state;
2903     AbstractInterpreter<InPlaceAbstractState> m_interpreter;
2904     BasicBlock* m_highBlock;
2905     BasicBlock* m_nextHighBlock;
2906     LBasicBlock m_nextLowBlock;
2907     
2908     CodeOrigin m_codeOriginForExitTarget;
2909     CodeOrigin m_codeOriginForExitProfile;
2910     unsigned m_nodeIndex;
2911     Node* m_node;
2912     SpeculationDirection m_direction;
2913 };
2914
2915 void lowerDFGToLLVM(State& state)
2916 {
2917     LowerDFGToLLVM lowering(state);
2918     lowering.lower();
2919 }
2920
2921 } } // namespace JSC::FTL
2922
2923 #endif // ENABLE(FTL_JIT)
2924